使用256位RSA密钥签署20字节消息,使用openssl.exe但不能使用代码

时间:2013-02-26 15:00:14

标签: cryptography openssl rsa

我有一个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;

    [...]
}

我在代码中做错了什么?

3 个答案:

答案 0 :(得分:3)

查看此SO answerrsautl已弃用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字节消息长,因此它会因给定的错误而失败。