使用polarssl进行RSA加密解密

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用polarssl进行RSA加密解密相关的知识,希望对你有一定的参考价值。

RSA算法的原理就不提了,网上有很多介绍的文章,因为项目中使用RSA加密,所以需要找一个RSA加密的算法,之前尝试过使用Crypto++库,无奈Crypto++其中使用了大量的模版,各种继承,看着头大,github上一些个人代码又不敢使用,最后选用了polarssl内的RSA算法,本文主要讲解VS2010如何使用polarssl内的RSA模块来进行RSA加密解密,方便自己和大家以后使用。

下载和编译

polarssl被ARM 公司收购,并改名为 mbed TLS,可以从其官网下载,或者从这里下载之前版本。博主下载的是polarssl-1.2.17版本,下载完成后解压,目录结构如下:

技术分享

默认似乎是没有导出函数的,所以直接把源码放入自己工程内使用,新建win32控制台项目,将Library下的所有文件以及include目录下的polarssl目录复制到项目目录,增加一个文件,写入如下内容:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string>

#include "polarssl/entropy.h"
#include "polarssl/ctr_drbg.h"
#include "polarssl/rsa.h"
#include "polarssl/aes.h"
#include "polarssl/base64.h"

const unsigned int RSA_KEY_SIZE = 1024;        // RSA 公钥的位数
const unsigned int AES_KEY_SIZE = 256;
const unsigned int EXPONENT = 65537;
const unsigned int BUFFER_SIZE = 1024;

class rsa
{
public:
    rsa()
    {
        memset(rsa_n, 0, BUFFER_SIZE);
        memset(rsa_e, 0, BUFFER_SIZE);
        memset(rsa_d, 0, BUFFER_SIZE);
        memset(rsa_p, 0, BUFFER_SIZE);
        memset(rsa_q, 0, BUFFER_SIZE);
        memset(rsa_dp, 0, BUFFER_SIZE);
        memset(rsa_dq, 0, BUFFER_SIZE);
        memset(rsa_qp, 0, BUFFER_SIZE);   
        n_len = BUFFER_SIZE;
        e_len = BUFFER_SIZE;
        d_len = BUFFER_SIZE;
        p_len = BUFFER_SIZE;
        q_len = BUFFER_SIZE;
        dp_len = BUFFER_SIZE;
        dq_len = BUFFER_SIZE; 
        qp_len = BUFFER_SIZE;
    }

    unsigned char    rsa_n[BUFFER_SIZE];
    unsigned char    rsa_e[BUFFER_SIZE];
    unsigned char    rsa_d[BUFFER_SIZE];
    unsigned char    rsa_p[BUFFER_SIZE];
    unsigned char    rsa_q[BUFFER_SIZE];
    unsigned char    rsa_dp[BUFFER_SIZE];
    unsigned char    rsa_dq[BUFFER_SIZE];
    unsigned char    rsa_qp[BUFFER_SIZE];

    unsigned int n_len;
    unsigned int e_len;
    unsigned int d_len;
    unsigned int p_len;
    unsigned int q_len;
    unsigned int dp_len;
    unsigned int dq_len; 
    unsigned int qp_len;
};

