Cryptography 使用256位RSA密钥在openssl.exe上签名20字节的消息,但不在代码中

Cryptography 使用256位RSA密钥在openssl.exe上签名20字节的消息,但不在代码中,cryptography,openssl,rsa,Cryptography,Openssl,Rsa,我有一个256位的私钥,我想用来签署SHA-1摘要(20字节)。直接使用openssl似乎是可行的 echo doesntmatter | openssl dgst-sha1-二进制| openssl rsautl-签名-inkey 256bit_private_key.pem | openssl enc-base64 按预期为我提供Base64输出 但使用OpenSSL失败的原因是“错误:04075070:rsa例程:rsa\u符号:对rsa密钥来说摘要太大”。正如您在下面看到的,我正在将20

我有一个256位的私钥,我想用来签署SHA-1摘要(20字节)。直接使用openssl似乎是可行的

echo doesntmatter | openssl dgst-sha1-二进制| openssl rsautl-签名-inkey 256bit_private_key.pem | openssl enc-base64

按预期为我提供Base64输出

但使用OpenSSL失败的原因是“错误:04075070:rsa例程:rsa\u符号:对rsa密钥来说摘要太大”。正如您在下面看到的,我正在将20字节(SHA_DIGEST_LENGTH=20)的SHA-1摘要作为输入传递给RSA_符号。即使使用填充,也不应该超过我可以用256位模数密钥加密的最大32字节

unsigned char digest[SHA_DIGEST_LENGTH];
SHA1(message, messageSize, digest);

unsigned int privateKeySize = RSA_size(privateKey); // 256 bits = 32 bytes
unsigned char* signature = new unsigned char[privateKeySize];
unsigned int signatureSize;

int res = RSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH, signature, &signatureSize, privateKey);

if(res == 0)
{
    int err = ERR_get_error(); // 67588208
    char *s = ERR_error_string(err, 0); // error:04075070:lib(4):func(117):reason(112)

    delete [] signature;

    [...]
}

代码中我做错了什么?

我想我找到了解决方案
openssl rsautl-sign
使用
RSA\u private\u encrypt
而不是
RSA\u sign
(这是我所期望的)
RSA\u-sign
创建的结构比我提供的20字节消息长,因此它会因给定错误而失败。

请检查此项
rsautl
被贬值,取而代之的是
pkeyutl

本质上,RSA签名应该使用RSA-PSS签名填充方案来确保安全,并且RSA-PSS将严格大于摘要,因为需要通信salt。另外,
RSA\u-sign
将摘要作为签名方案的一部分,因此您的代码将对摘要进行摘要。您可以直接传入消息,或者使用
RSA\u private\u encrypt
与合适的
RSA\u padding\u add\u x
调用相结合


正如我在评论中所说的,256位密钥对于对称算法来说是足够安全的,但是对于RSA私钥(数量级)来说,破解它是很容易的。使用最小1024位的密钥(可能是2048或4096位的密钥)将获得大致相当于128位对称算法的结果。

关于彼得·埃利奥特:不完全如此

中的PKCS1v1_5标准序列(以及9.2,与rfc4347和rfc3447类似)是散列,在ASN.1、pad(“类型1”)和modexp d中编码。(PSS省略ASN.1步骤,并使用不同的填充。)

OpenSSL(低级)
RSA\u-sign
执行最后三个操作(使用v1.5填充),但不执行第一个操作——即,它编码散列,但不执行散列;甚至更低的
RSA\u private\u encrypt
执行最后两项。 更高级别的信封模块(原始的
EVP_Sign{Init,Update,Final}*
,增强的
EVP_DigestSign*
)执行这四项任务。 正是ASN.1编码使得该值对于256位密钥来说太大了——正如所述,该值无论如何都是可破坏的

rsautl
只执行最后两个步骤而不执行编码,因此它会运行,但会给出非标准的结果。
pkeyutl
for RSA默认情况下也会执行相同的操作,但可以告知执行编码

另外,PSS有更好的安全性证明,但据我所知,在v1.5上没有实际的攻击,它仍然被广泛使用。
如果您可以选择PSS(双方/各方都支持),请选择它,但不要担心使用v1.5。

这是c吗?请指定编程语言!代码是C++,但不应该是256位RSA密钥非常不安全…我希望这只是一个学校的项目或东西,而不是一些“真正的”谢谢你的建议!我的用例有点不同,幸运的是,它并没有真正的安全性相关,否则我会立即更改为更大的密钥和RSA签名。