openssl 非对称加密 RSA 加密解密以及签名验证签名
1. 简介
openssl rsa.h 提供了密码学中公钥加密体系的一些接口,
本文主要讨论利用rsa.h接口开发以下功能
- 公钥私钥的生成
- 公钥加密,私钥解密
- 私钥加密,公钥解密
- 签名:私钥签名
- 验证签名:公钥验签
2. 生成公钥私钥对
主要接口,
/* Deprecated version */
DEPRECATEDIN_0_9_8(RSA *RSA_generate_key(int bits, unsigned long e, void
(*callback) (int, int, void *),
void *cb_arg)) /* New version */
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
接口调用需要先生成一个大数,如下生成密钥对示例
//生成密钥对
RSA *r = RSA_new();
int bits = ;
BIGNUM *e = BN_new();
BN_set_word(e, );
RSA_generate_key_ex(r, bits, e, NULL);
//打印密钥
RSA_print_fp(stdout, r, );
打印的密钥对结果:
Private-Key: ( bit)
modulus:
:c0::6c:::ed:4e::bb::ec:be:d6::
:bf:9b:be:4f:8b:fb::ae:f2::9c:e7:b8::
a2::9c::cc:4a:a2::1d:::c8:f6:e0::
3a:::c8:1a:d4:b7::::4c:3b:2a::0b:
:::4f:f9
publicExponent: (0x10001)
privateExponent:
:8f::9e:ca:8f:9f::3a:ed:eb:ec:5a::a0:
c1:2f:::::4c::6a:6e:b8:4a:ab:2c::
:e2:3e:c8:aa::bb::9e:e5:::b4:8f::
::dc:::::::ac::f8:fe:4d::
e1:e2:bf:fd:
prime1:
:fd::4d:f0::a0::5e:d1:c9:0e:b8::f9:
ce:0a:ef::e7:a4:::d8:fd:dd:e6:c4:::
dd:e6:
prime2:
:c2::a9:7b:c8:::::f0::9a::a2:
0b::3b::c0::6d:c6:c7:d1:a1::1d:d3:7d:
:cd:
exponent1:
6c::d8:2a:6b:4f::dd:::::f7:b5:c7:
ad:f2::5b:f7:7b:ca:::0c:eb:d3::f9:ac:
:f5
exponent2:
::e2:5a:::db:1e::2a::3c:6a:e7::
ac:e2:d7:a5::5f::c3:4d:cf::d8::7f::
:9d
coefficient:
:d7:0d:9b:e8:2f:3c::::a0:b2:8b::1d:
e2:b9:0f:9f:ca:b2:::ea:c8:9d:5e::e5:e3:
::aa
3. 公钥加密,私钥解密
主要接口
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);
由于较长数据需要分组加密,如下封装了一层
//公钥加密
int kkrsa_public_encrypt(char *inStr,char *outData,RSA *r)
{
int encRet = ;
unsigned long inLen = strlen(inStr);
int pdBlock = RSA_size(r)-;
unsigned int eCount = (inLen / pdBlock) +;
//分组加密,可以看出outData最大不超过malloc[eCount*pdBlock]
for (int i=; i < eCount; i++) {
RSA_public_encrypt(inLen > pdBlock?pdBlock:inLen, inStr, outData, r, RSA_PKCS1_PADDING);
inStr += pdBlock;
outData+=RSA_size(r);
encRet+=RSA_size(r);
inLen -= pdBlock;
}
return encRet;
}
//私钥解密
int kkrsa_private_decrypt(char *inStr,char *outData,RSA *r)
{
int decRet = ;
unsigned long inLen = strlen(inStr);
int pdBlock = RSA_size(r);
unsigned int dCount = inLen / pdBlock;
//分组解密
for (int i=; i < dCount; i++) {
int ret = RSA_private_decrypt(pdBlock, inStr, outData, r, RSA_PKCS1_PADDING);
inStr += pdBlock;
outData+=ret;
decRet+=ret;
}
return decRet;
}
测试例子,例子中的r,就是上面生成的RSA密钥对,
//测试一
printf("block:%d \n",RSA_size(r));
char *src = "this is test encrypt data use RSA_PKCS1_PADDING";
printf("src:%s len=%d\n",src,strlen(src));
char *encDat = malloc();
//公钥加密
int encRet = kkrsa_public_encrypt(src, encDat, r);
printf("enc:%d\n",encRet); char *decDat = malloc();
//私钥解密
int decRet = kkrsa_private_decrypt(encDat, decDat, r);
printf("dec:%s len=%d\n",decDat,decRet); free(encDat);
free(decDat);
打印结果:
block:
src:this is test encrypt data use RSA_PKCS1_PADDING len=
enc:
dec:this is test encrypt data use RSA_PKCS1_PADDING len= test2
src:this is test private encrypt data use RSA_PKCS1_PADDING len=
enc:
dec:this is test private encrypt data use RSA_PKCS1_PADDI len=
4. 私钥加密,公钥解密
主要接口
int RSA_private_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);
同样如果数据较长需要进行分组加密,如下简单封装的接口
//私钥加密
int kkrsa_private_encrypt(char *inStr,char *outData,RSA *r)
{
int encRet = ;
unsigned long inLen = strlen(inStr);
int pdBlock = RSA_size(r)-;
unsigned int eCount = (inLen / pdBlock) +;
//分组加密,可以看出outData最大不超过malloc[eCount*pdBlock]
for (int i=; i < eCount; i++) {
RSA_private_encrypt(inLen > pdBlock?pdBlock:inLen, inStr, outData, r, RSA_PKCS1_PADDING);
inStr += pdBlock;
outData+=RSA_size(r);
encRet+=RSA_size(r);
inLen -= pdBlock;
}
return encRet;
}
//公钥解密
int kkrsa_public_decrypt(char *inStr,char *outData,RSA *r)
{
int decRet = ;
unsigned long inLen = strlen(inStr);
int pdBlock = RSA_size(r);
unsigned int dCount = inLen / pdBlock;
//分组解密
for (int i=; i < dCount; i++) {
int ret = RSA_public_decrypt(pdBlock, inStr, outData, r, RSA_PKCS1_PADDING);
inStr += pdBlock;
outData+=ret;
decRet+=ret;
}
return decRet;
}
调用示例:需要上面生成的密钥对RSA r
//测试二
printf("\ntest2\n");
char *src2 = "this is test private encrypt data use RSA_PKCS1_PADDING";
printf("src:%s len=%d\n",src2,strlen(src2));
char *encDat2 = malloc();
//私钥加密
int encRet2 = kkrsa_private_encrypt(src2, encDat2, r);
printf("enc:%d\n",encRet2); char *decDat2 = malloc();
//公钥解密
int decRet2 = kkrsa_public_decrypt(encDat2, decDat2, r);
printf("dec:%s len=%d\n",decDat2,decRet2); free(encDat2);
free(decDat2);
测试结果:
test2
src:this is test private encrypt data use RSA_PKCS1_PADDING len=
enc:
dec:this is test private encrypt data use RSA_PKCS1_PADDING\\\375۷GO\ len=
5. 签名与验证签名
主要接口
int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen, RSA *rsa);
int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
测试示例,同样需要上面生成的RSA密钥对
//签名
printf("\ntest sign and verify\n");
char *msg = "";
char *sinDat = malloc(RSA_size(r));
int sinLen = ;
RSA_sign(NID_sha1, msg,strlen(msg),sinDat,&sinLen, r); int vret = RSA_verify(NID_sha1, msg, strlen(msg), sinDat, sinLen, r);
printf("sign_verify=%d\n",vret);
打印结果
test sign and verify
sign_verify=
6. 总结
上述RSA分组加密中使用了RSA_PKCS1_PADDING 的补位方式;当然还有如下
不同的补位方式,在进行分组加密时,需要注意分组块的处理
# define RSA_PKCS1_PADDING
# define RSA_SSLV23_PADDING
# define RSA_NO_PADDING
# define RSA_PKCS1_OAEP_PADDING
# define RSA_X931_PADDING
/* EVP_PKEY_ only */
# define RSA_PKCS1_PSS_PADDING # define RSA_PKCS1_PADDING_SIZE
测试使用 openssl 1.1.0c
参考:https://www.openssl.org/docs/man1.0.2/crypto/RSA_public_encrypt.html
https://www.openssl.org/docs/manmaster/man3/RSA_verify.html
openssl 非对称加密 RSA 加密解密以及签名验证签名的更多相关文章
- Cryptopp iOS 使用 RSA加密解密和签名验证签名
Cryptopp 是一个c++写的功能完善的密码学工具,类似于openssl 官网:https://www.cryptopp.com 以下主要演示Cryptopp 在iOS上的RSA加密解密签名与验证 ...
- JAVA的非对称加密算法RSA——加密和解密
原文转载至:https://www.cnblogs.com/OnlyCT/p/6586856.html 第一部分:RSA算法原理与加密解密 一.RSA加密过程简述 A和B进行加密通信时,B首先要生成一 ...
- C++调用openssl库生成RSA加密秘钥对
直接上代码.默认生成的是pkcs#1格式 // ---- rsa非对称加解密 ---- // #define KEY_LENGTH 1024 // 密钥长度 #define PUB_KEY_FILE ...
- openssl 非对称加密算法RSA命令详解
1.非对称加密算法概述 非对称加密算法也称公开密钥算法,其解决了对称加密算法密钥分配的问题,非对称加密算法基本特点如下: 1.加密密钥和解密密钥不同 2.密钥对中的一个密钥可以公开 3.根据公开密钥很 ...
- openssl C语言编码实现rsa加密
非原创, 引用自: 1 CC=gcc CPPFLAGS= -I /home/yyx//openssl-1.0.1t/include/ CFLAGS=-Wall -g LIBPATH = -L /usr ...
- 最通俗易懂的RSA加密解密指导
前言 RSA加密算法是一种非对称加密算法,简单来说,就是加密时使用一个钥匙,解密时使用另一个钥匙. 因为加密的钥匙是公开的,所又称公钥,解密的钥匙是不公开的,所以称为私钥. 密钥 关于RSA加密有很多 ...
- MD5,Des,RSA加密解密
一.加密和解密 下面先熟悉几个概念 1>对称加密:加密的key和解密的key是同一个 但是如何确保密钥安全地进行传递?秘钥的安全是一个问题 2>非对称加密:加密点的key和解密的key不是 ...
- 全面解决.Net与Java互通时的RSA加解密问题,使用PEM格式的密钥文件
作者: zyl910 一.缘由 RSA是一种常用的非对称加密算法.所以有时需要在不用编程语言中分别使用RSA的加密.解密.例如用Java做后台服务端,用C#开发桌面的客户端软件时. 由于 .Net.J ...
- RSA非对称加密,使用OpenSSL生成证书,iOS加密,java解密
最近换了一份工作,工作了大概一个多月了吧.差不多得有两个月没有更新博客了吧.在新公司自己写了一个iOS的比较通用的可以架构一个中型应用的不算是框架的一个结构,并已经投入使用.哈哈 说说文章标题的相关的 ...
随机推荐
- MySQL错误:The user specified as a definer (XXX@XXX) does not exist
今天由于更换服务器,重新再本地备份了数据库,试运行程序报错,如下: MySQL错误:The user specified as a definer (XXX@XXX) does not exist 意 ...
- php用正则检测某字段开头是否为字母
//判断数组都已字段的开头是否为字母 $data=array(); for($i=0;$i<$length;$i++){ //是,则把数组重新取出赋值if (preg_match(" ...
- 在Excel表格中输入一大段文字
1.有时为了注释的需要,在excel中需要输入一大段文字,这时候可以使用—视图-工具-绘图,然后选择下面的文本框,即可自定义文本框大小,如需要文本框和表格边框完全重合,在鼠标画文本框时按住 Alt键.
- PhpStorm设置编码
PhpStorm是一个轻量级且便捷的PHP IDE,其旨在提供用户效率,可深刻理解用户的编码,提供智能代码补全,快速导航以及即时错误检查. 本文为大家讲解的是如何设置phpstorm 编辑器的编码,感 ...
- C++术语俗解
C++作为一种复杂的编程语言,其最晦涩的莫过于各个术语. 以下就经常使用的术语,逐个俗解(特别声明:为了对术语的更好理解与记忆,仅代表个人的俗识,若有不妥之处望给予指正),分享共勉. 内存:一片计算机 ...
- 判断是否IPv6网络
bool isIPV6Net(const std::string ip_v4, std::string& out_ip) { bool is_v6 = false; struct addrin ...
- 如何:在 ASP.NET 网页中检测浏览器类型
https://msdn.microsoft.com/zh-cn/library/3yekbd5b(VS.80).aspx private void Button1_Click(object send ...
- 数据分析 - 开放街道地图(OpenStreetMap)
数据分析 - 开放街道地图(OpenStreetMap) Reinhard使用OpenStreetMap的开放地图数据作为本次数据分析的数据源,使用Python进行数据清洗,使用MongoDB进行数据 ...
- selenium测试(Java)--多窗口切换(十三)
selenium测试(Java)--多窗口切换(十三) 如果遇到点击按钮或链接后出现新窗口的情况,就需要使用窗口切换的方法. 本例中就是先打开百度搜索界面,然后利用js打开一个百度新闻界面,然后通过s ...
- 8. apache服务实验笔记
Apache服务器 一 简介 1 www:world wide web 万维网 http 协议: 超文本传输协议 HTML语言: 超文本标识语言 2 URL:统一资源定位 协议+域名:端口+网页文 ...