我对RSA-SHA1感到困惑,我认为它是RSA_private_encrypt(SHA1(消息))。 但我无法获得正确的签名值。 有什么不对吗?
答案 0 :(得分:8)
是的,PKCS#1加密和PKCS#1签名是different。在加密情况下(您尝试过的情况),输入消息在被取幂之前只需填充。
另一方面,PKCS#1 signagtures将首先计算表格的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
或更好,使用通用{{3}获得的编码相同}。
这是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/...">]>
如您所见,digest
DigestInfo
字段的值与我们自己计算的SHA-256哈希值相同。
答案 1 :(得分:3)
我认为你正在使用错误的OpenSSL抽象级别;您应该使用rsa.h
- 已声明的函数RSA_sign()
和RSA_verify()
,这些函数旨在用于符合PKCS#1的签名。