void generate_rsa(rsa& r)
{
    // 生成RSA密钥对
    rsa_context    rsa;
    entropy_context    entropy;
    ctr_drbg_context    ctr_drbg;

    entropy_init(&entropy);

    assert(ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, nullptr, 0) == 0);

    rsa_init(&rsa, RSA_PKCS_V15, 0);

    assert(rsa_gen_key(&rsa, ctr_drbg_random, &ctr_drbg, RSA_KEY_SIZE, EXPONENT) == 0);

    assert(mpi_write_binary(&rsa.N, r.rsa_n, BUFFER_SIZE) == 0);
    assert(mpi_write_binary(&rsa.E, r.rsa_e, BUFFER_SIZE) == 0);
    assert(mpi_write_binary(&rsa.D, r.rsa_d, BUFFER_SIZE) == 0);
    assert(mpi_write_binary(&rsa.P, r.rsa_p, BUFFER_SIZE) == 0);
    assert(mpi_write_binary(&rsa.Q, r.rsa_q, BUFFER_SIZE) == 0);
    assert(mpi_write_binary(&rsa.DP, r.rsa_dp, BUFFER_SIZE) == 0);
    assert(mpi_write_binary(&rsa.DQ, r.rsa_dq, BUFFER_SIZE) == 0);
    assert(mpi_write_binary(&rsa.QP, r.rsa_qp, BUFFER_SIZE) == 0);

    //写入文件保存,每个间隔1024字节
    FILE * fp = fopen("rsa","wb");
    fwrite(r.rsa_n,BUFFER_SIZE,1,fp);
    fwrite(r.rsa_e,BUFFER_SIZE,1,fp);
    fwrite(r.rsa_d,BUFFER_SIZE,1,fp);
    fwrite(r.rsa_p,BUFFER_SIZE,1,fp);
    fwrite(r.rsa_q,BUFFER_SIZE,1,fp);
    fwrite(r.rsa_dp,BUFFER_SIZE,1,fp);
    fwrite(r.rsa_dq,BUFFER_SIZE,1,fp);
    fwrite(r.rsa_qp,BUFFER_SIZE,1,fp);
    fclose(fp);
}

void read_rsa(rsa& r)
{
    //读取保存的RSA相关信息
    FILE * fp = fopen("rsa","rb");
    fread(r.rsa_n,BUFFER_SIZE,1,fp);
    fread(r.rsa_e,BUFFER_SIZE,1,fp);
    fread(r.rsa_d,BUFFER_SIZE,1,fp);
    fread(r.rsa_p,BUFFER_SIZE,1,fp);
    fread(r.rsa_q,BUFFER_SIZE,1,fp);
    fread(r.rsa_dp,BUFFER_SIZE,1,fp);
    fread(r.rsa_dq,BUFFER_SIZE,1,fp);
    fread(r.rsa_qp,BUFFER_SIZE,1,fp);
    fclose(fp);
}

// 加密
void encrypt(
    const rsa &r, 
    const unsigned char* plaintext, 
    unsigned int plaintext_size, 
    unsigned char *ciphertext, 
    unsigned int *ciphertext_size)
{
    rsa_context            rsa;
    entropy_context        entropy;
    ctr_drbg_context    ctr_drbg;

    entropy_init(&entropy);
    assert(ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, nullptr, 0) == 0);

    rsa_init(&rsa, RSA_PKCS_V15, 0);

    assert(mpi_read_binary(&rsa.N, r.rsa_n, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.E, r.rsa_e, BUFFER_SIZE) == 0);

    *ciphertext_size = rsa.len = (mpi_msb(&rsa.N) + 7) >> 3;

    assert(rsa_pkcs1_encrypt(&rsa, ctr_drbg_random, &ctr_drbg, RSA_PUBLIC, plaintext_size, plaintext, ciphertext) == 0);
}

// 解密
void decrypt(
    const rsa &r, 
    const unsigned char* ciphertext, 
    unsigned int ciphertext_size, 
    unsigned char *plaintext, 
    unsigned int &plaintext_size)
{
    rsa_context            rsa;
    entropy_context        entropy;
    ctr_drbg_context    ctr_drbg;

    entropy_init(&entropy);
    assert(ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, nullptr, 0) == 0);

    rsa_init(&rsa, RSA_PKCS_V15, 0);

    assert(mpi_read_binary(&rsa.N, r.rsa_n, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.E, r.rsa_e, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.D, r.rsa_d, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.P, r.rsa_p, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.Q, r.rsa_q, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.DP, r.rsa_dp, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.DQ, r.rsa_dq, BUFFER_SIZE) == 0);
    assert(mpi_read_binary(&rsa.QP, r.rsa_qp, BUFFER_SIZE) == 0);

    rsa.len = (mpi_msb(&rsa.N) + 7) >> 3;

    assert(rsa_pkcs1_decrypt(&rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, &plaintext_size, ciphertext, plaintext, plaintext_size) == 0);
}


