用libtommath实现RSA算法

RSA算法描述:

1) 选择两个大素数 p、q, 计算 n = p*q;

2) 产生 e, d 使:

    e*d = 1mod(p-1)(q-1)

    e 与 (p-1)(q-1) 互质

[公钥] e、n

[私钥] d、n

3) 加密:

    c = m^d mod n

4) 解密:

    m = c^e mod n

--------------------------------------------------------------------------------------

libtommath是一个大数算法库。以下的代码是用这个库中的函数实现的,相当简单。

#include <tommath.h>
typedef struct {
	int bits;			/* bits in key */
	mp_int n;			/* modulus */
	mp_int e;			/* public exponent */
	mp_int d;			/* private exponent */
}rsa_key;
int rsa_rng(unsigned char *dst, int len, void *dat)
{
	int x;
	for (x = 0; x < len; x++)   dst[x] = rand() & 0xFF;
	return len;
}
int rsa_preme_random( mp_int *a, int bits )
{
	int err = mp_prime_random_ex( a, 8, bits, LTM_PRIME_2MSB_ON|LTM_PRIME_SAFE, rsa_rng, NULL );
	if (err != MP_OKAY) {
		return -1;
	}
	return 0;
}
int rsa_gen_key( rsa_key *key, int bits )
{
	mp_int p, q;
	mp_int sp, sq;
	mp_int n, m;
	mp_int e, d;
	mp_int t;
	//init mp_ints
	mp_init( &p );	mp_init( &q );	mp_init( &sp );	mp_init( &sq );
	mp_init( &n );	mp_init( &m );	mp_init( &e );	mp_init( &d ); 	mp_init( &t );
	//genarate p & q
	rsa_preme_random( &p, bits/2 );
	rsa_preme_random( &q, bits/2 );
	//make n & m
	mp_sub_d( &p, 1, &sp );
	mp_sub_d( &q, 1, &sq );
	mp_mul( &p, &q, &n );
	mp_mul( &sp, &sq, &m );
	
	//make e & d 
	mp_set( &e, 127 );
	retry_e:
	mp_gcd( &e, &m, &t );
	if( ( mp_cmp_d(&t, 1) ) > 0 ){
		mp_add_d( &e, 2, &e );
		goto retry_e;
	}
	mp_invmod( &e, &m, &d );
	//copy n d e to key struct
	mp_init( &key->n );
	mp_init( &key->d );
	mp_init( &key->e );
	key->bits = bits;
	mp_copy( &n, &key->n );
	mp_copy( &d, &key->d );
	mp_copy( &e, &key->e );
	
	mp_clear( &p );	mp_clear( &q );	mp_clear( &sp );mp_clear( &sq );
	mp_clear( &n );	mp_clear( &m );	mp_clear( &e );	mp_clear( &d );	mp_clear( &t );
	return 0;
}
/*set rsa key by string */
int rsa_set_key( rsa_key *key, char *sn, char *se, char *sd, int bits, int radix )
{
	key->bits = bits;
	mp_init( &key->n );
	mp_init( &key->d );
	mp_init( &key->e );
	if( sn )	mp_read_radix( &key->n, sn, radix );
	if( se )	mp_read_radix( &key->e, se, radix );
	if( sd )	mp_read_radix( &key->d, sd, radix );
	
	return 0;
}
/*encrypt by private key */
int rsa_encrypt(mp_int *c, mp_int *m, rsa_key *key)
{
	mp_exptmod( c, &key->d, &key->n, m );
	return 0;
}
/*decrypt by public key */
int rsa_decrypt(mp_int *m, mp_int *c, rsa_key *key)
{
	mp_exptmod( m, &key->e, &key->n, c );	
	return 0;
}
int rsa_test()
{
	mp_int	c, m;
	rsa_key key;
	char sn[] = "BB7F51983FD8707FD6227C23DEF5D5377A5A737CEF3C5252E578EFE136DF87B50473F9341F1640C8D258034E14C16993FCE6C6B8C3CEEB65FC8FBCD8EB77B3B05AC7C4D09E0FA1BA2EFE87D3184DB6718AE41A7CAD89B8DCE0FE80CEB523D5D647F9DB58A31D2E71AC677E67FA6E75820736C9893761EE4ACD11F31DBDC349EF";
	char se[] = "010001";
	char sm[] = "AA7B0BF4AAE8B7C2ECC485ACFA57770E50BB9207233E4278654717E470691981C187F81FFC3B90895063EF98C0D86B5297B655399309E6699FEE2270B0F3431B5ABAD7E516261926C35BF6BBFEFB49366EBE96DC510E9CBD915337E8188D517D15DCF90298C40233EEEAFD5A9459F5D3410E6B89B44DF6E818FA3594EF935534";
	char sc[1024];
	mp_init( &c );
	mp_init( &m );
	rsa_set_key( &key, sn, se, NULL, 128, 16 ); 
	mp_read_radix( &m, sm, 16 );
	rsa_decrypt( &m, &c, &key );
	mp_toradix( &c, sc, 16 );
	printf("%s\n", sc);
	return 0;
}
posted @ 2010-11-10 17:30  linxr  阅读(3649)  评论(2编辑  收藏  举报