• 使用polarssl进行RSA加密解密


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

    下载和编译

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

    image

    默认似乎是没有导出函数的,所以直接把源码放入自己工程内使用,新建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
    ",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
    ",output);
        system("pause");
        return 0;
    }
    编译后gcm.c第202行可能会报错,将0x03FFFFE0llu改为0x03FFFFE0ull即可。

    运行结果:

    image

    使用已有公钥加密

    假设已经获得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
    ",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
    ",output);
        system("pause");
        return 0;
    }
  • 相关阅读:
    Mybatis Plus整合PageHelper分页的实现示例
    关于xlrd最新版本不支持.xlsx文件的解决办法
    mysql 错误解决大法 Specified key was too long; max key length is 767 bytes
    php连接redis
    flask通过request.path获取定义view函数的文件和行号
    使用bash内置命令complete来实现参数补全
    linux下对比两个文件夹下python文件的差异
    ssh登录后自动切换到原来的目录
    ssh &2>1 和重定向顺序问题
    wsl1(win10)中安装bochs
  • 原文地址:https://www.cnblogs.com/Reyzal/p/5192355.html
Copyright © 2020-2023  润新知