我感到困惑的RSA-SHA1,我认为这是RSA_private_encrypt(SHA1(消息))。 但我不能得到正确的签名值。 有什么不对的吗?
Answer 1:
是的,PKCS#1加密和PKCS#1签名不同 。 在加密情况下(一个你试过),它是幂之前只是被填充的输入消息。
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
甚至更好,使用通用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/...">]>
正如你所看到的,价值digest
领域DigestInfo
是一样的SHA-256散列,我们计算出自己。
Answer 2:
我认为你在错误的OpenSSL的抽象层次工作; 你或许应该使用的rsa.h
-declared功能RSA_sign()
和RSA_verify()
它的目的是要对要使用的PKCS#1兼容的签名。
文章来源: How to compute RSA-SHA1(sha1WithRSAEncryption) value with OpenSSL