int main()
{
    rsa    r;
    generate_rsa(r);
    //read_rsa(r);从generate_rsa保存的RSA文件中读取RSA参数信息

    unsigned char    plaintext[] = "testrsa";
    unsigned char    ciphertext[BUFFER_SIZE] = { 0 };
    unsigned int    ciphertext_len = BUFFER_SIZE;
    encrypt(r, plaintext, sizeof(plaintext), ciphertext, &ciphertext_len);
    
    size_t dstlen = 0;
    base64_encode(NULL,&dstlen,ciphertext,ciphertext_len);//第一次获取目标长度
    unsigned char* dstbuf = new unsigned char[dstlen+1];
    memset(dstbuf,0,dstlen+1);
    base64_encode(dstbuf,&dstlen,ciphertext,ciphertext_len);//转换为BASE64编码
    printf("%s\\n",dstbuf);

    unsigned char    output[BUFFER_SIZE] = { 0 };
    unsigned int    output_len = BUFFER_SIZE;

    dstlen = 0;
    base64_decode(NULL,&dstlen,dstbuf,strlen((const char*)dstbuf));
    unsigned char* srcbuf = new unsigned char[dstlen];
    base64_decode(srcbuf,&dstlen,dstbuf,strlen((const char*)dstbuf));

    decrypt(r, srcbuf, dstlen, output, output_len);
    printf("%s\\n",output);
    system("pause");
    return 0;
}
编译后gcm.c第202行可能会报错,将0x03FFFFE0llu改为0x03FFFFE0ull即可。

运行结果:

技术分享

使用已有公钥加密

假设已经获得RSA相关参数信息,则只需要将参数设置即可,不需要重新生成RSA密钥信息,上述代码中将main函数改为如下即可测试:

int main()
{
    rsa    r;
    //generate_rsa(r);
    read_rsa(r);//从generate_rsa保存的RSA文件中读取RSA参数信息

    unsigned char    plaintext[] = "testrsa";
    unsigned char    ciphertext[BUFFER_SIZE] = { 0 };
    unsigned int    ciphertext_len = BUFFER_SIZE;
    encrypt(r, plaintext, sizeof(plaintext), ciphertext, &ciphertext_len);
    
    size_t dstlen = 0;
    base64_encode(NULL,&dstlen,ciphertext,ciphertext_len);//第一次获取目标长度
    unsigned char* dstbuf = new unsigned char[dstlen+1];
    memset(dstbuf,0,dstlen+1);
    base64_encode(dstbuf,&dstlen,ciphertext,ciphertext_len);//转换为BASE64编码
    printf("%s\\n",dstbuf);

    unsigned char    output[BUFFER_SIZE] = { 0 };
    unsigned int    output_len = BUFFER_SIZE;

    dstlen = 0;
    base64_decode(NULL,&dstlen,dstbuf,strlen((const char*)dstbuf));
    unsigned char* srcbuf = new unsigned char[dstlen];
    base64_decode(srcbuf,&dstlen,dstbuf,strlen((const char*)dstbuf));

    decrypt(r, srcbuf, dstlen, output, output_len);
    printf("%s\\n",output);
    system("pause");
    return 0;
}

以上是关于使用polarssl进行RSA加密解密的主要内容,如果未能解决你的问题,请参考以下文章

利用openssl进行RSA加密解密

RSA 加密解密

使用OpenSSL进行RSA非对称加密(C++版本)

使用OpenSSL进行RSA非对称加密(C++版本)

使用OpenSSL进行RSA非对称加密(C++版本)

使用OpenSSL进行RSA非对称加密(C++版本)