📄 pegwit.c
字号:
if (v[0] == 0) v[1] = 0;
key[j] = (byte)v[1];
vlShortRshift (v, 8);
}
}
void increment( squareBlock iv )
{
int i = 0;
while (iv[i]==0xff) iv[i++] = 0;
iv[i] += 1;
}
int sym_encrypt( vlPoint secret, FILE * f_inp, FILE * f_out )
{
squareBlock key,iv;
squareCtsContext ctx;
big_buf buffer;
int n,err = 0;
byte pad;
memset( iv, 0, sizeof(iv) );
vlong_to_square_block (secret, key);
squareCtsInit( &ctx, key );
pad = 0;
while (n = fread( buffer, 1, BIG_BLOCK_SIZE, f_inp ) )
{
if ( n < BIG_BLOCK_SIZE )
{
pad = 0;
if (n<BPB)
pad = 17-n;
else if (n&1)
pad = 2;
memset( n+(byte*)buffer, pad, pad );
n += pad;
}
squareCtsSetIV( &ctx, iv );
increment(iv);
squareCtsEncrypt( &ctx, (byte*)buffer, n );
{
int written = fwritePlus( buffer,1,n,f_out );
if ( written != n )
{
fputs( err_output, stderr );
err = 1;
break;
}
}
}
squareCtsFinal( &ctx );
memset( key, 0, sizeof(key) );
return err;
}
int sym_decrypt( vlPoint secret, FILE * f_inp, FILE * f_out)
{
squareBlock key,iv;
big_buf b1,b2;
byte * buf1 = (byte*)b1, * buf2 = (byte*)b2;
squareCtsContext ctx;
int err = 0, n = 0;
memset(iv,0,sizeof(iv));
vlong_to_square_block( secret, key );
squareCtsInit( &ctx, key );
while (1)
{
int i = 0;
if ( n == 0 || n == BIG_BLOCK_SIZE )
i = freadPlus( buf1, 1, BIG_BLOCK_SIZE, f_inp );
if (n)
{
if ( n < BPB )
{
decrypt_error:
fputs( err_decrypt, stderr );
err = 1;
break;
}
if ( i == 1 )
{
n += 1;
buf2[BIG_BLOCK_SIZE] = buf1[0];
i = 0;
}
squareCtsSetIV( &ctx, iv );
increment( iv );
squareCtsDecrypt( &ctx, buf2, n );
if ( n & 1 )
{
byte pad = buf2[n-1];
/* Check pad bytes are as expected */
if ( pad < 1 || pad > BPB ) goto decrypt_error;
n -= pad;
{
int j;
for (j=0;j<pad;j+=1)
if ( buf2[n+j] != pad ) goto decrypt_error;
}
}
{
int written = fwrite( buf2, 1, n, f_out );
if ( written != n )
{
fputs( err_output, stderr );
err = 1;
break;
}
}
}
if ( i == 0 ) break;
{ byte * tmp = buf1; buf1=buf2; buf2 = tmp; } /* swap */
n = i;
}
memset( key, 0, sizeof(key) );
squareCtsFinal( &ctx );
return err;
}
int do_operation( FILE * f_key, FILE * f_inp, FILE * f_out, FILE * f_sec, int operation )
{
prng p;
vlPoint pub,secret,session,mac,msg;
cpPair sig;
int err = 0;
/* Initialise the prng and calculate keys */
prng_init( &p );
if ( operation == 'v' || operation == 'e' || 'V' == operation ) /* public key operations */
{
get_vlong( f_key, pub ); /* should be a validity check here */
if ( operation == 'e' )
{
if ( f_sec ) prng_set_secret( &p, f_sec );
prng_set_mac( &p, f_inp, 1 );
}
}
else
{
setbuf(f_key,0); /* intention is to help security */
prng_set_secret( &p, f_key );
if ( operation == 'E' || operation == 'D' )
hash_to_vlong( p.seed+1, secret );
else
prng_to_vlong( &p, secret );
}
if ( operation == 's' || operation == 'v' )
{
prng_set_mac( &p, f_inp, 2 );
hash_to_vlong( p.seed+1+HW, mac );
}
if('S' == operation)
{
clearsign( &p, f_inp, f_out );
hash_to_vlong( p.seed+1+HW, mac );
}
if('V' == operation)
{
if ( readsign( &p, f_inp, f_out ) )
return 2; /* header not found */
hash_to_vlong( p.seed+1+HW, mac );
}
/* Do operation */
if ( operation == 'E' )
{
if(stdout == f_out) fputs(begin_clearsign,f_out);
err = sym_encrypt( secret, f_inp, f_out );
if(stdout == f_out)
{
if(!flushArmour(f_out)) return 3;
fputs(end_ckarmour, f_out);
}
}
else if ( operation == 'D' )
{
if(stdin == f_inp) if(!position(f_inp)) return 2;
err = sym_decrypt( secret, f_inp, f_out );
}
else
{
gfInit();
if ( operation == 'i' )
{
cpMakePublicKey( pub, secret );
fputs( pubkey_magic, f_out);
put_vlong( pub );
}
else if ( operation == 'e' )
{
if(stdout == f_out) fputs(begin_clearsign,f_out);
prng_set_time( &p );
prng_to_vlong( &p, session );
cpEncodeSecret( pub, msg, session );
put_binary_vlong( f_out, msg );
err = sym_encrypt( session, f_inp, f_out );
if(stdout == f_out)
{
if(!flushArmour(f_out)) return 3;
fputs(end_pkarmour, f_out);
}
}
else if ( operation == 'd')
{
if(stdin == f_inp) if(!position(f_inp)) return 2;
get_binary_vlong( f_inp, msg );
cpDecodeSecret( secret, msg, session );
err = sym_decrypt( session, f_inp, f_out );
}
else if ( operation == 's' || 'S' == operation)
{
do
{
prng_to_vlong( &p, session );
cpSign( secret, session, mac, &sig );
} while ( sig.r[0] == 0 );
put_vlong( sig.s );
if('S' == operation) fputs("\n", f_out); /* avoid word wrap */
else fputs( ":", f_out );
put_vlong( sig.r );
if('S' == operation) fputs("\n", f_out); /* avoid word wrap */
}
else
{
if('v' == operation)
{
get_vlong( f_sec, sig.s );
get_vlong( f_sec, sig.r );
}
else /* if( 'V' == operation) */
{
get_vlong_a( f_inp, sig.s );
get_vlong_a( f_inp, sig.r );
}
err = !cpVerify( pub, mac, &sig );
if (err)
fputs( err_signature, stderr );
}
gfQuit();
}
fflush(f_out);
/* burn sensistive information */
prng_init( &p );
vlClear( secret );
vlClear( session );
return err;
}
FILE * chkopen( char * s, char * mode )
{
FILE * result = fopen(s,mode);
if (!result)
{
fputs( err_open_failed, stderr );
fputs( s, stderr );
}
return result;
}
void burn_stack(void)
{
/* just in case any local burn code has been forgotten */
/* size is just a fairly conservative guess */
unsigned char x [ 20000 ];
memset( x, 0, sizeof(x) );
}
#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#if defined(_M_IX86) || defined(_M_I86) || defined(__alpha)
#define LITTLE_ENDIAN
#else
#error "LITTLE_ENDIAN or BIG_ENDIAN must be defined"
#endif
#endif
int main( unsigned argc, char * argv[] )
{
int err, operation, filter=0;
unsigned expect, arg_ix;
FILE * f_key, * f_inp, * f_out, *f_sec;
char openForRead [3] = "rb";
char openForWrite [3] = "wb";
char openKey[3] = "rb";
static byte x[4] = {1,2,3,4};
#ifdef LITTLE_ENDIAN
if ( *(word32*)x != 0x04030201 )
{
fputs( "Porting error : need to define BIG_ENDIAN instead of LITTLE_ENDIAN\n", stderr );
return 1;
}
#else
if ( *(word32*)x != 0x01020304 )
{
fputs( "Porting error : need to define LITTLE_ENDIAN instead of BIG_ENDIAN\n", stderr );
return 1;
}
#endif
if ( argc<2 || argv[1][0] != '-')
{
error:
if(filter) goto filterError;
fputs( manual, stderr );
/* gfSelfTest(100);
ecSelfTest(100);*/
return 1;
}
operation = argv[1][1];
if('f' == operation)
{
filter=1;
operation = argv[1][2];
if(0 == argv[1][2])
{
filterError:
fputs(filterManual, stderr);
return 1;
}
if (0 != argv[1][3]) goto error;
}
else if (argv[1][2] != 0 ) goto error;
/* Check the number of arguments */
expect = 0;
if(!filter)
{
if ( operation == 'i' ) expect = 2;
else if ( operation == 's' || 'S' == operation ) expect = 3;
else if ( operation == 'd' || operation == 'v' || 'V' == operation ||
operation == 'D' || operation == 'E' ) expect = 4;
else if ( operation == 'e' ) expect = 5;
}
else
{
if('V' == operation || 'S' == operation || 'E' == operation ||
'D' == operation || 'd' == operation ) expect = 3;
else if ('e' == operation) expect = 4;
}
if ( argc != expect ) goto error;
arg_ix = 2;
f_key = stdin;
if ( operation == 'e' || operation == 'v' || 'V' == operation || filter )
{
unsigned i, isPub = 1;
if('S' == operation || 'd' == operation) openKey[1] = 0;
f_key = chkopen( argv[arg_ix++], openKey );
if (!f_key) return 1;
if(filter && 'e' != operation && 'V' != operation) isPub = 0;
for (i=0;isPub && pubkey_magic[i];i+=1)
{
if ( fgetc( f_key ) != pubkey_magic[i] )
{
fputs( err_bad_public_key, stderr );
fputs( pubkey_magic, stderr );
fputc( '"', stderr );
return 1;
}
}
}
f_inp = stdin;
f_out = stdout;
if(!filter)
{
if('V' == operation || 'S' == operation)
openForRead[1] = openForWrite[1] = 0;
f_sec = 0;
if('e' == operation || 'v' == operation) f_sec = stdin;
if ( argc > arg_ix )
{
f_inp = chkopen( argv[arg_ix++], openForRead );
if (!f_inp) return 1;
}
if ( argc > arg_ix )
{
f_out = chkopen( argv[arg_ix++], openForWrite );
if (!f_out) return 1;
}
}
else
{
f_sec = 0;
if('e' == operation)
{
f_sec = chkopen( argv[arg_ix++], openForRead );
if (!f_sec) return 1;
}
}
err = do_operation( f_key, f_inp, f_out, f_sec, operation );
burn_stack();
burnBinasc();
return err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -