参考链接:

https://blog.csdn.net/github_35454460/article/details/51862470

https://developer.aliyun.com/article/693527

之前文章有提过使用openssl库能够很方便的实现rsa的加密和解密,但是在实际使用过程中发现,无法解密客户方发送过来的密文,原因是客户使用的填充方式是OAEPWithSHA-256,两边填充方式不一致导致。

但是这里会有一个问题,openssl库没有直接提供接口能够选择sha256方式的填充,即使是选择了oaep方式填充,默认的也是sha1方式。参考上面大佬的资料后,有两种方法可以使用。第一种,直接修改源码,将EVP_sha1替换成EVP_sha256,注意,RSA_padding_add_PKCS1_OAEP_mgf1函数和RSA_padding_check_PKCS1_OAEP_mgf1函数都需要改。

/* crypto/rsa/rsa_oaep.c */
/** Written by Ulf Moeller. This software is distributed on an "AS IS" basis,* WITHOUT WARRANTY OF ANY KIND, either express or implied.*//* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) *//** See Victor Shoup, "OAEP reconsidered," Nov. 2000, <URL:* http://www.shoup.net/papers/oaep.ps.Z> for problems with the security* proof for the original OAEP scheme, which EME-OAEP is based on. A new* proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern,* "RSA-OEAP is Still Alive!", Dec. 2000, <URL:* http://eprint.iacr.org/2000/061/>. The new proof has stronger requirements* for the underlying permutation: "partial-one-wayness" instead of* one-wayness.  For the RSA function, this is an equivalent notion.*/#include "constant_time_locl.h"#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
# include <stdio.h>
# include "cryptlib.h"
# include <openssl/bn.h>
# include <openssl/rsa.h>
# include <openssl/evp.h>
# include <openssl/rand.h>
# include <openssl/sha.h>int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,const unsigned char *from, int flen,const unsigned char *param, int plen)
{return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen,param, plen, NULL, NULL);
}int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,const unsigned char *from, int flen,const unsigned char *param, int plen,const EVP_MD *md, const EVP_MD *mgf1md)
{int i, emlen = tlen - 1;unsigned char *db, *seed;unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE];int mdlen;if (md == NULL)md = EVP_sha1();if (mgf1md == NULL)mgf1md = md;mdlen = EVP_MD_size(md);if (flen > emlen - 2 * mdlen - 1) {RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);return 0;}if (emlen < 2 * mdlen + 1) {RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,RSA_R_KEY_SIZE_TOO_SMALL);return 0;}to[0] = 0;seed = to + 1;db = to + mdlen + 1;if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))return 0;memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);db[emlen - flen - mdlen - 1] = 0x01;memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);if (RAND_bytes(seed, mdlen) <= 0)return 0;
# ifdef PKCS_TESTVECTmemcpy(seed,"\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",20);
# endifdbmask = OPENSSL_malloc(emlen - mdlen);if (dbmask == NULL) {RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);return 0;}if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0)goto err;for (i = 0; i < emlen - mdlen; i++)db[i] ^= dbmask[i];if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0)goto err;for (i = 0; i < mdlen; i++)seed[i] ^= seedmask[i];OPENSSL_free(dbmask);return 1;err:OPENSSL_free(dbmask);return 0;
}int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,const unsigned char *from, int flen, int num,const unsigned char *param, int plen)
{return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num,param, plen, NULL, NULL);
}int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,const unsigned char *from, int flen,int num, const unsigned char *param,int plen, const EVP_MD *md,const EVP_MD *mgf1md)
{int i, dblen, mlen = -1, one_index = 0, msg_index;unsigned int good, found_one_byte;const unsigned char *maskedseed, *maskeddb;/** |em| is the encoded message, zero-padded to exactly |num| bytes: em =* Y || maskedSeed || maskedDB*/unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE],phash[EVP_MAX_MD_SIZE];int mdlen;if (md == NULL)md = EVP_sha1();if (mgf1md == NULL)mgf1md = md;mdlen = EVP_MD_size(md);if (tlen <= 0 || flen <= 0)return -1;/** |num| is the length of the modulus; |flen| is the length of the* encoded message. Therefore, for any |from| that was obtained by* decrypting a ciphertext, we must have |flen| <= |num|. Similarly,* num < 2 * mdlen + 2 must hold for the modulus irrespective of* the ciphertext, see PKCS #1 v2.2, section 7.1.2.* This does not leak any side-channel information.*/if (num < flen || num < 2 * mdlen + 2)goto decoding_err;dblen = num - mdlen - 1;db = OPENSSL_malloc(dblen);em = OPENSSL_malloc(num);if (db == NULL || em == NULL) {RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);goto cleanup;}/** Always do this zero-padding copy (even when num == flen) to avoid* leaking that information. The copy still leaks some side-channel* information, but it's impossible to have a fixed  memory access* pattern since we can't read out of the bounds of |from|.** TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.*/memset(em, 0, num);memcpy(em + num - flen, from, flen);/** The first byte must be zero, however we must not leak if this is* true. See James H. Manger, "A Chosen Ciphertext  Attack on RSA* Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).*/good = constant_time_is_zero(em[0]);maskedseed = em + 1;maskeddb = em + 1 + mdlen;if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))goto cleanup;for (i = 0; i < mdlen; i++)seed[i] ^= maskedseed[i];if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md))goto cleanup;for (i = 0; i < dblen; i++)db[i] ^= maskeddb[i];if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL))goto cleanup;good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));found_one_byte = 0;for (i = mdlen; i < dblen; i++) {/** Padding consists of a number of 0-bytes, followed by a 1.*/unsigned int equals1 = constant_time_eq(db[i], 1);unsigned int equals0 = constant_time_is_zero(db[i]);one_index = constant_time_select_int(~found_one_byte & equals1,i, one_index);found_one_byte |= equals1;good &= (found_one_byte | equals0);}good &= found_one_byte;/** At this point |good| is zero unless the plaintext was valid,* so plaintext-awareness ensures timing side-channels are no longer a* concern.*/if (!good)goto decoding_err;msg_index = one_index + 1;mlen = dblen - msg_index;if (tlen < mlen) {RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, RSA_R_DATA_TOO_LARGE);mlen = -1;} else {memcpy(to, db + msg_index, mlen);goto cleanup;}decoding_err:/** To avoid chosen ciphertext attacks, the error message should not* reveal which kind of decoding error happened.*/RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,RSA_R_OAEP_DECODING_ERROR);cleanup:if (db != NULL)OPENSSL_free(db);if (em != NULL)OPENSSL_free(em);return mlen;
}int PKCS1_MGF1(unsigned char *mask, long len,const unsigned char *seed, long seedlen, const EVP_MD *dgst)
{long i, outlen = 0;unsigned char cnt[4];EVP_MD_CTX c;unsigned char md[EVP_MAX_MD_SIZE];int mdlen;int rv = -1;EVP_MD_CTX_init(&c);mdlen = EVP_MD_size(dgst);if (mdlen < 0)goto err;for (i = 0; outlen < len; i++) {cnt[0] = (unsigned char)((i >> 24) & 255);cnt[1] = (unsigned char)((i >> 16) & 255);cnt[2] = (unsigned char)((i >> 8)) & 255;cnt[3] = (unsigned char)(i & 255);if (!EVP_DigestInit_ex(&c, dgst, NULL)|| !EVP_DigestUpdate(&c, seed, seedlen)|| !EVP_DigestUpdate(&c, cnt, 4))goto err;if (outlen + mdlen <= len) {if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL))goto err;outlen += mdlen;} else {if (!EVP_DigestFinal_ex(&c, md, NULL))goto err;memcpy(mask + outlen, md, len - outlen);outlen = len;}}rv = 0;err:EVP_MD_CTX_cleanup(&c);return rv;
}#endif

