博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
openssl 非对称加密 RSA 加密解密以及签名验证签名
阅读量:6855 次
发布时间:2019-06-26

本文共 6851 字,大约阅读时间需要 22 分钟。

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 = 512;    BIGNUM *e = BN_new();    BN_set_word(e, 65537);    RSA_generate_key_ex(r, bits, e, NULL);    //打印密钥    RSA_print_fp(stdout, r, 0);

 打印的密钥对结果:

Private-Key: (512 bit)modulus:    00:c0:53:6c:46:57:ed:4e:33:bb:71:ec:be:d6:21:    78:bf:9b:be:4f:8b:fb:32:ae:f2:83:9c:e7:b8:63:    a2:34:9c:98:cc:4a:a2:17:1d:31:03:c8:f6:e0:13:    3a:29:40:c8:1a:d4:b7:88:38:07:4c:3b:2a:01:0b:    17:45:36:4f:f9publicExponent: 65537 (0x10001)privateExponent:    00:8f:59:9e:ca:8f:9f:01:3a:ed:eb:ec:5a:11:a0:    c1:2f:90:16:39:94:4c:97:6a:6e:b8:4a:ab:2c:74:    96:e2:3e:c8:aa:34:bb:99:9e:e5:60:86:b4:8f:55:    49:80:dc:26:06:74:13:64:49:ac:31:f8:fe:4d:80:    e1:e2:bf:fd:41prime1:    00:fd:95:4d:f0:25:a0:87:5e:d1:c9:0e:b8:96:f9:    ce:0a:ef:59:e7:a4:57:49:d8:fd:dd:e6:c4:59:24:    dd:e6:33prime2:    00:c2:28:a9:7b:c8:98:97:33:32:f0:52:9a:26:a2:    0b:50:3b:86:c0:55:6d:c6:c7:d1:a1:43:1d:d3:7d:    53:cd:23exponent1:    6c:80:d8:2a:6b:4f:36:dd:21:92:90:13:f7:b5:c7:    ad:f2:20:5b:f7:7b:ca:03:69:0c:eb:d3:13:f9:ac:    60:f5exponent2:    55:44:e2:5a:18:98:db:1e:83:2a:84:3c:6a:e7:13:    ac:e2:d7:a5:34:5f:87:c3:4d:cf:52:d8:90:7f:24:    04:9dcoefficient:    00:d7:0d:9b:e8:2f:3c:00:86:00:a0:b2:8b:00:1d:    e2:b9:0f:9f:ca:b2:75:84:ea:c8:9d:5e:78:e5:e3:    92:46:aa
View Code

 

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 = 0;    unsigned long inLen = strlen(inStr);    int pdBlock = RSA_size(r)-11;    unsigned int eCount = (inLen / pdBlock) +1;    //分组加密,可以看出outData最大不超过malloc[eCount*pdBlock]    for (int i=0; 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 = 0;    unsigned long inLen = strlen(inStr);    int pdBlock = RSA_size(r);    unsigned int dCount = inLen / pdBlock;    //分组解密    for (int i=0; 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(1024);    //公钥加密    int encRet = kkrsa_public_encrypt(src, encDat, r);    printf("enc:%d\n",encRet);        char *decDat = malloc(1024);    //私钥解密    int decRet = kkrsa_private_decrypt(encDat, decDat, r);    printf("dec:%s  len=%d\n",decDat,decRet);        free(encDat);    free(decDat);

 打印结果:

block:64 src:this is test encrypt data use RSA_PKCS1_PADDING  len=47enc:64dec:this is test encrypt data use RSA_PKCS1_PADDING  len=47test2src:this is test private encrypt data use RSA_PKCS1_PADDING  len=55enc:128dec:this is test private encrypt data use RSA_PKCS1_PADDI  len=53
View Code

 

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 = 0;    unsigned long inLen = strlen(inStr);    int pdBlock = RSA_size(r)-11;    unsigned int eCount = (inLen / pdBlock) +1;    //分组加密,可以看出outData最大不超过malloc[eCount*pdBlock]    for (int i=0; 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 = 0;    unsigned long inLen = strlen(inStr);    int pdBlock = RSA_size(r);    unsigned int dCount = inLen / pdBlock;    //分组解密    for (int i=0; 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(1024);    //私钥加密    int encRet2 = kkrsa_private_encrypt(src2, encDat2, r);    printf("enc:%d\n",encRet2);        char *decDat2 = malloc(1024);    //公钥解密    int decRet2 = kkrsa_public_decrypt(encDat2, decDat2, r);    printf("dec:%s  len=%d\n",decDat2,decRet2);        free(encDat2);    free(decDat2);

 测试结果:

test2src:this is test private encrypt data use RSA_PKCS1_PADDING  len=55enc:128dec:this is test private encrypt data use RSA_PKCS1_PADDING\372\314\375۷GO\304  len=55
View Code

 

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 = "0123456789";    char *sinDat = malloc(RSA_size(r));    int sinLen = 0;    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 verifysign_verify=1
View Code

6. 总结

  上述RSA分组加密中使用了RSA_PKCS1_PADDING 的补位方式;当然还有如下

  不同的补位方式,在进行分组加密时,需要注意分组块的处理

# define RSA_PKCS1_PADDING       1# define RSA_SSLV23_PADDING      2# define RSA_NO_PADDING          3# define RSA_PKCS1_OAEP_PADDING  4# define RSA_X931_PADDING        5/* EVP_PKEY_ only */# define RSA_PKCS1_PSS_PADDING   6# define RSA_PKCS1_PADDING_SIZE  11

 

测试使用 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

 

  

转载地址:http://miyyl.baihongyu.com/

你可能感兴趣的文章
使用Java向properties存数据
查看>>
产能过剩的光伏电池,是否还是未来的朝阳产业?
查看>>
如何在SaaS企业及服务市场上站稳脚跟
查看>>
中心商务区建智慧城市 将现 “芝加哥夜景”
查看>>
移动端App测试实用指南(下)
查看>>
为什么没有一个软件质量保证的RUP工作流程
查看>>
海尔王淼:智能家居互联互通先解决用户需求
查看>>
商务部:中国将采取一切措施维护光伏企业合法权益
查看>>
MySQL数据库开发必备常识
查看>>
晶科能源力促分布式光伏行业标准制定
查看>>
苏征:大贲科技让酒店更智慧
查看>>
Ascent公司在亚特兰大和多伦多收购数据中心资产
查看>>
哈尔滨加快推进大数据产业发展
查看>>
跟屌丝学DB2 第二课 建立数据库以及添加用户
查看>>
Speedy —— 京东推出的 Docker 镜像存储系统
查看>>
盘点当下最流行的 Java 工具
查看>>
《NX-OS与Cisco Nexus交换技术:下一代数据中心架构(第2版)》一2.3 PVLAN
查看>>
6月23日云栖精选夜读:重磅!阿里妈妈首次公开自研CTR预估核心算法MLR
查看>>
《Hadoop大数据分析与挖掘实战》——1.4节数据挖掘建模过程
查看>>
重拾开始菜单的 Windows 9
查看>>