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加密解密的更多相关文章

  1. 兼容javascript和C#的RSA加密解密算法,对web提交的数据进行加密传输

    Web应用中往往涉及到敏感的数据,由于HTTP协议以明文的形式与服务器进行交互,因此可以通过截获请求的数据包进行分析来盗取有用的信息.虽然https可以对传输的数据进行加密,但是必须要申请证书(一般都 ...

  2. iOS使用Security.framework进行RSA 加密解密签名和验证签名

    iOS 上 Security.framework为我们提供了安全方面相关的api: Security框架提供的RSA在iOS上使用的一些小结 支持的RSA keySize 大小有:512,768,10 ...

  3. openssl evp RSA 加密解密

    openssl evp RSA 加密解密 可以直接使用RSA.h 提供的接口 如下测试使用EVP提供的RSA接口 1. EVP提供的RSA 加密解密 主要接口: int EVP_PKEY_encryp ...

  4. C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法

    因为C#的RSA加密解密只有公钥加密,私钥解密,没有私钥加密,公钥解密.在网上查了很久也没有很好的实现.BouncyCastle的文档少之又少.很多人可能会说,C#也是可以的,通过Biginteger ...

  5. Cryptopp iOS 使用 RSA加密解密和签名验证签名

    Cryptopp 是一个c++写的功能完善的密码学工具,类似于openssl 官网:https://www.cryptopp.com 以下主要演示Cryptopp 在iOS上的RSA加密解密签名与验证 ...

  6. C# Java间进行RSA加密解密交互

    原文:C# Java间进行RSA加密解密交互 这里,讲一下RSA算法加解密在C#和Java之间交互的问题,这两天纠结了很久,也看了很多其他人写的文章,颇受裨益,但没能解决我的实际问题,终于,还是被我捣 ...

  7. C# Java间进行RSA加密解密交互(二)

    原文:C# Java间进行RSA加密解密交互(二) 接着前面一篇文章C# Java间进行RSA加密解密交互,继续探讨这个问题. 在前面,虽然已经实现了C# Java间进行RSA加密解密交互,但是还是与 ...

  8. C# Java间进行RSA加密解密交互(三)

    原文:C# Java间进行RSA加密解密交互(三) 接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在上篇中为了实现 /** * RSA加密 * @param text--待加密的明文 ...

  9. RSA加密解密及数字签名Java实现--转

    RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院 ...

随机推荐

  1. PHP设计模式——工厂模式

    <?php /** * 工厂模式 * 提供获取某个对象的新实例的一个接口,同时使调用代码避免确定实际实例化基类的步骤. * * 工厂类用于创建不同类的实例,并将其返回. */ /** * 服务端 ...

  2. 【洛谷P2831】[NOIP2016]愤怒的小鸟

    愤怒的小鸟 题目链接 本来是刷状压DP的,然而不会.. 搜索是比较好想的,直接dfs就行了 我们可以知道两只猪确定一条抛物线 依次处理每一只猪,有以下几种方法: 1.先看已经建立的抛物线是否能打到这只 ...

  3. iOS程序的启动原理

    一.在一些老的项目中,有很多不是通过代码添加窗口和跟控制器.是通过设置MainInterface(设置最主要的xib),在xib中通过图形化的操作设置应用程序的代理->设置窗口->设置根控 ...

  4. Java 加密Excel文件(打开时需输入密码)

    收集:author: lifq package com.XXX.XXX.utils; import java.io.IOException; import com.jxcell.CellExcepti ...

  5. jenkins添加环境变量 ,win 10的 环境变量如下,win7 就是不加也可以运行,不报 “python 不是内部命令 ” 的错误。

    jenkins 添加win 10的 环境变量如下,win7 就是不加也可以运行,不报 “python 不是内部命令 ” 的错误,暂时不知道怎么回事.    jenkins这样添加环境变量 .

  6. 【SHOI2015】脑洞治疗仪(恶心的线段树,区间最大子段和)

    题目描述: 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.11代表这个位 ...

  7. python 用selenuim判断页面是否全部加载完成,并且加上最大时长,超过时长报错

    STR_READY_STATE = '' time_start = time.time() while STR_READY_STATE != 'complete': time.sleep(0.001) ...

  8. PHP无法用下标访问

    php数组分为普通数组和关联数组,普通数组可以用下标访问,而关联数组不可以.

  9. 【c学习-14】

    /*练习*/ #include int testFeiunction(b[],n){ b[1]=1; n=10; } int main(){ int a[10]={1,2,3,4,5}; int n= ...

  10. windows 下安装pyspider

    今天主要介绍一下在Windows下安装pyspider,pyspider是一款用python编写的网络爬虫框架,这个框架最好是在linux下运行,Windows下运行可能会出现兼容性问题,如果实在要在 ...