【问题标题】:RSA encryption. EVP_PKEY_CTX_new failedRSA 加密。 EVP_PKEY_CTX_new 失败
【发布时间】:2020-08-28 20:22:45
【问题描述】:

我正在使用 OAEP SHA256 实施 RSA 加密。 按照 stackoverflow 和 openssl 文档的示例, 我实现了下面的代码。但是我找不到 EVP_PKEY_size 和 EVP_PKEY_CTX_new() 失败的原因。

谁能指出错误?或者任何人都可以提供可以进行 SHA256 rsa 公钥加密的代码吗?

   keybio = BIO_new(BIO_s_mem());
    if (keybio == NULL)
    {
        printf("Failed to create key BIO");
        return 0;
    }
    int len = BIO_write(keybio, Key, strlen(Key));
    EVP_PKEY*  evppubKey = PEM_read_bio_PUBKEY(keybio, NULL, NULL, NULL);
//  EVP_PKEY* evp_key = PEM_read_bio_RSAPublicKey(keybio, NULL, NULL, NULL);
    int a = EVP_PKEY_size(evp_key);
    EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(evp_key, eng);
    
    EVP_PKEY_free(evp_key);

    if (ctx)
    {
        if (EVP_PKEY_encrypt_init(ctx) > 0)
        {
            EVP_PKEY_CTX_ctrl_str(ctx, "rsa_padding_mode", "oaep");
            EVP_PKEY_CTX_ctrl_str(ctx, "rsa_oaep_md", "sha256");
            EVP_PKEY_CTX_ctrl_str(ctx, "rsa_mgf1_md", "sha256");


            if (EVP_PKEY_encrypt(ctx, NULL, &outlen, data, data_len) <= 0)
            {
                return -1;
            }

            outdata = OPENSSL_malloc(outlen);

            if (!outdata) {
                return -1;
            }
            if (EVP_PKEY_encrypt(ctx, outdata, &outlen, data, data_len) <= 0) {
                return -1;
            }

        }
        EVP_PKEY_CTX_free(ctx);
    }

更新: 我对代码进行了更改。 PEM_read_bio_PUBKEY() 返回 NULL。 我的公众以 -----BEGIN RSA PUBLIC KEY----- 我不确定 PEM_read_bio_PUBKEY() 是否是正确的阅读方法。

【问题讨论】:

    标签: c openssl rsa


    【解决方案1】:

    就是类型。

    PEM_read_bio_RSA_PUBKEY 通过引用获取(如果非空)并且返回 RSA * 而不是 EVP_PKEY *;请参阅系统上的手册页或on the web。使用错误的指向类型违反了 C 中的约束,如果您在符合模式下使用体面的编译器(这几乎总是一个好主意),它应该会给您诊断,您应该注意这一点。

    同样,RSA_size 需要 RSA *,而您实际上没有 EVP_PKEY *,因为您错误地声明并因此工作,但 EVP_PKEY_CTX_new 需要 EVP_PKEY *,您没有,因此无法工作。如果你更幸运的话,它至少会崩溃,或者给你带来鼻恶魔或重新格式化你的磁盘。

    最简单的解决方案是使用PEM_read_bio_PUBKEY(注意NO RSA),也在同一个手册页上,它需要&返回EVP_PKEY *——并且不要调用RSA_size。如果您确实需要输出大小或密钥大小,但您似乎不需要,请酌情使用EVP_PKEY_size 或EVP_PKEY_bits。

    或者,您可以将RSA * 用于PEM_read_bio_RSA_PUBKEY 的结果,然后将其设置为单独分配的EVP_PKEY * 以用于加密。这会起作用,但更繁琐。

    补充:你还需要使用EVP_PKEY_encrypt_init而不是_decrypt_init作为EVP_PKEY_encrypt,

    我只能访问 pub 密钥,不能访问 .pem 文件

    文件的扩展名本身并不重要,只是因为它通常用于指示文件的内容。 PEM 格式(在文件中)可用于多种数据,包括公钥,实际上PEM_read_[bio]_[type]_PUBKEY 读取的正是:包含公钥的 PEM 文件(或其他数据源) .如果这不是您所拥有的,那么您的代码比我上面诊断的要错误得多,但是由于您没有说出您所拥有的,因此不可能提供任何有用的建议。如果您的意思是您在 PEM 文件中有 私钥,并且想要公钥,请使用 openssl rsa -in private -pubout -out public 或 openssl pkey -in private -pubout -out public。 OpenSSL 实际上可以使用私钥进行加密,因为私钥的值完全决定了公钥,但是任何使用这种方式的系统都设计得很糟糕并且可能不安全。


    更新:您现在披露您的文件包含-----BEGIN/END RSA PUBLIC KEY-----。这是一种很少使用的格式,不是 OpenSSL 称为“PUBKEY”的格式,它是 X.509/PKIX 中的 SubjectPublicKeyInfo 结构,标记为-----BEGIN/END PUBLIC KEY-----(即使它包含也没有'RSA' em> 一个 RSA 公钥)。要阅读您的文件,您必须使用(正如您在评论中所使用的)PEM_read_[bio]_RSAPublicKey -- 它需要&返回RSA * 而不是EVP_PKEY *。无法将这种类型的文件读取为EVP_PKEY *,但由于您需要EVP_PKEY * 来执行所需的加密例程,因此您必须使用我之前提到的“替代方案”:首先将文件读入RSA *,然后从RSA * 构建一个EVP_PKEY *:

    ...
    RSA * rsa = PEM_read_bio_RSAPublicKey (bio, NULL, NULL, NULL);
    if( rsa == NULL ) error;
    EVP_PKEY * evp_key = EVP_PKEY_new();
    if( evp_key == NULL ) error; // very unlikely
    if( ! EVP_PKEY_set1_RSA (evp_key, rsa) ) error;
    RSA_free (rsa);
    // and then continue as you already have:
    EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(evp_key, eng/*normally NULL*/);
    if nonnull and EVP_PKEY_encrypt_init(ctx) > 0:
      EVP_PKEY_CTX_ctrl ... and EVP_PKEY_encrypt
    

    【讨论】:

    • nasal demons: n.的有用链接
    • @David C. Rankin :我在上面的链接中没有看到任何与我的问题相关的内容
    • @TippuR 这是作者解释的链接“或给你鼻恶魔或重新格式化你的磁盘。”...
    猜你喜欢
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-09
    相关资源
    最近更新 更多