第二种方式更为通用,直接调用RSA_padding_add_PKCS1_OAEP_mgf1函数并将md的值赋为EVP_sha256,先手动将明文填充好,然后再加密。

c语言使用openssl库进行RSA加解密,并使用OAEP SHA256填充方式相关推荐

  1. MacOS下使用C语言基于openssl库进行RSA加密解密

    MacOS下使用C语言基于openssl库进行RSA加密解密 1 安装openssl并生成密钥 首先当然要安装openssl(这里记得看一下安装路径,应该是/usr/local/Cellar/open ...

  2. openssl在多平台和多语言之间进行RSA加解密注意事项

    首先说一下平台和语言: 系统平台为CentOS6.3,RSA加解密时使用NOPADDING进行填充 1)使用C/C++调用系统自带的openssl 2)Android4.2模拟器,第三方openssl ...

  3. C语言实现简单的RSA加解密算法

    使用c语言实现了简单的RSA加解密算法. 实验内容: 1.输入两个素数,然后生成一个随机数,计算出随机数的逆元,然后保存这些信息: 2.选择加密,则输入明文,输出密文: 3.选择解密,则输入密钥,输出 ...

  4. 前后端跨语言RSA加解密和签名验证实现(js+python)

    信息安全课程作业,敲了整整4天才基本搞定,还有一小问题没解决,可以的话评论区留言感激不尽. 总体思路: 该系统后端使用python的tornado框架(专门实现聊天功能的框架,笔者也只学了一天),前端 ...

  5. 与非java语言使用RSA加解密遇到的问题:algid parse error, not a sequence

    遇到的问题 在一个与Ruby语言对接的项目中,决定使用RSA算法来作为数据传输的加密与签名算法.但是,在使用Ruby生成后给我的私钥时,却发生了异常:IOException: algid parse ...

  6. 区块链背后的信息安全(4)RSA加解密及签名算法的技术原理及其Go语言实现

    # RSA加解密及签名算法的技术原理及其Go语言实现 对称加密中,加密和解密使用相同的密钥,因此必须向解密者配送密钥,即密钥配送问题. 而非对称加密中,由于加密和解密分别使用公钥和私钥,而公钥是公开的 ...

  7. 介绍一个很好用的Rsa加解密的.Net库 Kalix.ApiCrypto

    Rsa非对称加密技术 这个就不说了,大家上网搜索都知道,公钥加密,私钥解密.当然大家也可以自己实现.这里就懒了,就去找一个现成的库,Nuget上搜索,GitHub上搜索,发现.Net的加解密库,下载量 ...

  8. Crypto++库在VS 2005中的使用——RSA加解密

    Crypto++库在VS 2005中的使用--RSA加解密 源代码:下载 一.   下载Crypto++ Library Crypto++ Library的官方网:http://www.cryptop ...

  9. 全国二级c语言上机题库答案,二级C语言上机题库100题加答案

    <二级C语言上机题库100题加答案>由会员分享,可在线阅读,更多相关<二级C语言上机题库100题加答案(67页珍藏版)>请在人人文库网上搜索. 1.1 :将大于整数m且接近m的 ...

