这个工作的RSA OpenSSL码
void SwapBytes( unsigned char *pv, size_t n )
{
unsigned char *p = pv;
size_t lo, hi;
for ( lo = 0, hi = n - 1; hi > lo; lo++, hi-- )
{
char tmp = p[lo];
p[lo] = p[hi];
p[hi] = tmp;
}
}
void RSA(unsigned char *plaintext, unsigned char *ciphertext)
{
BIGNUM *bnN = NULL;
BIGNUM *bnE = NULL;
RSA *keys = RSA_new();
BN_hex2bn(&bnN, modulus);
BN_hex2bn(&bnE, public_exp);
RSA_set0_key(keys, bnN, bnE, NULL);
int modulus_size = RSA_size(keys);
SwapBytes(plaintext, modulus_size);
int cipher_len = RSA_public_encrypt(modulus_size, plaintext, ciphertext, keys, RSA_NO_PADDING);
RSA_free(keys);
SwapBytes(ciphertext, modulus_size);
}
编译时会产生过时的警告,如
/mnt/c/Projects/src/rsa.cpp:37:102: warning: ‘int RSA_public_encrypt(int, const unsigned char*, unsigned char*, RSA*, int)’ is deprecated: Since OpenSSL 3.0 [-Wdeprecated-declarations]
37 | int cipher_len = RSA_public_encrypt(modulus_size, plaintext, ciphertext, keys, RSA_NO_PADDING);
可以使用此编译器选项来抑制
-Wno-反对-声明
然而,OpenSSL开发团队注意到:
长期以来,OpenSSL开发团队一直非正式地不鼓励使用低级别API。然而,在OpenSSL 3.0中,这变得更加正式。所有这些低级别的API都已被废弃。您仍然可以在应用程序中使用它们,但是您可能会在编译期间看到弃用警告(这取决于编译器对此的支持)。不推荐的API可能会从OpenSSL的未来版本中删除,因此强烈鼓励您更新代码以使用高级API。
问题
建议用EVP代替上述低层API。
是否有一个用OpenSSL EVP函数替换上述代码的RSA示例?
发布于 2022-10-30 19:35:16
我不是openssl专家,但通过阅读DOC的文章,我发现了下面的对话,它通过测试生成与您的函数相同的输出(假设没有调用SwapBytes,因为您没有提供这种功能)。
我想可以分为三部分。
示例:
#include <cassert>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/param_build.h>
template<typename T, typename D>
std::unique_ptr<T, D> make_handle(T* handle, D deleter)
{
return std::unique_ptr<T, D>{handle, deleter};
}
void newRSA(unsigned char *plaintext, unsigned char *ciphertext, int length, char const* modulus, char const* public_exp)
{
// build BIGNUM values
BIGNUM* num{ nullptr };
BN_hex2bn(&num, modulus);
assert(num != nullptr);
auto bnN = make_handle(num, BN_free);
num = nullptr;
BN_hex2bn(&num, public_exp);
assert(num != nullptr);
auto bnE = make_handle(num, BN_free);
// Build params to create PARAM array
auto params_build = make_handle(OSSL_PARAM_BLD_new(), OSSL_PARAM_BLD_free);
assert(params_build.get() != nullptr);
auto result = OSSL_PARAM_BLD_push_BN(params_build.get(), "n", bnN.get());
assert(result == 1);
result = OSSL_PARAM_BLD_push_BN(params_build.get(), "e", bnE.get());
assert(result == 1);
result = OSSL_PARAM_BLD_push_BN(params_build.get(), "d", nullptr);
assert(result == 1);
// create PARAMS array
auto params = make_handle(OSSL_PARAM_BLD_to_param(params_build.get()), OSSL_PARAM_free);
// cleanup params build up
params_build.reset();
bnN.reset();
bnE.reset();
// Create RSA key from params
auto ctx = make_handle(EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr), EVP_PKEY_CTX_free);
assert(ctx.get() != nullptr);
result = EVP_PKEY_fromdata_init(ctx.get());
assert(result == 1);
EVP_PKEY *key = nullptr;
result = EVP_PKEY_fromdata(ctx.get(), &key, EVP_PKEY_KEYPAIR, params.get());
assert(result == 1);
auto keys = make_handle(key, EVP_PKEY_free);
// cleanup params
params.reset();
// RSA_size equivalent
int modulus_size = (EVP_PKEY_get_bits(keys.get()) + 7) / 8;
assert(length == modulus_size);
// setup encryption from the key generated above
auto enc_ctx = make_handle(EVP_PKEY_CTX_new(keys.get(), nullptr), EVP_PKEY_CTX_free);
assert(enc_ctx.get() != nullptr);
result = EVP_PKEY_encrypt_init(enc_ctx.get());
assert(result == 1);
// encrypt using RSA_NO_PADDING
result = EVP_PKEY_CTX_set_rsa_padding(enc_ctx.get(), RSA_NO_PADDING);
assert(result == 1);
// encrypt
size_t outlen = length;
result = EVP_PKEY_encrypt(enc_ctx.get(), ciphertext, &outlen, plaintext, length);
assert(result == 1);
assert(outlen == length);
}
https://stackoverflow.com/questions/74175833
复制相似问题