/** * Decrypts a string and removes the padding using either private or public key. * (depending on mode). * @param ciphertext: binary string to be decrypted. * @param key: table containing either the public or the private key, as generated by gen_key. * @return The original message (if everything works ok). * @see rsa_genkey */ static int luarsa_pkcs1_decrypt (lua_State *L) { int res = 0; int mode; size_t lmsg, lresult; rsa_context rsa; char *message = (char*)luaL_checklstring(L, 1, &lmsg); /* ciphertext */ char result[KEY_SIZE]; rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL ); mode = processKey(L, 2, &rsa); /* keytable */ rsa.len = lmsg; memset(result, 0, KEY_SIZE); printf("\nMode==%s\n", mode==RSA_PUBLIC ? "RSA_PUBLIC" : "RSA_PRIVATE" ); printf("Size==%d\n", lmsg ); printf("Crypt.Size==%d\n", rsa.len ); printf("ver: %d\n", rsa.ver); printf("len: %d\n", rsa.len); printf("padding: %d\n", rsa.padding); printf("hash_id: %d\n", rsa.hash_id); mpi_print("N:%s\n", &rsa.N); mpi_print("E:%s\n", &rsa.E); if(mode!=RSA_PUBLIC) { mpi_print("D:%s\n", &rsa.D); mpi_print("P:%s\n", &rsa.P); mpi_print("Q:%s\n", &rsa.Q); mpi_print("DP:%s\n", &rsa.DP); mpi_print("DQ:%s\n", &rsa.DQ); mpi_print("QP:%s\n", &rsa.QP); //mpi_print("RN:%s\n", &rsa.RN); //mpi_print("RP:%s\n", &rsa.RP); //mpi_print("RQ:%s\n", &rsa.RQ); } // pass rsa context and ciphertext to decryption engine res = rsa_pkcs1_decrypt(&rsa, RSA_PRIVATE, &lmsg, message, result); printf("Orig.Size==%d\n", lmsg ); if(res) { luaL_error(L, "Error during cipher (%d)", res); } // push encrypted result buffer lua_pushlstring(L, result, lmsg); /* ciphertext */ rsa_free( &rsa ); return 1; }
void g10_log_mpidump( const char *text, MPI a ) { FILE *fp = log_stream(); g10_log_print_prefix(text); mpi_print(fp, a, 1 ); fputc('\n', fp); }
static void print_key_data( PKT_public_key *pk, u32 *keyid ) { int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; int i; for(i=0; i < n; i++ ) { printf("pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) ); mpi_print(stdout, pk->pkey[i], 1 ); putchar(':'); putchar('\n'); } }
int main(int argc, char **argv) { static ARGPARSE_OPTS opts[] = { {0} }; ARGPARSE_ARGS pargs; int i, c; int state = 0; char strbuf[1000]; int stridx=0; pargs.argc = &argc; pargs.argv = &argv; pargs.flags = 0; i18n_init(); while( arg_parse( &pargs, opts) ) { switch( pargs.r_opt ) { default : pargs.err = 2; break; } } if( argc ) usage(1); for(i=0; i < STACKSIZE; i++ ) stack[i] = NULL; stackidx =0; while( (c=getc(stdin)) != EOF ) { if( !state ) { /* waiting */ if( isdigit(c) ) { state = 1; ungetc(c, stdin); strbuf[0] = '0'; strbuf[1] = 'x'; stridx=2; } else if( isspace(c) ) ; else { switch(c) { case '+': if( (c=getc(stdin)) == '+' ) do_inc(); else { ungetc(c, stdin); do_add(); } break; case '-': if( (c=getc(stdin)) == '-' ) do_dec(); else if( isdigit(c) || (c >='A' && c <= 'F') ) { state = 1; ungetc(c, stdin); strbuf[0] = '-'; strbuf[1] = '0'; strbuf[2] = 'x'; stridx=3; } else { ungetc(c, stdin); do_sub(); } break; case '*': do_mul(); break; case 'm': do_mulm(); break; case '/': do_div(); break; case '%': do_rem(); break; case '^': do_powm(); break; case 'I': do_inv(); break; case 'G': do_gcd(); break; case '>': do_rshift(); break; case 'i': /* dummy */ if( !stackidx ) fputs("stack underflow\n", stderr); else { mpi_free(stack[stackidx-1]); stackidx--; } break; case 'd': /* duplicate the tos */ if( !stackidx ) fputs("stack underflow\n", stderr); else if( stackidx < STACKSIZE ) { mpi_free(stack[stackidx]); stack[stackidx] = mpi_copy( stack[stackidx-1] ); stackidx++; } else fputs("stack overflow\n", stderr); break; case 'c': for(i=0; i < stackidx; i++ ) mpi_free(stack[i]), stack[i] = NULL; stackidx = 0; break; case 'p': /* print the tos */ if( !stackidx ) puts("stack is empty"); else { mpi_print(stdout, stack[stackidx-1], 1 ); putchar('\n'); } break; case 'f': /* print the stack */ for( i = stackidx-1 ; i >= 0; i-- ) { printf("[%2d]: ", i ); mpi_print(stdout, stack[i], 1 ); putchar('\n'); } break; default: fputs("invalid operator\n", stderr); } } } else if( state == 1 ) { /* in a number */ if( !isxdigit(c) ) { /* store the number */ state = 0; ungetc(c, stdin); if( stridx < 1000 ) strbuf[stridx] = 0; if( stackidx < STACKSIZE ) { if( !stack[stackidx] ) stack[stackidx] = mpi_alloc(10); if( mpi_fromstr(stack[stackidx], strbuf) ) fputs("invalid number\n", stderr); else stackidx++; } else fputs("stack overflow\n", stderr); } else { /* store digit */ if( stridx < 999 ) strbuf[stridx++] = c; else if( stridx == 999 ) { strbuf[stridx] = 0; fputs("string too large - truncated\n", stderr); stridx++; } } } } for(i=0; i < stackidx; i++ ) mpi_free(stack[i]); return 0; }
/** * Adds padding and encrypts a string using either private or public key. * (depending on mode). * @param message: arbitrary binary string to be encrypted. * @param keytable: table containing either the public or the private key, as generated by gen_key. * @return The cyphertext (as a binary string). * @see rsa_genkey */ static int luarsa_pkcs1_encrypt (lua_State *L) { int res = 0; int mode; size_t lmsg, lresult; rsa_context rsa; char *message = (char*)luaL_checklstring(L, 1, &lmsg); /* message */ char result[KEY_SIZE]; char alt_result[KEY_SIZE]; char* strMode=NULL; if(lua_type(L, 3)==LUA_TSTRING) { printf("Got parameter\n"); strMode = (char*)lua_tostring(L, 3); printf("[%s]\n", strMode); mode = strncmp(strMode, "private", 7) ? RSA_PUBLIC : RSA_PRIVATE; } rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL ); processKey(L, 2, &rsa); /* keytable */ rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3; memset(result, 0, KEY_SIZE); // <test> by Jason printf("\nMode==%s\n", mode==RSA_PUBLIC ? "RSA_PUBLIC" : "RSA_PRIVATE" ); printf("Size==%d\n", lmsg ); printf("Crypt.Size==%d\n", rsa.len ); printf("ver: %d\n", rsa.ver); printf("len: %d\n", rsa.len); printf("padding: %d\n", rsa.padding); printf("hash_id: %d\n", rsa.hash_id); mpi_print("N:%s\n", &rsa.N); mpi_print("E:%s\n", &rsa.E); if(mode!=RSA_PUBLIC) { //mpi_print("D:%s\n", &rsa.D); //mpi_print("P:%s\n", &rsa.P); //mpi_print("Q:%s\n", &rsa.Q); //mpi_print("DP:%s\n", &rsa.DP); //mpi_print("DQ:%s\n", &rsa.DQ); //mpi_print("QP:%s\n", &rsa.QP); //mpi_print("RN:%s\n", &rsa.RN); //mpi_print("RP:%s\n", &rsa.RP); //mpi_print("RQ:%s\n", &rsa.RQ); } // </test> by Jason // pass rsa context and message to encryption engine res = rsa_pkcs1_encrypt(&rsa, RSA_PUBLIC, lmsg, message, result); if(res) luaL_error(L, "Error during cipher (%d)", res); /* lmsg = 128; res = rsa_pkcs1_decrypt(&rsa, mode, &lmsg, result, alt_result); if(res) luaL_error(L, "Error during decipher (%d)", res); printf("(%d)", lmsg); */ push_private_key(L, &rsa); // push encrypted result buffer lua_pushlstring(L, result, rsa.len); /* ciphertext */ rsa_free( &rsa ); return 1; }
/**************** * We do not need to use the strongest RNG because we gain no extra * security from it - The prime number is public and we could also * offer the factors for those who are willing to check that it is * indeed a strong prime. * * mode 0: Standard * 1: Make sure that at least one factor is of size qbits. */ MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors ) { int n; /* number of factors */ int m; /* number of primes in pool */ unsigned fbits; /* length of prime factors */ MPI *factors; /* current factors */ MPI *pool; /* pool of primes */ MPI q; /* first prime factor (variable)*/ MPI prime; /* prime test value */ MPI q_factor; /* used for mode 1 */ byte *perms = NULL; int i, j; int count1, count2; unsigned nprime; unsigned req_qbits = qbits; /* the requested q bits size */ MPI val_2 = mpi_alloc_set_ui( 2 ); /* find number of needed prime factors */ for(n=1; (pbits - qbits - 1) / n >= qbits; n++ ) ; n--; if( !n || (mode==1 && n < 2) ) log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits ); if( mode == 1 ) { n--; fbits = (pbits - 2*req_qbits -1) / n; qbits = pbits - req_qbits - n*fbits; } else { fbits = (pbits - req_qbits -1) / n; qbits = pbits - n*fbits; } if( DBG_CIPHER ) log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n ); prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB ); q = gen_prime( qbits, 0, 0 ); q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL; /* allocate an array to hold the factors + 2 for later usage */ factors = m_alloc_clear( (n+2) * sizeof *factors ); /* make a pool of 3n+5 primes (this is an arbitrary value) */ m = n*3+5; if( mode == 1 ) m += 5; /* need some more for DSA */ if( m < 25 ) m = 25; pool = m_alloc_clear( m * sizeof *pool ); /* permutate over the pool of primes */ count1=count2=0; do { next_try: if( !perms ) { /* allocate new primes */ for(i=0; i < m; i++ ) { mpi_free(pool[i]); pool[i] = NULL; } /* init m_out_of_n() */ perms = m_alloc_clear( m ); for(i=0; i < n; i++ ) { perms[i] = 1; pool[i] = gen_prime( fbits, 0, 0 ); factors[i] = pool[i]; } } else { m_out_of_n( perms, n, m ); for(i=j=0; i < m && j < n ; i++ ) if( perms[i] ) { if( !pool[i] ) pool[i] = gen_prime( fbits, 0, 0 ); factors[j++] = pool[i]; } if( i == n ) { m_free(perms); perms = NULL; progress('!'); goto next_try; /* allocate new primes */ } } mpi_set( prime, q ); mpi_mul_ui( prime, prime, 2 ); if( mode == 1 ) mpi_mul( prime, prime, q_factor ); for(i=0; i < n; i++ ) mpi_mul( prime, prime, factors[i] ); mpi_add_ui( prime, prime, 1 ); nprime = mpi_get_nbits(prime); if( nprime < pbits ) { if( ++count1 > 20 ) { count1 = 0; qbits++; progress('>'); mpi_free (q); q = gen_prime( qbits, 0, 0 ); goto next_try; } } else count1 = 0; if( nprime > pbits ) { if( ++count2 > 20 ) { count2 = 0; qbits--; progress('<'); mpi_free (q); q = gen_prime( qbits, 0, 0 ); goto next_try; } } else count2 = 0; } while( !(nprime == pbits && check_prime( prime, val_2 )) ); if( DBG_CIPHER ) { progress('\n'); log_mpidump( "prime : ", prime ); log_mpidump( "factor q: ", q ); if( mode == 1 ) log_mpidump( "factor q0: ", q_factor ); for(i=0; i < n; i++ ) log_mpidump( "factor pi: ", factors[i] ); log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) ); if( mode == 1 ) fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) ); for(i=0; i < n; i++ ) fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); progress('\n'); } if( ret_factors ) { /* caller wants the factors */ *ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors); i = 0; if( mode == 1 ) { (*ret_factors)[i++] = mpi_copy( q_factor ); for(; i <= n; i++ ) (*ret_factors)[i] = mpi_copy( factors[i] ); } else { for(; i < n; i++ ) (*ret_factors)[i] = mpi_copy( factors[i] ); } } if( g ) { /* create a generator (start with 3)*/ MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) ); MPI b = mpi_alloc( mpi_get_nlimbs(prime) ); MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) ); if( mode == 1 ) BUG(); /* not yet implemented */ factors[n] = q; factors[n+1] = mpi_alloc_set_ui(2); mpi_sub_ui( pmin1, prime, 1 ); mpi_set_ui(g,2); do { mpi_add_ui(g, g, 1); if( DBG_CIPHER ) { log_debug("checking g: "); mpi_print( stderr, g, 1 ); } else progress('^'); for(i=0; i < n+2; i++ ) { /*fputc('~', stderr);*/ mpi_fdiv_q(tmp, pmin1, factors[i] ); /* (no mpi_pow(), but it is okay to use this with mod prime) */ mpi_powm(b, g, tmp, prime ); if( !mpi_cmp_ui(b, 1) ) break; } if( DBG_CIPHER ) progress('\n'); } while( i < n+2 ); mpi_free(factors[n+1]); mpi_free(tmp); mpi_free(b); mpi_free(pmin1); } if( !DBG_CIPHER ) progress('\n'); m_free( factors ); /* (factors are shallow copies) */ for(i=0; i < m; i++ ) mpi_free( pool[i] ); m_free( pool ); m_free(perms); mpi_free(val_2); mpi_free(q); return prime; }