Output armor works, RSA keygen works.

This commit is contained in:
Werner Koch 1997-11-19 13:12:23 +00:00
parent 5393dd53c5
commit 25c8f1a3d7
21 changed files with 395 additions and 115 deletions

View File

@ -22,10 +22,14 @@
@@TOP@@ @@TOP@@
#undef M_DEBUG #undef M_DEBUG
#undef VERSION #undef VERSION
#undef PACKAGE #undef PACKAGE
/* RSA is only compiled in if you have these files. You can use
* RSA with out any restrictions, if your not in the U.S. or
* wait until sep 20, 2000
*/
#undef HAVE_RSA_CIPHER
@@BOTTOM@@ @@BOTTOM@@

View File

@ -91,50 +91,57 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
MPI n; /* the public key */ MPI n; /* the public key */
MPI e; /* the exponent */ MPI e; /* the exponent */
MPI phi; /* helper: (p-a)(q-1) */ MPI phi; /* helper: (p-a)(q-1) */
MPI g;
MPI f;
/* select two (very secret) primes */ /* select two (very secret) primes */
p = generate_random_prime( nbits / 2 ); p = generate_random_prime( nbits / 2 );
q = generate_random_prime( nbits / 2 ); q = generate_random_prime( nbits / 2 );
if( mpi_cmp( p, q ) > 0 ) /* p shall be smaller than q */ if( mpi_cmp( p, q ) > 0 ) /* p shall be smaller than q (for calc of u)*/
mpi_swap(p,q); mpi_swap(p,q);
/* calculate phi = (p-1)(q-1) */ /* calculate Euler totient: phi = (p-1)(q-1) */
t1 = mpi_alloc_secure( mpi_get_nlimbs(p) ); t1 = mpi_alloc_secure( mpi_get_nlimbs(p) );
t2 = mpi_alloc_secure( mpi_get_nlimbs(p) ); t2 = mpi_alloc_secure( mpi_get_nlimbs(p) );
phi = mpi_alloc_secure( nbits / BITS_PER_MPI_LIMB ); phi = mpi_alloc_secure( nbits / BITS_PER_MPI_LIMB );
g = mpi_alloc_secure( nbits / BITS_PER_MPI_LIMB );
f = mpi_alloc_secure( nbits / BITS_PER_MPI_LIMB );
mpi_sub_ui( t1, p, 1 ); mpi_sub_ui( t1, p, 1 );
mpi_sub_ui( t2, q, 1 ); mpi_sub_ui( t2, q, 1 );
mpi_mul( phi, t1, t2 ); mpi_mul( phi, t1, t2 );
mpi_gcd(g, t1, t2);
mpi_fdiv_q(f, phi, g);
/* multiply them to make the private key */ /* multiply them to make the private key */
n = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); n = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
mpi_mul( n, p, q ); mpi_mul( n, p, q );
/* find a public exponent */ /* find a public exponent */
e = mpi_alloc(1); e = mpi_alloc(1);
mpi_set_ui( e, 17); /* start with 17 */ mpi_set_ui( e, 17); /* start with 17 */
while( !mpi_gcd(t1, e, phi) ) { /* (while gcd is not 1) */ while( !mpi_gcd(t1, e, phi) ) /* (while gcd is not 1) */
if( DBG_CIPHER )
log_mpidump("trying e=", e);
mpi_add_ui( e, e, 2); mpi_add_ui( e, e, 2);
}
/* calculate the secret key d = e^1 mod phi */ /* calculate the secret key d = e^1 mod phi */
d = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); d = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
mpi_inv_mod(d, e, phi ); mpi_inv_mod(d, e, f );
/* calculate the inverse of p and q (used for chinese remainder theorem)*/ /* calculate the inverse of p and q (used for chinese remainder theorem)*/
u = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); u = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
mpi_inv_mod(u, p, q ); mpi_inv_mod(u, p, q );
if( DBG_CIPHER ) { if( DBG_CIPHER ) {
log_mpidump("p=", p ); log_mpidump(" p= ", p );
log_mpidump("q=", q ); log_mpidump(" q= ", q );
log_mpidump("phi=", phi ); log_mpidump("phi= ", phi );
log_mpidump("n=", n ); log_mpidump(" g= ", g );
log_mpidump("e=", e ); log_mpidump(" f= ", f );
log_mpidump("d=", d ); log_mpidump(" n= ", n );
log_mpidump("u=", u ); log_mpidump(" e= ", e );
log_mpidump(" d= ", d );
log_mpidump(" u= ", u );
} }
mpi_free(t1); mpi_free(t1);
mpi_free(t2); mpi_free(t2);
mpi_free(phi); mpi_free(phi);
mpi_free(f);
mpi_free(g);
pk->n = mpi_copy(n); pk->n = mpi_copy(n);
pk->e = mpi_copy(e); pk->e = mpi_copy(e);
@ -146,7 +153,7 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
sk->u = u; sk->u = u;
/* now we can test our keys (this should never fail!) */ /* now we can test our keys (this should never fail!) */
test_keys( pk, sk, nbits - 16 ); test_keys( pk, sk, nbits - 64 );
} }

