diff options
author | Werner Koch <[email protected]> | 2000-09-13 16:11:24 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2000-09-13 16:11:24 +0000 |
commit | 8f6b40ff1cde4112c54d2669e6c864fca448a76d (patch) | |
tree | 7748b83535f1812d857a39e8b73869b9b7807881 | |
parent | Add RSA (diff) | |
download | gnupg-8f6b40ff1cde4112c54d2669e6c864fca448a76d.tar.gz gnupg-8f6b40ff1cde4112c54d2669e6c864fca448a76d.zip |
See ChangeLog: Wed Sep 13 18:12:34 CEST 2000 Werner Koch
-rw-r--r-- | cipher/ChangeLog | 6 | ||||
-rw-r--r-- | cipher/rsa.c | 93 | ||||
-rw-r--r-- | g10/ChangeLog | 7 | ||||
-rw-r--r-- | g10/keyedit.c | 2 | ||||
-rw-r--r-- | g10/ringedit.c | 8 | ||||
-rw-r--r-- | g10/seckey-cert.c | 15 |
6 files changed, 122 insertions, 9 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog index c85d958f2..7616fe521 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,9 @@ +Wed Sep 13 18:12:34 CEST 2000 Werner Koch <[email protected]> + + * rsa.c (secret): Speed up by using the CRT. For a 2k keys this + is about 3 times faster. + (stronger_key_check): New but unused code to check the secret key. + Wed Sep 6 17:55:47 CEST 2000 Werner Koch <[email protected]> * rsa.c: Changed the comment about the patent. diff --git a/cipher/rsa.c b/cipher/rsa.c index 36b0802e2..2daa0547f 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -98,7 +98,7 @@ generate( RSA_secret_key *sk, unsigned nbits ) MPI t1, t2; MPI n; /* the public key */ MPI e; /* the exponent */ - MPI phi; /* helper: (p-a)(q-1) */ + MPI phi; /* helper: (p-1)(q-1) */ MPI g; MPI f; @@ -201,19 +201,106 @@ public(MPI output, MPI input, RSA_public_key *pkey ) mpi_powm( output, input, pkey->e, pkey->n ); } +#if 0 +static void +stronger_key_check ( RSA_secret_key *skey ) +{ + MPI t = mpi_alloc_secure ( 0 ); + MPI t1 = mpi_alloc_secure ( 0 ); + MPI t2 = mpi_alloc_secure ( 0 ); + MPI phi = mpi_alloc_secure ( 0 ); + + /* check that n == p * q */ + mpi_mul( t, skey->p, skey->q); + if (mpi_cmp( t, skey->n) ) + log_info ( "RSA Oops: n != p * q\n" ); + + /* check that p is less than q */ + if( mpi_cmp( skey->p, skey->q ) > 0 ) + log_info ("RSA Oops: p >= q\n"); + + + /* check that e divides neither p-1 nor q-1 */ + mpi_sub_ui(t, skey->p, 1 ); + mpi_fdiv_r(t, t, skey->e ); + if ( !mpi_cmp_ui( t, 0) ) + log_info ( "RSA Oops: e divides p-1\n" ); + mpi_sub_ui(t, skey->q, 1 ); + mpi_fdiv_r(t, t, skey->e ); + if ( !mpi_cmp_ui( t, 0) ) + log_info ( "RSA Oops: e divides q-1\n" ); + + /* check that d is correct */ + mpi_sub_ui( t1, skey->p, 1 ); + mpi_sub_ui( t2, skey->q, 1 ); + mpi_mul( phi, t1, t2 ); + mpi_gcd(t, t1, t2); + mpi_fdiv_q(t, phi, t); + mpi_invm(t, skey->e, t ); + if ( mpi_cmp(t, skey->d ) ) + log_info ( "RSA Oops: d is wrong\n"); + + /* check for crrectness of u */ + mpi_invm(t, skey->p, skey->q ); + if ( mpi_cmp(t, skey->u ) ) + log_info ( "RSA Oops: u is wrong\n"); + + log_info ( "RSA secret key check finished\n"); + + mpi_free (t); + mpi_free (t1); + mpi_free (t2); + mpi_free (phi); +} +#endif + + /**************** * Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT. * * m = c^d mod n * - * Where m is OUTPUT, c is INPUT and d,n are elements of PKEY. + * Or faster: + * + * m1 = c ^ (d mod (p-1)) mod p + * m2 = c ^ (d mod (q-1)) mod q + * h = u * (m2 - m1) mod q + * m = m1 + h * p * - * FIXME: We should better use the Chinese Remainder Theorem + * Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY. */ static void secret(MPI output, MPI input, RSA_secret_key *skey ) { + #if 0 mpi_powm( output, input, skey->d, skey->n ); + #else + MPI m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); + MPI m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); + MPI h = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); + + /* m1 = c ^ (d mod (p-1)) mod p */ + mpi_sub_ui( h, skey->p, 1 ); + mpi_fdiv_r( h, skey->d, h ); + mpi_powm( m1, input, h, skey->p ); + /* m2 = c ^ (d mod (q-1)) mod q */ + mpi_sub_ui( h, skey->q, 1 ); + mpi_fdiv_r( h, skey->d, h ); + mpi_powm( m2, input, h, skey->q ); + /* h = u * ( m2 - m1 ) mod q */ + mpi_sub( h, m2, m1 ); + if ( mpi_is_neg( h ) ) + mpi_add ( h, h, skey->q ); + mpi_mulm( h, skey->u, h, skey->q ); + /* m = m2 + h * p */ + mpi_mul ( h, h, skey->p ); + mpi_add ( output, m1, h ); + /* ready */ + + mpi_free ( h ); + mpi_free ( m1 ); + mpi_free ( m2 ); + #endif } diff --git a/g10/ChangeLog b/g10/ChangeLog index 5acfd4f0f..4dd7ad675 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +Wed Sep 13 18:12:34 CEST 2000 Werner Koch <[email protected]> + + * keyedit.c (keyedit_menu): Allow to use "debug" on the secret key. + + * ringedit.c (cmp_seckey): Fix for v4 RSA keys. + * seckey-cert.c (do_check): Workaround for PGP 7 bug. + Wed Sep 6 17:55:47 CEST 2000 Werner Koch <[email protected]> * misc.c (print_pubkey_algo_note): Do not print the RSA notice. diff --git a/g10/keyedit.c b/g10/keyedit.c index 84e8cd194..79f7c6350 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -592,7 +592,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, { N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") }, { N_("s") , cmdSIGN , 0,1,1, NULL }, { N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") }, - { N_("debug") , cmdDEBUG , 0,1,0, NULL }, + { N_("debug") , cmdDEBUG , 0,0,0, NULL }, { N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") }, { N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") }, { N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") }, diff --git a/g10/ringedit.c b/g10/ringedit.c index 5fcd458b0..382d7281f 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -1070,7 +1070,13 @@ cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk ) n = pubkey_get_nskey( req_sk->pubkey_algo ); for(i=0; i < n; i++ ) { - if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) ) + /* Note: becuase v4 protected keys have nothing in the + * mpis except for the first one, we skip all NULL MPIs. + * This might not be always correct in cases where the both + * keys do not match in their secret parts but we can ignore that + * because the need for this function is quite ugly. */ + if( req_sk->skey[1] && sk->skey[i] + && mpi_cmp( req_sk->skey[i], sk->skey[i] ) ) return -1; } return 0; diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 5cb10ee13..55a11939f 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -80,10 +80,13 @@ do_check( PKT_secret_key *sk ) if( sk->version >= 4 ) { int ndata; byte *p, *data; + u16 csumc = 0; i = pubkey_get_npkey(sk->pubkey_algo); assert( mpi_is_opaque( sk->skey[i] ) ); p = mpi_get_opaque( sk->skey[i], &ndata ); + if ( ndata > 1 ) + csumc = p[ndata-2] << 8 | p[ndata-1]; data = m_alloc_secure( ndata ); cipher_decrypt( cipher_hd, data, p, ndata ); mpi_free( sk->skey[i] ); sk->skey[i] = NULL ; @@ -96,9 +99,14 @@ do_check( PKT_secret_key *sk ) else { csum = checksum( data, ndata-2); sk->csum = data[ndata-2] << 8 | data[ndata-1]; + if ( sk->csum != csum ) { + /* This is a PGP 7.0.0 workaround */ + sk->csum = csumc; /* take the encrypted one */ + } } + /* must check it here otherwise the mpi_read_xx would fail - * because the length das an abritary value */ + * because the length may have an arbitrary value */ if( sk->csum == csum ) { for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { nbytes = ndata; @@ -106,6 +114,7 @@ do_check( PKT_secret_key *sk ) ndata -= nbytes; p += nbytes; } + /* at this point ndata should be equal to 2 (the checksum) */ } m_free(data); } @@ -237,9 +246,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) randomize_buffer(sk->protect.iv, sk->protect.ivlen, 1); cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); if( sk->version >= 4 ) { - /* FIXME: There is a bug in this function for all algorithms - * where the secret MPIs are more than 1 */ - byte *bufarr[PUBKEY_MAX_NSKEY]; + byte *bufarr[PUBKEY_MAX_NSKEY]; unsigned narr[PUBKEY_MAX_NSKEY]; unsigned nbits[PUBKEY_MAX_NSKEY]; int ndata=0; |