RSA的公私钥生成过程
步骤 | 说明 | 描述 |
1 | 选择一对不相等且足够大的质数 | p,q |
2 | 计算两个质数的乘积 | n=p*q |
3 | 计算的n的欧拉函数 | φ(n)=(p-1)(q-1) |
4 | 选择一个与φ(n)互质的整数e | 1<e<φ(n) |
5 | 计算e对于φ(n)的模反d | demodφ(n)=1 |
6 | 公钥 | e,n |
7 | 私钥 | d,n |
RSA加解密过程
M^emodn=C
C^dmodn=M
1、生成RSA密钥对
1)创建一个RSA对象,用来存放密钥对。这个RSA对象需要手动释放;
RSA *RSA_new(void);
2)准备公钥指数E,在OpenSSL中用一个大数结构体BIGNUM存放,公钥指数可以指定为默认值65537;
BIGNUM *BN_new(void); int BN_set_word(BIGNUM *a, BN_ULONG w);
3)生成私钥指数D和模数N,也就是生成RSA密钥对;
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
4)可以通过以下接口拿到D、N、E
const BIGNUM *RSA_get0_n(const RSA *d); const BIGNUM *RSA_get0_e(const RSA *d); const BIGNUM *RSA_get0_d(const RSA *d);
产生密钥对代码实现
RSA* creatRSAkey() { //r存放RSA密钥对 RSA*r=RSA_new(); //大数结构体 公钥质数 大质数 //公钥(E,N) BIGNUM *e = BN_new(); //创建好了大数 BN_set_word(e, RSA_F4); //公钥指数使用默认值 RSA_F4 65537,也可以使用随机值 //生成私钥指数D和N RSA_generate_key_ex(r, 512, //指定密钥长度为512bit e, NULL); return r; }
2、RSA的填充
RSA的填充方式选为RSA_PKCS1_PADDING,要求输入的明文长度比RSA密钥长度短至少11个字节。长度如下:
输入明文长度:keysize- 11;
加密后的密文长度为:keysize;
输入密文长度:keysize;
解密后的明文长度为:keysize- 11;
3、加解密接口
//@flen明文长度@from明文@to密文@rsa密钥@padding填充方式 int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding); int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
加密代码实现
由于密钥长度keysize设置为64字节,将原始明文划分为53(keysize-11)字节的整数倍,分块加密。每块输出密文长度为keysize64字节。
int RSAEncrypto(unsigned char *data, int datasize, RSA*r, unsigned char *outdata) { //keysize=64字节512bit //输入数据大小=64-11=53 int blocksize = RSA_size(r) - RSA_PKCS1_PADDING_SIZE; int outsize = 0; for (int i = 0; i < datasize; i += blocksize) { int ensize = blocksize; if (datasize - i < blocksize) { ensize = datasize - i; } int outoff = i + RSA_PKCS1_PADDING_SIZE * (i / blocksize); int ret = RSA_public_encrypt(ensize, data + i,
outdata + outoff, r, RSA_PKCS1_PADDING); if (ret < 0) { ERR_print_errors_fp(stderr); } outsize = outoff + RSA_size(r); } return outsize; }
解密代码实现
密文都是keysize的整数倍,每块密文解密后的明文长度为keysize-11;
int RSAdecrypto(unsigned char *data, int datasize, RSA*r, unsigned char*outdata) { int ensize = RSA_size(r); int outoff = 0; for (int i = 0; i < datasize; i += ensize) { int len=RSA_private_decrypt(ensize, data+i,
outdata+outoff, r, RSA_PKCS1_PADDING); outoff += len; } return outoff; }