View File

@ -44,6 +44,11 @@
#undef M_DEBUG #undef M_DEBUG
#undef VERSION #undef VERSION
#undef PACKAGE #undef PACKAGE
/* RSA is only compiled in if you have these files. You can use
* RSA with out any restrictions, if your not in the U.S. or
* wait until sep 20, 2000
*/
#undef HAVE_RSA_CIPHER
/* Define if you have the strerror function. */ /* Define if you have the strerror function. */
#undef HAVE_STRERROR #undef HAVE_STRERROR

View File

@ -47,6 +47,15 @@ dnl Checks for library functions.
AC_FUNC_VPRINTF AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror strtol strtoul) AC_CHECK_FUNCS(strerror strtol strtoul)
dnl
AC_MSG_CHECKING(wether we have the rsa source)
if test -f cipher/rsa.c && test -f cipher/rsa.h; then
AC_DEFINE(HAVE_RSA_CIPHER)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_OUTPUT([ Makefile util/Makefile mpi/Makefile cipher/Makefile \ AC_OUTPUT([ Makefile util/Makefile mpi/Makefile cipher/Makefile \
g10/Makefile tools/Makefile ], g10/Makefile tools/Makefile ],
[echo timestamp > stamp-h ]) [echo timestamp > stamp-h ])

View File

@ -31,3 +31,6 @@ g10_SOURCES = g10.c \
LDADD = -L ../cipher -L ../mpi -L ../util -lcipher -lmpi -lutil LDADD = -L ../cipher -L ../mpi -L ../util -lcipher -lmpi -lutil
$(PROGRAMS): ../cipher/libcipher.a ../mpi/libmpi.a

View File

@ -277,6 +277,8 @@ install-exec install-data install uninstall all installdirs \
mostlyclean-generic distclean-generic clean-generic \ mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean maintainer-clean-generic clean mostlyclean distclean maintainer-clean
$(PROGRAMS): ../cipher/libcipher.a ../mpi/libmpi.a
.SUFFIXES: .SUFFIXES:
.SUFFIXES: .c .o .SUFFIXES: .c .o

View File

