这两个链接代码使用以下方式实现低级签名RSASSA-PKCS1-v1_5,但消息使用的是修改后的编码,而不是EMSA-PKCS1-v1_5,因此处理与标准不同。
两个主要的 Python 加密库PyCryptodome and 密码学只支持高级签名,它封装了entire过程遵循标准,因此不允许对消息的编码进行任何修改。
解决该问题的最有效方法是使用还支持低级签名的 Python 库,以便可以使用链接的 Java 或 Python 代码中的消息编码。但是,我不知道有这样的图书馆。
如果您也不知道这样的库,还有以下替代方案:由于 RSASSA-PKCS1-v1_5 非常简单,并且 Python 本身支持大整数及其操作,因此可以将自定义实现与辅助函数相结合,例如PyCryptodome很容易成为可能。至少你不必再依赖遗留库了:
from Crypto.Util import number
def customizedSign(key, msg):
modBits = number.size(key.n)
k = number.ceil_div(modBits, 8)
ps = b'\xFF' * (k - len(msg) - 3)
em = b'\x00\x01' + ps + b'\x00' + msg
em_int = number.bytes_to_long(em)
m_int = key._decrypt(em_int)
signature = number.long_to_bytes(m_int, k)
return signature
解释:
实施遵循PyCryptodome
的实施sign()方法。这only功能差异在于,使用链接代码的编码而不是 EMSA-PKCS1-v1_5。
EMSA-PKCS1-v1_5 定义为:
EM = 0x00 || 0x01 || PS || 0x00 || T
where T
是 DER 编码的 DigestInfo 值和散列消息的串联,请参阅here.
链接代码的编码仅使用消息MSG
代替T
:
EM = 0x00 || 0x01 || PS || 0x00 || MSG
在这两种情况下,PS
是一个填充,其值是 0xFF,最高可达密钥大小(即模数的大小)。
使用及测试:
由于签名是确定性的,因此相同的密钥和相同的消息始终提供相同的签名。这样就很容易证明上面的函数等价于链接的 Java 或 Python 代码:
from Crypto.PublicKey import RSA
import base64
# For simplicity, a 512 bits key is used. Note that a 512 bits key may only be used for testing, in practice the key size has to be >= 2048 bits for security reasons.
pkcs8 = """-----BEGIN PRIVATE KEY-----
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA2gdsVIRmg5IH0rG3
u3w+gHCZq5o4OMQIeomC1NTeHgxbkrfznv7TgWVzrHpr3HHK8IpLlG04/aBo6U5W
2umHQQIDAQABAkEAu7wulGvZFat1Xv+19BMcgl3yhCdsB70Mi+7CH98XTwjACk4T
+IYv4N53j16gce7U5fJxmGkdq83+xAyeyw8U0QIhAPIMhbtXlRS7XpkB66l5DvN1
XrKRWeB3RtvcUSf30RyFAiEA5ph7eWXbXWpIhdWMoe50yffF7pW+C5z07tzAIH6D
Ko0CIQCyveSTr917bdIxk2V/xNHxnx7LJuMEC5DcExorNanKMQIgUxHRQU1hNgjI
sXXZoKgfaHaa1jUZbmOPlNDvYYVRyS0CIB9ZZee2zubyRla4qN8PQxCJb7DiICmH
7nWP7CIvcQwB
-----END PRIVATE KEY-----"""
key = RSA.import_key(pkcs8)
msg = 'The quick brown fox jumps over the lazy dog'.encode('utf8')
signature = customizedSign(key, msg)
print(base64.b64encode(signature).decode('utf8')) # OwpVG/nPmkIbVxONRwXHvOqLdYNnP67YtiWA+GcKBZ3rIzAJ+8izvmlqUQnzVp03Wrrzq2ogUmCMaLSPlInDNw==
链接的 Java 代码为相同的密钥和消息提供相同的签名。