【问题标题】:How to properly create an RSA key from raw data in OpenSSL 3.0 in C language?如何使用 C 语言从 OpenSSL 3.0 中的原始数据正确创建 RSA 密钥?
【发布时间】:2021-09-28 14:32:39
【问题描述】:

我对 OpenSSL 还很陌生,我目前的工作是将项目代码从 OpenSSL 1.1.1 更新到 OpenSSL 3.0,我遇到了一个非常奇怪的问题。

我正在尝试从给定的原始数据、精确的二进制模数和转换为 BIGNUM 的指数创建一个 RSA 密钥。我已尝试按照手册中的说明进行操作,并且密钥创建有效,但问题是我尝试使用该密钥(或基于它的 CTX)执行的任何操作都失败了,无论是签名解密还是验证。

这是我创建密钥的代码:

    /* function set up above */
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
    if ( ctx == NULL) {
        ERROR("Error: failed to initialize CTX from name.\n");
        goto OPENSSL_ERROR;
    }

    modulus = BN_bin2bn(pubkey->data, pubkey->size, NULL);
    exponent = BN_bin2bn(exp_arr, 3, NULL);
    if ( modulus == NULL || exponent == NULL ) {
        goto OPENSSL_ERROR;
    }

    OSSL_PARAM params[] = {
        OSSL_PARAM_BN("n", &modulus, BN_num_bytes(modulus)*8),
        OSSL_PARAM_BN("e", &exponent, BN_num_bytes(exponent)*8),
        OSSL_PARAM_BN("d", NULL, 0),
        OSSL_PARAM_END
    };

    status = EVP_PKEY_fromdata_init(ctx);
    if ( status <= 0 ) {
        ERROR("Error: failed to initialize key creation.\n");
        goto OPENSSL_ERROR;
    }

    status = EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params);
    if ( status <= 0 || evp_key == NULL ) {
        ERROR("Error: failed to create key.\n");
        goto OPENSSL_ERROR;
    }
    /* goes on to decrypt signature and later verify it against data - both fail */

它通过得很快,但是尝试使用该密钥或基于该密钥的 CTX 做任何事情都失败了。 我尝试使用 EVP_PKEY_CTX_new_id() 创建 CTX,但它没有任何改变。 我尝试省略参数“d”,但没有任何改变。

如果有人知道我做错了什么以及应该改变什么 - 所有帮助将不胜感激。

附言

  1. pubkey 作为参数传递给函数,data 是二进制数组,size 显然是它的大小(size_t)
  2. 给键的参数与之前使用RSA_set0_key()函数的代码版本相同
  3. unsigned char exp_arr[] = {0x01, 0x00, 0x01};

【问题讨论】:

  • 我不是真正的专家,但是快速搜索一下会发现一个用于从数据生成 RSA 密钥对的不同函数,例如 RSA_Generate_Key。也许this 帖子可以提供帮助?
  • RSA_Generate_Key 在 OSSL 3.0 中已被弃用(因为它是低级的),我正在使用的函数由官方迁移指南指出。

标签: c openssl cryptography rsa


【解决方案1】:

在手册中并不明显(OpenSSL 没有新内容)。

问题在于 OSSL_PARAM 参数数组无法按照上面代码中的方式进行初始化。它需要使用 OSSL_PARAM_BLD 构建,如下所示:

    OSSL_PARAM_BLD *params_build = OSSL_PARAM_BLD_new();
    if ( params_build == NULL ) {
        goto OPENSSL_ERROR;
    }
    if ( !OSSL_PARAM_BLD_push_BN(params_build, "n", modulus) ) {
        ERROR("Error: failed to push modulus into param build.\n");
        goto OPENSSL_ERROR;
    }
    if ( !OSSL_PARAM_BLD_push_BN(params_build, "e", exponent) ) {
        ERROR("Error: failed to push exponent into param build.\n");
        goto OPENSSL_ERROR;
    }
    if ( !OSSL_PARAM_BLD_push_BN(params_build, "d", NULL) ) {
        ERROR("Error: failed to push NULL into param build.\n");
        goto OPENSSL_ERROR;
    }
    OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(params_build);
    if ( params == NULL ) {
        ERROR("Error: failed to construct params from build.\n");
        goto OPENSSL_ERROR;
    }

它可能与使用EVP_PKEY_fromdata() 函数创建的所有其他类型的键相同。

[重要!] 请记住检查您尝试创建的密钥的可设置参数,否则您可能会长时间卡在该部分上,不知道您的代码有什么问题;)

【讨论】:

    猜你喜欢
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2017-08-31
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多