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 加密解密以及签名验证签名的更多相关文章

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

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

  2. JAVA的非对称加密算法RSA——加密和解密

    原文转载至:https://www.cnblogs.com/OnlyCT/p/6586856.html 第一部分:RSA算法原理与加密解密 一.RSA加密过程简述 A和B进行加密通信时,B首先要生成一 ...

  3. C++调用openssl库生成RSA加密秘钥对

    直接上代码.默认生成的是pkcs#1格式 // ---- rsa非对称加解密 ---- // #define KEY_LENGTH 1024 // 密钥长度 #define PUB_KEY_FILE ...

  4. openssl 非对称加密算法RSA命令详解

    1.非对称加密算法概述 非对称加密算法也称公开密钥算法,其解决了对称加密算法密钥分配的问题,非对称加密算法基本特点如下: 1.加密密钥和解密密钥不同 2.密钥对中的一个密钥可以公开 3.根据公开密钥很 ...

  5. openssl C语言编码实现rsa加密

    非原创, 引用自: 1 CC=gcc CPPFLAGS= -I /home/yyx//openssl-1.0.1t/include/ CFLAGS=-Wall -g LIBPATH = -L /usr ...

  6. 最通俗易懂的RSA加密解密指导

    前言 RSA加密算法是一种非对称加密算法,简单来说,就是加密时使用一个钥匙,解密时使用另一个钥匙. 因为加密的钥匙是公开的,所又称公钥,解密的钥匙是不公开的,所以称为私钥. 密钥 关于RSA加密有很多 ...

  7. MD5,Des,RSA加密解密

    一.加密和解密 下面先熟悉几个概念 1>对称加密:加密的key和解密的key是同一个 但是如何确保密钥安全地进行传递?秘钥的安全是一个问题 2>非对称加密:加密点的key和解密的key不是 ...

  8. 全面解决.Net与Java互通时的RSA加解密问题,使用PEM格式的密钥文件

    作者: zyl910 一.缘由 RSA是一种常用的非对称加密算法.所以有时需要在不用编程语言中分别使用RSA的加密.解密.例如用Java做后台服务端,用C#开发桌面的客户端软件时. 由于 .Net.J ...

  9. RSA非对称加密,使用OpenSSL生成证书,iOS加密,java解密

    最近换了一份工作,工作了大概一个多月了吧.差不多得有两个月没有更新博客了吧.在新公司自己写了一个iOS的比较通用的可以架构一个中型应用的不算是框架的一个结构,并已经投入使用.哈哈 说说文章标题的相关的 ...

随机推荐

  1. HTA全解析:给VBS和JS一个强大的交互界面

    1.概述 HTA全称Html Application,在Windows中由mshta.exe加载执行,是一种本地程序.可使用html元素来构建界面,用JS或VBS来构建执行逻辑,从而强化Windows ...

  2. css2 [lang|=en] 误区

    [lang|=en] w3c说明:css2选择器,选择以en开头的的lang属性. w3c的这个解释是有误区的,en开头,但是en后面必须要有-,也就是说是选择的是en-开头

  3. failed to lazily initialize a collection of role:XXX, no sessi

    系统 框架  springMVC+hibernate 这种情况 由于 hibernate 的 懒汉机制,和 Spring 事务机制(不确定)造成的 由于 spring 配置的时候,在service 层 ...

  4. EditPlus 3.8.1346 中文版(6月16日更新)

    新的版本增加了粘贴时自动调整行首缩进的功能(“编辑”菜单→剪贴板→粘贴时自动缩进),非常方便.建议各位马上更新.

  5. 7.Git的版本退回

    现在,你已经学会了修改文件,然后把修改提交到Git版本库,现在,再练习一次,修改readme.txt文件如下: Git is a distributed version control system. ...

  6. WCF、MongoDB

    http://www.cnblogs.com/quietwalk/archive/2011/08/09/2132573.html http://www.cnblogs.com/huangxinchen ...

  7. c#控制台調用SSIS包互传值

    有时候不仅仅需要在内部执行package包,多数情况下,是需要在外部进行调用,比如,需要一个批处理或者控制台程序进行外部调用SSIS包,而往往这个包所配置的连接字符串是经过加密处理的,所以当外部调用S ...

  8. Linux:-杀进程的技巧

    <---kill进程的技巧---> 1.杀掉某个关键字的进程 pgrep -f 2.批量杀掉某个关键字的进程 pkill - "name" 3.批量杀掉多个关键字的进程

  9. 电脑装的是office2013,右键新建却是2007,或者右键新建菜单中没有excel2013问题解决办法。

    我的office出现了两个问题,因为工作比较忙,也没有着急解决,今天实在受不了了,花费一下午才找到解决方法. 原来万恶之源都是可恶的wps,以后千万不安装kingsoft了. 第一个问题:excel打 ...

  10. css3样式二

    1.2D转换 通过 translate() 方法,元素从其当前位置移动,根据给定的 left(x 坐标) 和 top(y 坐标) 位置参数 如:div{transform: translate(50p ...