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; }