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. SVD java 算法实现

    https://github.com/Richard-Cao/MatrixSvdDemo/blob/master/app/src/main/java/me/ele/caolicheng/matrixs ...

  2. [整理]Centos6.5 + hadoop2.6.4环境搭建

    搭建Hadoop集群环境(3台机器) 1 准备环境 1.1 安装系统,并配置网络使3台机器互联互通,且SSH可直连(无需密码.保存私钥) 1.1.1 安装系统 安装Centos 6.5系统 安装过程略 ...

  3. 快速排序算法 java 实现

    快速排序算法 java 实现 快速排序算法Java实现 白话经典算法系列之六 快速排序 快速搞定 各种排序算法的分析及java实现 算法概念 快速排序是C.R.A.Hoare于1962年提出的一种划分 ...

  4. redhat 更新 python 为 2.7.6

    1. 下载 wget http://python.org/ftp/python/2.7.6/Python-2.7.6.tgz 2. 解压,编译 tar zxvf Python-2.7.6.tgz ./ ...

  5. Web 2D/3d

    首选应该是H5,通过现成的js库来实现,兼容性应该不错 其次可以考虑使用Unity3d,开发起来应该比较快 搜集点资料先放起来~ Unity3d: http://unity3d.com/cn/get- ...

  6. windows环境安装和配置Apache-Tomcat7.0

    转自:http://blog.sina.com.cn/s/blog_7c35df9b010111sh.html 说明: Tomcat Manager的用户名和密码可以到"Tomcat安装目录 ...

  7. Django(三)

    1.Django请求的生命周期         路由系统 -> 视图函数(获取模板+数据-->渲染) -> 字符串返回给用户   2.路由系统         /index/    ...

  8. sum data

    $('.group_header').each(function(){ ; $(this).nextUntil('tr.group_header').find('.num').each(functio ...

  9. mysql 擎特点

  10. ThinkPHP之登录验证

    验证方面写的不是很完整,正在完善当中 <?php /** * Created by dreamcms. * User: Administrator * Date: 2016/9/5 * Time ...