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. ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 A、Saving Tang Monk II 【状态搜索】

    任意门:http://hihocoder.com/problemset/problem/1828 Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制:25 ...

  2. onInterceptTouchEvent和onTouchEvent调用关系详解 ...

    http://blog.csdn.net/lvxiangan/article/details/9309927 老实说,这两个小东东实在是太麻烦了,很不好懂,我自己那api文档都头晕,在网上找到很多资料 ...

  3. 通过sql语句查询出来的结果字段没有到对应实体类时的处理方法

    通过sql语句查询出来的结果字段没有到对应实体类时的处理方法,对于Person类获取用户第一个名字和年龄两个字段,常见的有两种方式: 1.在创建一个与查询结果字段对应的类,然后通过构造函数实现: Qu ...

  4. opencv 数据类型转换:CvArr, Mat, CvMat, IplImage, BYTE 转

    留着以后查询: http://blog.csdn.net/augusdi/article/details/8863820 一.Mat类型:矩阵类型,Matrix. 在openCV中,Mat是一个多维的 ...

  5. Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition

    Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition Kaiming He, Xiangyu Zh ...

  6. 配置两台Azure服务器,一台加入另一台的ad域加入不进去的问题

    AD服务器   10.0.0.4 数据库服务器    10.0.0.5 将数据库服务器加入到AD域中,需要将Azure的DNS改成10.0.0.4 Copy一下

  7. jquery mobile 移动web(3)

    可折叠功能块. div 元素的 data-role 属性设置为 collapsible 代码如下: <div data-role="collapsible"> < ...

  8. vue项目中使用vuex

    1.运行 cnpm i vuex -S 2.导入包 import Vuex from 'vuex' 3.注册vuex到vue中 Vue.use(vuex) 4. var store = new Vue ...

  9. Tomcat服务器的介绍、安装配置

    [1] Tomcat服务器的介绍 1.是一个免费的.开饭源代码的Servlet服务器,目前非常流行. 2.Tomcat服务器是Apache软件基金会的一个顶级项目,由Apache.Sun等公司共同开发 ...

  10. MySQL的Root用户密码

    缘由:最近北京市二环内大兴土木,各种挖沟埋线.忽而一纸通令周末断电,故多年不断电的服务器,便令人有了关机后是否还能正常启动的隐忧.其中一台较年迈的服务器中搭载有MySQL数据库.数据库内容本属于外包项 ...