700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > c语言使用openssl库进行RSA加解密 并使用OAEP SHA256填充方式

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

时间:2020-12-18 19:10:41

相关推荐

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

参考链接:

/github_35454460/article/details/51862470

/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:* /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:* /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,先手动将明文填充好,然后再加密。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。