RSA 加密。 EVP_PKEY_CTX_new 失败
RSA encryption. EVP_PKEY_CTX_new failed
我正在使用 OAEP SHA256 实施 RSA 加密。
按照 Whosebug 和 openssl 文档上的示例,
我在下面实施 code.But 我没有找到 EVP_PKEY_size 和 EVP_PKEY_CTX_new() 失败的原因。
谁能指出错误?或者谁能提供可以进行 SHA256 rsa public 密钥加密的代码?
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。
我的 public 开头是 -----BEGIN RSA PUBLIC KEY----- 我不确定 PEM_read_bio_PUBKEY() 是否是正确的阅读方法。
就是这个类型
PEM_read_bio_RSA_PUBKEY
通过引用获取(如果非空)AND returns RSA *
不是 EVP_PKEY *
;请参阅系统的手册页或 on the web。使用错误的 pointed-to 类型违反了 C 中的约束,并且如果您在符合模式下使用一个体面的编译器(这几乎总是一个好主意)它应该给您诊断,您应该注意这一点。
类似地,RSA_size
需要 RSA *
,而您实际上没有 EVP_PKEY *
,因为您错误地声明并因此有效,但是 EVP_PKEY_CTX_new
需要 EVP_PKEY *
,您没有,因此不起作用。如果你幸运的话,它至少会崩溃,或者给你鼻恶魔或重新格式化你的磁盘。
最简单的解决方案是使用 PEM_read_bio_PUBKEY
(注意 NO RSA
),也在同一个手册页上,它需要 &returns EVP_PKEY *
-- 而且不要不要在上面调用 RSA_size
。如果您确实需要输出大小或密钥大小,但您似乎没有这样做,请根据需要使用 EVP_PKEY_size
或 EVP_PKEY_bits
。
或者,您可以使用 RSA *
作为 PEM_read_bio_RSA_PUBKEY
的结果,然后将其设置为单独分配的 EVP_PKEY *
以用于加密。这会工作,但更繁琐。
已添加:您还需要对 EVP_PKEY_encrypt
、
使用 EVP_PKEY_encrypt_init
而不是 _decrypt_init
I have access only to pub key, not to .pem file
文件的扩展名本身并不重要,只是因为它通常用于指示文件的内容。 PEM 格式(在文件中)可用于多种数据,包括 public 键,实际上 PEM_read_[bio]_[type]_PUBKEY
完全读取:一个 PEM 文件(或其他数据源)包含 public 键。如果那不是你所拥有的,那么你的代码比我上面诊断的要错误得多,但是由于你没有说出你所拥有的,所以不可能提供任何有用的建议。如果您的意思是您在 PEM 文件中有 私钥 ,并且想要 public 密钥,请使用 openssl rsa -in private -pubout -out public
或 openssl pkey -in private -pubout -out public
。 OpenSSL 实际上可以用私钥加密,因为私钥值完全决定了 public 密钥,但任何以这种方式使用密钥的系统都设计得很糟糕,可能不安全。
更新: 您现在披露您的文件包含 -----BEGIN/END RSA PUBLIC KEY-----
。这是一种很少使用的格式,它不是 OpenSSL 调用的格式 'PUBKEY',它是来自 X.509/PKIX 的 SubjectPublicKeyInfo 结构并且被标记为 -----BEGIN/END PUBLIC KEY-----
(没有 'RSA',尽管它包含 一个 RSA public 密钥)。要阅读您的文件,您必须使用(正如您在评论中所做的那样)PEM_read_[bio]_RSAPublicKey
——这需要 &returns RSA *
而不是 EVP_PKEY *
。无法将这种类型的文件读取为 EVP_PKEY *
,但是由于您需要 EVP_PKEY *
用于您想要的加密例程,因此您必须使用我之前提到的 'alternative':首先读取文件进入 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
我正在使用 OAEP SHA256 实施 RSA 加密。 按照 Whosebug 和 openssl 文档上的示例, 我在下面实施 code.But 我没有找到 EVP_PKEY_size 和 EVP_PKEY_CTX_new() 失败的原因。
谁能指出错误?或者谁能提供可以进行 SHA256 rsa public 密钥加密的代码?
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。 我的 public 开头是 -----BEGIN RSA PUBLIC KEY----- 我不确定 PEM_read_bio_PUBKEY() 是否是正确的阅读方法。
就是这个类型
PEM_read_bio_RSA_PUBKEY
通过引用获取(如果非空)AND returns RSA *
不是 EVP_PKEY *
;请参阅系统的手册页或 on the web。使用错误的 pointed-to 类型违反了 C 中的约束,并且如果您在符合模式下使用一个体面的编译器(这几乎总是一个好主意)它应该给您诊断,您应该注意这一点。
类似地,RSA_size
需要 RSA *
,而您实际上没有 EVP_PKEY *
,因为您错误地声明并因此有效,但是 EVP_PKEY_CTX_new
需要 EVP_PKEY *
,您没有,因此不起作用。如果你幸运的话,它至少会崩溃,或者给你鼻恶魔或重新格式化你的磁盘。
最简单的解决方案是使用 PEM_read_bio_PUBKEY
(注意 NO RSA
),也在同一个手册页上,它需要 &returns EVP_PKEY *
-- 而且不要不要在上面调用 RSA_size
。如果您确实需要输出大小或密钥大小,但您似乎没有这样做,请根据需要使用 EVP_PKEY_size
或 EVP_PKEY_bits
。
或者,您可以使用 RSA *
作为 PEM_read_bio_RSA_PUBKEY
的结果,然后将其设置为单独分配的 EVP_PKEY *
以用于加密。这会工作,但更繁琐。
已添加:您还需要对 EVP_PKEY_encrypt
、
EVP_PKEY_encrypt_init
而不是 _decrypt_init
I have access only to pub key, not to .pem file
文件的扩展名本身并不重要,只是因为它通常用于指示文件的内容。 PEM 格式(在文件中)可用于多种数据,包括 public 键,实际上 PEM_read_[bio]_[type]_PUBKEY
完全读取:一个 PEM 文件(或其他数据源)包含 public 键。如果那不是你所拥有的,那么你的代码比我上面诊断的要错误得多,但是由于你没有说出你所拥有的,所以不可能提供任何有用的建议。如果您的意思是您在 PEM 文件中有 私钥 ,并且想要 public 密钥,请使用 openssl rsa -in private -pubout -out public
或 openssl pkey -in private -pubout -out public
。 OpenSSL 实际上可以用私钥加密,因为私钥值完全决定了 public 密钥,但任何以这种方式使用密钥的系统都设计得很糟糕,可能不安全。
更新: 您现在披露您的文件包含 -----BEGIN/END RSA PUBLIC KEY-----
。这是一种很少使用的格式,它不是 OpenSSL 调用的格式 'PUBKEY',它是来自 X.509/PKIX 的 SubjectPublicKeyInfo 结构并且被标记为 -----BEGIN/END PUBLIC KEY-----
(没有 'RSA',尽管它包含 一个 RSA public 密钥)。要阅读您的文件,您必须使用(正如您在评论中所做的那样)PEM_read_[bio]_RSAPublicKey
——这需要 &returns RSA *
而不是 EVP_PKEY *
。无法将这种类型的文件读取为 EVP_PKEY *
,但是由于您需要 EVP_PKEY *
用于您想要的加密例程,因此您必须使用我之前提到的 'alternative':首先读取文件进入 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