@ -361,7 +361,7 @@ write_header( IOBUF out, int ctb, u32 len )
if( iobuf_put(out, ctb ) ) if( iobuf_put(out, ctb ) )
return -1; return -1;
if( !len ) { if( !len ) {
iobuf_set_block_mode(out, 5 /*8196*/ ); iobuf_set_block_mode(out, 8196 );
} }
else { else {
if( ctb & 2 ) { if( ctb & 2 ) {

View File

@ -56,9 +56,52 @@ typedef struct {
} cipher_filter_context_t; } cipher_filter_context_t;
typedef struct {
int status;
int what;
byte buf[3];
int idx, idx2;
u32 crc;
} armor_filter_context_t;
#define CRCINIT 0xB704CE
#define CRCPOLY 0X864CFB
#define CRCUPDATE(a,c) do { \
a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
a &= 0x00ffffff; \
} while(0)
static u32 crc_table[256];
static int crc_table_initialized;
static void
init_crc_table(void)
{
int i, j;
u32 t;
crc_table[0] = 0;
for(i=j=0; j < 128; j++ ) {
t = crc_table[j];
if( t & 0x00800000 ) {
t <<= 1;
crc_table[i++] = t ^ CRCPOLY;
crc_table[i++] = t;
}
else {
t <<= 1;
crc_table[i++] = t;
crc_table[i++] = t ^ CRCPOLY;
}
}
crc_table_initialized=1;
}
/**************** /****************
* Encode FILENAME only with the symmetric cipher. Take input from * Encode FILENAME only with the symmetric cipher. Take input from
@ -106,8 +149,10 @@ encode_simple( const char *filename, int mode )
int rc = 0; int rc = 0;
u32 filesize; u32 filesize;
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t afx;
memset( &cfx, 0, sizeof cfx); memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
/* prepare iobufs */ /* prepare iobufs */
if( !(inp = iobuf_open(filename)) ) { if( !(inp = iobuf_open(filename)) ) {
@ -135,7 +180,7 @@ encode_simple( const char *filename, int mode )
} }
if( opt.armor ) if( opt.armor )
iobuf_push_filter( out, armor_filter, NULL ); iobuf_push_filter( out, armor_filter, &afx );
write_comment( out, "#Created by G10 pre-release " VERSION ); write_comment( out, "#Created by G10 pre-release " VERSION );
@ -197,11 +242,13 @@ encode_crypt( const char *filename, STRLIST remusr )
int last_rc, rc = 0; int last_rc, rc = 0;
u32 filesize; u32 filesize;
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t afx;
int any_names = 0; int any_names = 0;
STRLIST local_remusr = NULL; STRLIST local_remusr = NULL;
char *ustr; char *ustr;
memset( &cfx, 0, sizeof cfx); memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
if( !remusr ) { if( !remusr ) {
remusr = NULL; /* fixme: ask */ remusr = NULL; /* fixme: ask */
@ -225,7 +272,7 @@ encode_crypt( const char *filename, STRLIST remusr )
} }
if( opt.armor ) if( opt.armor )
iobuf_push_filter( out, armor_filter, NULL ); iobuf_push_filter( out, armor_filter, &afx );
write_comment( out, "#Created by G10 pre-release " VERSION ); write_comment( out, "#Created by G10 pre-release " VERSION );
@ -389,11 +436,121 @@ open_outfile( const char *iname )
static int static int
armor_filter( void *opaque, int control, armor_filter( void *opaque, int control,
IOBUF chain, byte *buf, size_t *ret_len) IOBUF a, byte *buffer, size_t *ret_len)
{ {
if( control == IOBUFCTRL_DESC ) { static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
*(char**)buf = "armor_filter"; "abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
size_t size = *ret_len;
armor_filter_context_t *afx = opaque;
int rc=0, i, c;
byte buf[3];
int idx, idx2;
u32 crc;
if( control == IOBUFCTRL_FLUSH ) {
if( !afx->status ) { /* write the header line */
if( !afx->what )
iobuf_writestr(a, "-----BEGIN PGP MESSAGE-----\n");
else
iobuf_writestr(a, "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
iobuf_writestr(a, "Version: G10 pre-release " VERSION "\n");
iobuf_writestr(a, "Comment: This is a alpha test version!\n\n");
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
afx->crc = CRCINIT;
}
crc = afx->crc;
idx = afx->idx;
idx2 = afx->idx2;
for(i=0; i < idx; i++ )
buf[i] = afx->buf[i];
for(i=0; i < size; i++ )
crc = (crc << 8) ^ crc_table[(crc >> 16)&0xff ^ buffer[i]];
crc &= 0x00ffffff;
for( ; size; buffer++, size-- ) {
buf[idx++] = *buffer;
if( idx > 2 ) {
idx = 0;
c = bintoasc[(*buf >> 2) & 077];
iobuf_put(a, c);
c = bintoasc[(((*buf<<4)&060)|((buf[1] >> 4)&017))&077];
iobuf_put(a, c);
c = bintoasc[(((buf[1]<<2)&074)|((buf[2]>>6)&03))&077];
iobuf_put(a, c);
c = bintoasc[buf[2]&077];
iobuf_put(a, c);
if( ++idx2 > (72/4) ) {
iobuf_put(a, '\n');
idx2=0;
}
}
}
for(i=0; i < idx; i++ )
afx->buf[i] = buf[i];
afx->idx = idx;
afx->idx2 = idx2;
afx->crc = crc;
} }
else if( control == IOBUFCTRL_INIT ) {
if( !crc_table_initialized )
init_crc_table();
}
else if( control == IOBUFCTRL_FREE ) {
if( afx->status ) { /* pad, write cecksum, and bottom line */
crc = afx->crc;
idx = afx->idx;
idx2 = afx->idx2;
for(i=0; i < idx; i++ )
buf[i] = afx->buf[i];
if( idx ) {
c = bintoasc[(*buf>>2)&077];
iobuf_put(a, c);
if( idx == 1 ) {
c = bintoasc[((*buf << 4) & 060) & 077];
iobuf_put(a, c);
iobuf_put(a, '=');
iobuf_put(a, '=');
}
else { /* 2 */
c = bintoasc[(((*buf<<4)&060)|((buf[1]>>4)&017))&077];
iobuf_put(a, c);
c = bintoasc[((buf[1] << 2) & 074) & 077];
iobuf_put(a, c);
iobuf_put(a, '=');
}
++idx2;
}
/* may need a linefeed */
if( idx2 < (72/4) )
iobuf_put(a, '\n');
/* write the CRC */
iobuf_put(a, '=');
buf[0] = crc >>16;
buf[1] = crc >> 8;
buf[2] = crc;
c = bintoasc[(*buf >> 2) & 077];
iobuf_put(a, c);
c = bintoasc[(((*buf<<4)&060)|((buf[1] >> 4)&017))&077];
iobuf_put(a, c);
c = bintoasc[(((buf[1]<<2)&074)|((buf[2]>>6)&03))&077];
iobuf_put(a, c);
c = bintoasc[buf[2]&077];
iobuf_put(a, c);
iobuf_put(a, '\n');
/* and the the trailer */
if( !afx->what )
iobuf_writestr(a, "-----END PGP MESSAGE-----\n");
else
iobuf_writestr(a, "-----END PGP PUBLIC KEY BLOCK-----\n");
}
}
else if( control == IOBUFCTRL_DESC )
*(char**)buf = "armor_filter";
return 0; return 0;
} }

View File

@ -50,7 +50,11 @@ strusage( int level )
case 12: p = case 12: p =
"\nSyntax: g10 [options] [files]\n" "\nSyntax: g10 [options] [files]\n"
"sign, check, encrypt or decrypt\n" "sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"; "default operation depends on the input data\n"
#ifndef HAVE_RSA_CIPHER
"This version does not support RSA!\n"
#endif
;
break; break;
default: p = default_strusage(level); default: p = default_strusage(level);
} }

View File

@ -204,7 +204,6 @@ generate_keypair()
m_free(answer); m_free(answer);
} }
} }
/* now check wether we a are allowed to write the keyrings */ /* now check wether we a are allowed to write the keyrings */
if( !(rc=overwrite_filep( pub_fname )) ) { if( !(rc=overwrite_filep( pub_fname )) ) {
if( !(pub_io = iobuf_create( pub_fname )) ) if( !(pub_io = iobuf_create( pub_fname )) )

View File

@ -30,7 +30,9 @@
#include "mpi.h" #include "mpi.h"
#include "../cipher/md5.h" #include "../cipher/md5.h"
#include "../cipher/rmd.h" #include "../cipher/rmd.h"
#include "../cipher/rsa.h" #ifdef HAVE_RSA_CIPHER
#include "../cipher/rsa.h"
#endif
#include "../cipher/idea.h" #include "../cipher/idea.h"
#include "../cipher/blowfish.h" #include "../cipher/blowfish.h"
#include "../cipher/gost.h" #include "../cipher/gost.h"

View File

@ -81,6 +81,7 @@ void iobuf_set_limit( IOBUF a, unsigned long nlimit );
int iobuf_readbyte(IOBUF a); int iobuf_readbyte(IOBUF a);
int iobuf_writebyte(IOBUF a, unsigned c); int iobuf_writebyte(IOBUF a, unsigned c);
int iobuf_write(IOBUF a, byte *buf, unsigned buflen ); int iobuf_write(IOBUF a, byte *buf, unsigned buflen );
int iobuf_writestr(IOBUF a, const char *buf );
int iobuf_write_temp( IOBUF a, IOBUF temp ); int iobuf_write_temp( IOBUF a, IOBUF temp );
size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ); size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen );

