首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用等效的OpenSSL函数替换已废弃的RSA低级别的EVP 3.0 API?

如何用等效的OpenSSL函数替换已废弃的RSA低级别的EVP 3.0 API?
EN

Stack Overflow用户
提问于 2022-10-24 01:05:24
回答 1查看 132关注 0票数 0

这个工作的RSA OpenSSL码

代码语言:javascript
运行
复制
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);
}  

编译时会产生过时的警告,如

代码语言:javascript
运行
复制
/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示例?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-30 19:35:16

我不是openssl专家,但通过阅读DOC的文章,我发现了下面的对话,它通过测试生成与您的函数相同的输出(假设没有调用SwapBytes,因为您没有提供这种功能)。

我想可以分为三部分。

  • 使用xx函数设置具有关键参数的PARAMS数组
  • 使用从数据函数从PARAMS数组创建RSA密钥
  • 使用xxx函数加密数据

示例:

代码语言:javascript
运行
复制
#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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74175833

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档