我正在尝试使用rsautl
验证来自OpenSSL的PyCryptodome命令的签名。我用来对数据进行签名的Bash命令(数据是“38b..da1”字符串)是:
echo 38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1 | openssl rsautl -inkey another_guys_priv_key.pem -sign | base64
我已将此命令转换为Python脚本,因此我可以比较Python中的内容:
from subprocess import Popen, PIPE
from shlex import split
# Use openssl to sign the data ("38b2..0da1") with another_guys private key
p1 = Popen(split('echo 38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1'), stdout=PIPE)
p2 = Popen(split('openssl rsautl -inkey another_guys_priv_key.pem -sign'), stdin=p1.stdout, stdout=PIPE)
output, _ = p2.communicate()
然后我使用PyCryptodome签署相同的数据并比较签名:
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
# Use PyCrypto to sign the data with another_guys private key
key = RSA.importKey(open('another_guys_priv_key.pem').read())
signer = PKCS1_v1_5.new(key)
h = SHA256.new()
h.update('38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1'.encode('utf-8'))
signature = signer.sign(h)
# Compare signature with OpenSSL signature
output == signature # False
并且结果不一样。
所以我在想,也许OpenSSL会自动将十六进制数据转换成字节并签名,所以我用Python试了一下:
from binascii import unhexlify
# Use PyCryptodome to sign the hex-decoded data with another_guys private key
hh = SHA256.new()
hh.update(unhexlify('38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1'))
hex_signature = signer.sign(hh)
# Compare signature with OpenSSL signature
output == hex_signature # False
但这些结果也不相同。
我显然做错了,但我对Python加密库不太熟悉,无法弄清楚它是什么。我做错了什么?
答案 0 :(得分:0)
默认情况下,echo
命令(或内置shell)会向输出添加一个新行,因此签名永远不会匹配。尝试禁用它。
$ echo -n foo | wc -c # hint - this counts number of bytes
3
$ echo foo | wc -c
4
但就个人而言,我只是将字符串作为标准输入直接传递给第二个进程。