View File

@ -40,7 +40,7 @@ int mpi_debug_mode;
#error add definions for this machine here #error add definions for this machine here
#endif #endif
typedef struct { typedef struct mpi_struct {
int alloced; /* array size (# of allocated limbs) */ int alloced; /* array size (# of allocated limbs) */
int nlimbs; /* number of valid limbs */ int nlimbs; /* number of valid limbs */
int sign; /* indicates a negative number */ int sign; /* indicates a negative number */
@ -139,9 +139,10 @@ int mpi_test_bit( MPI a, unsigned n );
void mpi_set_bit( MPI a, unsigned n ); void mpi_set_bit( MPI a, unsigned n );
void mpi_clear_bit( MPI a, unsigned n ); void mpi_clear_bit( MPI a, unsigned n );
void mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque ); void mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque );
void mpi_rshift( MPI x, MPI a, unsigned n );
/*-- mpi-inv.c --*/ /*-- mpi-inv.c --*/
int mpi_inv_mod( MPI x, MPI u, MPI v ); void mpi_inv_mod( MPI x, MPI u, MPI v );
#endif /*G10_MPI_H*/ #endif /*G10_MPI_H*/

View File

@ -68,7 +68,7 @@ mpi_add_ui(MPI w, MPI u, unsigned long v )
else { else {
mpihelp_sub_1(wp, up, usize, v); mpihelp_sub_1(wp, up, usize, v);
/* Size can decrease with at most one limb. */ /* Size can decrease with at most one limb. */
wsize = (usize - (wp[usize-1]? 0:1)); wsize = usize - (wp[usize-1]==0);
wsign = 1; wsign = 1;
} }
} }
@ -85,27 +85,30 @@ mpi_add(MPI w, MPI u, MPI v)
mpi_size_t usize, vsize, wsize; mpi_size_t usize, vsize, wsize;
int usign, vsign, wsign; int usign, vsign, wsign;
usize = u->nlimbs; if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
vsize = v->nlimbs; usize = v->nlimbs;
usign = u->sign; usign = v->sign;
vsign = v->sign; vsize = u->nlimbs;
vsign = u->sign;
if( usize < vsize ) { /* Swap U and V. */ wsize = usize + 1;
{ MPI t; t = u; u = v; v = t; } RESIZE_IF_NEEDED(w, wsize);
{ mpi_size_t t = usize; usize = vsize; vsize = t; } /* These must be after realloc (u or v may be the same as w). */
{ int t = usign; usign = vsign; vsign = t; } up = v->d;
vp = u->d;
}
else {
usize = u->nlimbs;
usign = u->sign;
vsize = v->nlimbs;
vsign = v->sign;
wsize = usize + 1;
RESIZE_IF_NEEDED(w, wsize);
/* These must be after realloc (u or v may be the same as w). */
up = u->d;
vp = v->d;
} }
/* If not space for w (and possible carry), increase space. */
wsize = usize + 1;
if( w->alloced < wsize )
mpi_resize(w, wsize);
wsign = 0;
/* These must be after realloc (u or v may be the same as w). */
up = u->d;
vp = v->d;
wp = w->d; wp = w->d;
wsign = 0;
if( !vsize ) { /* simple */ if( !vsize ) { /* simple */
MPN_COPY(wp, up, usize ); MPN_COPY(wp, up, usize );
@ -140,7 +143,7 @@ mpi_add(MPI w, MPI u, MPI v)
wp[usize] = cy; wp[usize] = cy;
wsize = usize + cy; wsize = usize + cy;
if( usign ) if( usign )
wsize = 1; wsign = 1;
} }
w->nlimbs = wsize; w->nlimbs = wsize;
@ -193,7 +196,7 @@ mpi_sub_ui(MPI w, MPI u, unsigned long v )
else { else {
mpihelp_sub_1(wp, up, usize, v); mpihelp_sub_1(wp, up, usize, v);
/* Size can decrease with at most one limb. */ /* Size can decrease with at most one limb. */
wsize = (usize - (wp[usize-1]? 1:0)); wsize = usize - (wp[usize-1]==0);
} }
} }
@ -204,7 +207,7 @@ mpi_sub_ui(MPI w, MPI u, unsigned long v )
void void
mpi_sub(MPI w, MPI u, MPI v) mpi_sub(MPI w, MPI u, MPI v)
{ {
if( w == v ) { if( 1 || w == v ) {
MPI vv = mpi_copy(v); MPI vv = mpi_copy(v);
vv->sign = !vv->sign; vv->sign = !vv->sign;
mpi_add( w, u, vv ); mpi_add( w, u, vv );

View File

@ -130,4 +130,25 @@ mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque )
assert(!xbits); assert(!xbits);
} }
/****************
* Shift A by N bits to the right
* FIXME: should use alloc_limb if X and A are same.
*/
void
mpi_rshift( MPI x, MPI a, unsigned n )
{
mpi_ptr_t xp;
mpi_size_t xsize;
xsize = a->nlimbs;
x->sign = a->sign;
RESIZE_IF_NEEDED(x, xsize);
xp = x->d;
if( xsize ) {
mpihelp_rshift( xp, a->d, xsize, n);
MPN_NORMALIZE( xp, xsize);
}
x->nlimbs = xsize;
}

View File

@ -23,20 +23,21 @@
#include <stdlib.h> #include <stdlib.h>
#include "mpi-internal.h" #include "mpi-internal.h"
/**************** /****************
* Calculate the multiplicative inverse X of U mod V * Calculate the multiplicative inverse X of A mod N
* That is: Find the solution for * That is: Find the solution x for
* 1 = (u*x) mod v * 1 = (a*x) mod n
* This has only a unique solution if U and V are relatively prime.
* Returns 0 if a solution was found.
*/ */
int void
mpi_inv_mod( MPI x, MPI u, MPI v ) mpi_inv_mod( MPI x, MPI a, MPI n )
{ {
#if 0 #if 0
/* Extended Euclid's algorithm (See TAOPC Vol II, 4.52. Alg X) */ MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
MPI u1, u2, u3, v1, v2, v3, q, t1, t2, t3; MPI ta, tb, tc;
u = mpi_copy(a);
v = mpi_copy(n);
u1 = mpi_alloc_set_ui(1); u1 = mpi_alloc_set_ui(1);
u2 = mpi_alloc_set_ui(0); u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u); u3 = mpi_copy(u);
@ -48,22 +49,20 @@ mpi_inv_mod( MPI x, MPI u, MPI v )
t2 = mpi_alloc( mpi_get_nlimbs(u) ); t2 = mpi_alloc( mpi_get_nlimbs(u) );
t3 = mpi_alloc( mpi_get_nlimbs(u) ); t3 = mpi_alloc( mpi_get_nlimbs(u) );
while( mpi_cmp_ui( v3, 0 ) ) { while( mpi_cmp_ui( v3, 0 ) ) {
/*log_debug("----------------------\n"); mpi_fdiv_q( q, u3, v3 );
log_mpidump("q =", u1); mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3);
mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3);
mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3);
}
/* log_debug("result:\n");
log_mpidump("q =", q );
log_mpidump("u1=", u1); log_mpidump("u1=", u1);
log_mpidump("u2=", u2); log_mpidump("u2=", u2);
log_mpidump("u3=", u3); log_mpidump("u3=", u3);
log_mpidump("v1=", v1); log_mpidump("v1=", v1);
log_mpidump("v2=", v2); log_mpidump("v2=", v2); */
log_mpidump("v3=", v3); */ mpi_set(x, u1);
mpi_fdiv_q( q, u3, v3 );
mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3);
mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3);
mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3);
}
mpi_set(x, u3);
mpi_free(u1); mpi_free(u1);
mpi_free(u2); mpi_free(u2);
@ -75,52 +74,89 @@ mpi_inv_mod( MPI x, MPI u, MPI v )
mpi_free(t1); mpi_free(t1);
mpi_free(t2); mpi_free(t2);
mpi_free(t3); mpi_free(t3);
#endif mpi_free(u);
mpi_free(v);
#else
/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
* modified according to Michael Penk's solution for Exercice 35 */
/***************************** /* FIXME: we can simplify this in most cases (see Knuth) */
* 1. Init: g0 = u g1 = v v0 = 0 v1 = 1 MPI u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3;
* 2. Test: if g1 is 0 terminate. Result = v0 < 0: v0 + n unsigned k;
* else: v0 int sign;
* 3. Divide: div,rem = g0 / g1
* t1 = v0 - div * v1
* v0 = v1
* v1 = t1
* g0 = g1
* g1 = rem
* continue with step 2.
*/
MPI g0, g1, v0, v1, div, rem, t1;
g0 = mpi_copy(v);
g1 = mpi_copy(u);
v0 = mpi_alloc_set_ui( 0 );
v1 = mpi_alloc_set_ui( 1 );
div = mpi_alloc(mpi_get_nlimbs(v));
rem = mpi_alloc(mpi_get_nlimbs(v));
t1 = mpi_alloc(mpi_get_nlimbs(v));
while( mpi_cmp_ui( g1, 0) ) {
mpi_fdiv_qr(div, rem, g0, g1);
mpi_mul(t1, div, v1);
mpi_sub(t1, v0, t1);
mpi_set(v0, v1);
mpi_set(v1, t1);
mpi_set(g0, g1);
mpi_set(g1, rem);
u = mpi_copy(a);
v = mpi_copy(n);
for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
mpi_rshift(u, u, 1);
mpi_rshift(v, v, 1);
} }
if( mpi_cmp_ui( v0, 0) < 0 )
mpi_add( x, v0, v);
else
mpi_set( x, v0);
mpi_free(g0);
mpi_free(g1); u1 = mpi_alloc_set_ui(1);
mpi_free(v0); u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_copy(v); /* !-- used as const 1 */
v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u );
v3 = mpi_copy(v);
if( mpi_test_bit(u, 0) ) { /* u is odd */
t1 = mpi_alloc_set_ui(0);
t2 = mpi_alloc_set_ui(1); t2->sign = 1;
t3 = mpi_copy(v); t3->sign = !t3->sign;
goto Y4;
}
else {
t1 = mpi_alloc_set_ui(1);
t2 = mpi_alloc_set_ui(0);
t3 = mpi_copy(u);
}
do {
do {
if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
mpi_rshift(t1, t1, 1);
mpi_rshift(t2, t2, 1);
mpi_rshift(t3, t3, 1);
Y4:
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
if( !t3->sign ) {
mpi_set(u1, t1);
mpi_set(u2, t2);
mpi_set(u3, t3);
}
else {
mpi_sub(v1, v, t1);
sign = u->sign; u->sign = !u->sign;
mpi_sub(v2, u, t2);
u->sign = sign;
sign = t3->sign; t3->sign = !t3->sign;
mpi_set(v3, t3);
t3->sign = sign;
}
mpi_sub(t1, u1, v1);
mpi_sub(t2, u2, v2);
mpi_sub(t3, u3, v3);
if( t1->sign ) {
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
} while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(u2);
mpi_free(u3);
mpi_free(v1); mpi_free(v1);
mpi_free(div); mpi_free(v2);
mpi_free(rem); mpi_free(v3);
mpi_free(t1); mpi_free(t1);
return 0; mpi_free(t2);
mpi_free(t3);
#endif
} }

