【发布时间】:2012-06-14 22:04:55
【问题描述】:
我对 RSA-SHA1 感到困惑,我认为它是 RSA_private_encrypt(SHA1(message))。 但我无法获得正确的签名值。 有什么问题吗?
【问题讨论】:
标签: cryptography openssl rsa digital-signature xml-signature
我对 RSA-SHA1 感到困惑,我认为它是 RSA_private_encrypt(SHA1(message))。 但我无法获得正确的签名值。 有什么问题吗?
【问题讨论】:
标签: cryptography openssl rsa digital-signature xml-signature
我认为您在错误的 OpenSSL 抽象级别上工作;您可能应该使用rsa.h 声明的函数RSA_sign() 和RSA_verify(),它们旨在用于PKCS#1 兼容的签名。
【讨论】:
是的,PKCS#1 加密和 PKCS#1 签名是 different。在加密情况下(您尝试过的那个),输入消息在取幂之前被简单地填充。
另一方面,PKCS#1 签名将首先计算表单的 ASN.1 DER 结构
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,
digest OCTET STRING
}
然后再次填充以形成编码消息 EM
EM = 0x00 || 0x01 || PS || 0x00 || T
其中 PS 是足够长度的 0xff 填充字符串。如果您重现此 EM 并使用 RSA_private_encrypt,那么您将获得正确的 PKCS#1 v1.5 签名编码,与使用 RSA_sign 获得的相同,甚至更好,使用通用的 EVP_PKEY_sign。
这里有一个 Ruby 的小演示:
require 'openssl'
require 'pp'
data = "test"
digest = OpenSSL::Digest::SHA256.new
hash = digest.digest("test")
key = OpenSSL::PKey::RSA.generate 512
signed = key.sign(digest, data)
dec_signed = key.public_decrypt(signed)
p hash
pp OpenSSL::ASN1.decode dec_signed
SHA-256 哈希打印如下:
"\x9F\x86\xD0\x81\x88L}e\x9A/..."
dec_signed 是用公钥再次解密RSA_sign 的结果——这让我们准确地返回了 RSA 函数的输入,去掉了填充,事实证明,这正是 DigestInfo 结构上面提到的:
#<OpenSSL::ASN1::Sequence:0x007f60dc36b250
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::Sequence:0x007f60dc36b318
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::ObjectId:0x007f60dc36b390
@infinite_length=false,
@tag=6,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value="SHA256">,
#<OpenSSL::ASN1::Null:0x007f60dc36b340
@infinite_length=false,
@tag=5,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=nil>]>,
#<OpenSSL::ASN1::OctetString:0x007f60dc36b2a0
@infinite_length=false,
@tag=4,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value="\x9F\x86\xD0\x81\x88L}e\x9A/...">]>
如您所见,DigestInfo 的 digest 字段的值与我们自己计算的 SHA-256 哈希值相同。
【讨论】: