我有一个256位私钥,我想用它来签署一个SHA-1摘要(20个字节)。直接使用openssl似乎可以正常工作
echo doesntmatter | openssl dgst -sha1 -binary | openssl rsautl -sign -inkey 256bit_private_key.pem | openssl enc -base64
按预期给我一个Base64输出。
但是使用OpenSSL执行此操作失败,并显示“错误:04075070:rsa例程:RSA_sign:对于rsa密钥,消息太大”。如下所示,我将20字节(SHA_DIGEST_LENGTH = 20)SHA-1摘要作为RSA_sign的输入传递。即使使用填充,它也不应该超过我用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;
[...]
}
我在代码中做错了什么?
答案 0 :(得分:3)
查看此SO answer。 rsautl
已弃用pkeyutl
基本上,RSA签名应该使用RSA-PSS签名填充方案是安全的,并且RSA-PSS将严格大于摘要,因为必须进行盐的通信。另外,RSA_sign
作为签名方案的一部分进行摘要,因此您的代码将对摘要进行摘要。您希望直接传递邮件,或者使用RSA_private_encrypt
并结合适当的RSA_padding_add_x
电话。
正如我在评论中所说,256位密钥对于对称算法来说足够安全,但对于RSA私钥(大约4 minutes on a couple of year old machine)来说,破解它将是微不足道的。使用至少1024位密钥(可能是2048或4096位密钥)将为您提供大致相当于128位对称算法的security level。
答案 1 :(得分:3)
Re Peter Elliott:不太好。
PKCS1标准序列是哈希,在ASN.1中编码,pad(v1.5又称type1或PSS),modexp(private_encrypt)。
OpenSSL(低级别)RSA_sign
执行最后三次(使用v1.5填充)但不是第一次。
更高级别的信封模块会执行所有四项(原始EVP_Sign{Init,Update,Final}*
,增强型EVP_DigestSign*
)。
它是ASN.1编码,使得该值对于256位密钥而言太大 - 无论如何,这都是可破坏的。
rsautl
只执行最后两步而不是编码,因此它会运行但会产生非标准结果。
对于RSA,pkeyutl
默认情况下也是如此,但可以告诉它进行编码。
此外,PSS有更好的安全性证明,但据我所知,v1.5没有真正的攻击,它仍然被广泛使用。 如果您可以选择PSS(两方/所有各方都支持它),请选择它,但不要担心使用v1.5。
答案 2 :(得分:0)
猜猜我找到了解决方案。 openssl rsautl -sign
使用RSA_private_encrypt
代替RSA_sign
(我所期望的)。 RSA_sign
创建的结构比我提供的20字节消息长,因此它会因给定的错误而失败。