最新文章

  1. RUP大讲堂(第一讲):RUP简介及软件过程改进
  2. import的几种用法
  3. python基础实例-Python入门基础知识实例,值得收藏!
  4. 成功解决TypeError: object of type ‘int‘ has no len()
  5. ALV TREE学习笔记
  6. 安卓APP_ 控件(6)—— Notification通知
  7. input上传文件个数控制
  8. 传统的6d位姿估计fangfa1_李飞飞团队最新论文:基于anchor关键点的类别级物体6D位姿跟踪...
  9. 索引sql server_SQL Server报告– SQL Server索引利用率
  10. mysql集群集成springboot_springboot配置数据库包括集群下 配置
  11. python圆柱体积代码_python实现Bencode解码方法
  12. python 与栈 入门
  13. 【Python实例第18讲】affinity propagation聚类算法
  14. 常用的eclipse插件下载地址
  15. 华为rh5885服务器oid_高性能全冗余 华为RH5885 V3服务器解析
  16. Android虚拟机参数意义,Android虚拟机参数说明
  17. centos漏洞系列(三):Google Android libnl权限提升漏洞
  18. get与post的解释与区别
  19. Android文件系统的结构及目录用途、操作方法 整理
  20. 《内网安全攻防:渗透测试实战指南》读书笔记(四):权限提升分析及防御

热门文章

  1. android经纬度查询,Android - 经纬度获取
  2. 神雕侠侣手游服务器维护,《神雕侠侣》3月30日更新维护新服开启公告
  3. Eclipse连接Hadoop集群(详细版)
  4. RGB图像转HSI直方图均衡化后再转回RGB
  5. Qtum量子链发布QIP-6,通过预编译合约大幅降低开发成本
  6. 差异数据的对比和整理
  7. 手把手教你选购电脑组件
  8. HTML打开QQ对话窗口
  9. 图片没有透明效果html,为什么png不是透明底
  10. 基于SSM java学校教务管理系统