2011-04-14 38 views
4

这两个码提供相同的签名,预计:M2crypto签名 “算法”

代码1:

from M2Crypto import RSA, EVP 
import base64, hashlib 

text = "some text" 

pkey = EVP.load_key("mykey.pem") #"mykey.pem" was generated as: openssl genrsa -des3 -out mykey.pem 2048 
pkey.sign_init() 
pkey.sign_update(text) 
signature = pkey.sign_final() 
print base64.b64encode(signature) 

码2:

pkey = RSA.load_key("mykey.pem") 
signature = pkey.sign(hashlib.sha1(text).digest()) 
print base64.b64encode(signature) 

但是,如果我想要“模仿“签名算法,即用私钥加密摘要,我得到一个不同的签名,即:

pkey = RSA.load_key("mykey.pem") 
signature = pkey.private_encrypt(hashlib.sha1(text).digest(), RSA.pkcs1_padding) 
print base64.b64encode(signature) #different from the two above 

您能否提供一些解释?后一种签名方式有什么问题?

+0

你可以显示你的进口吗? – Daenyth 2011-04-14 14:48:20

+0

当然,对不起,我添加了进口 – michal 2011-04-14 19:49:58

+0

仅供参考,我认为[pycrypto](http://www.dlitz.net/software/pycrypto/)是[首选加密软件包](http://stackoverflow.com/questions/1137874/recommended-python-cryptographic-module)。 – Keith 2011-04-16 04:55:15

回答

3

我认为不同之处在于RSA_sign与摘要数据一起签署摘要PKCS1算法标识符,其中RSA_private_encrypt仅签署摘要数据。

RSA_private_encrypt手册页:

RSA_PKCS1_PADDING 
    PKCS #1 v1.5 padding. This function does not handle the 
    algorithmIdentifier specified in PKCS #1. When generating or 
    verifying PKCS #1 signatures, RSA_sign(3) and RSA_verify(3) should 
    be used. 
+0

谢谢!这当然是有道理的。 – michal 2011-04-16 10:37:57

0

什么EVP.sign()内部发生如下(相对于纯RSA.sign()):

sha1_hash = hashlib.sha1(MESSAGE).digest() 
# Add ASN.1 SHA-1 OID prefix 
sha1_asn1_prefix = '3021300906052b0e03021a05000414'.decode('hex') 
asn1_hash = sha1_asn1_prefix + sha1_hash 
rsa = RSA.load_key(KEY) 
# Use PKCS#1 padding 
signature = rsa.private_encrypt(asn1_hash, RSA.pkcs1_padding).encode('hex') 

对于更详细的解释和this gistthis answer一个完整的例子。

但是底线是应该使用EVP.sign()而不是上面的代码1 - 它在内部做正确的事情。