View File

@ -265,6 +265,7 @@ mpi_copy( MPI a )
b = mpi_alloc( a->nlimbs ); b = mpi_alloc( a->nlimbs );
#endif #endif
b->nlimbs = a->nlimbs; b->nlimbs = a->nlimbs;
b->sign = a->sign;
for(i=0; i < b->nlimbs; i++ ) for(i=0; i < b->nlimbs; i++ )
b->d[i] = a->d[i]; b->d[i] = a->d[i];
} }
@ -318,9 +319,9 @@ mpi_alloc_set_ui( unsigned long u)
void void
mpi_swap( MPI a, MPI b) mpi_swap( MPI a, MPI b)
{ {
MPI x; struct mpi_struct tmp;
x = a; a = b; b = x; tmp = *a; *a = *b; *b = tmp;
} }

View File

@ -7,6 +7,7 @@ bin_PROGRAMS = mpicalc
mpicalc_SOURCES = mpicalc.c mpicalc_SOURCES = mpicalc.c
LDADD = -L ../cipher -L ../mpi -L ../util -lcipher -lmpi -lutil LDADD = -L ../cipher -L ../mpi -L ../util -lmpi -lutil
$(PROGRAMS): ../mpi/libmpi.a

View File

@ -44,7 +44,7 @@ bin_PROGRAMS = mpicalc
mpicalc_SOURCES = mpicalc.c mpicalc_SOURCES = mpicalc.c
LDADD = -L ../cipher -L ../mpi -L ../util -lcipher -lmpi -lutil LDADD = -L ../cipher -L ../mpi -L ../util -lmpi -lutil
mkinstalldirs = $(top_srcdir)/scripts/mkinstalldirs mkinstalldirs = $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = ../config.h CONFIG_HEADER = ../config.h
PROGRAMS = $(bin_PROGRAMS) PROGRAMS = $(bin_PROGRAMS)
@ -244,6 +244,8 @@ install-exec install-data install uninstall all installdirs \
mostlyclean-generic distclean-generic clean-generic \ mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean maintainer-clean-generic clean mostlyclean distclean maintainer-clean
$(PROGRAMS): ../mpi/libmpi.a
.SUFFIXES: .SUFFIXES:
.SUFFIXES: .c .o .SUFFIXES: .c .o

View File

@ -179,6 +179,16 @@ do_gcd(void)
stackidx--; stackidx--;
} }
static void
do_rshift(void)
{
if( stackidx < 1 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
}
int int
main(int argc, char **argv) main(int argc, char **argv)
@ -259,6 +269,9 @@ main(int argc, char **argv)
case 'G': case 'G':
do_gcd(); do_gcd();
break; break;
case '>':
do_rshift();
break;
case 'i': /* dummy */ case 'i': /* dummy */
if( !stackidx ) if( !stackidx )
fputs("stack underflow\n", stderr); fputs("stack underflow\n", stderr);

View File

@ -627,6 +627,15 @@ iobuf_write(IOBUF a, byte *buf, unsigned buflen )
return 0; return 0;
} }
int
iobuf_writestr(IOBUF a, const char *buf )
{
for( ; *buf; buf++ )
if( iobuf_writebyte(a, *buf) )
return -1;
return 0;
}
/**************** /****************