python使用有效负载和公钥字符串验证数字签名

Posted

技术标签:

【中文标题】python使用有效负载和公钥字符串验证数字签名【英文标题】:python verifying a digital signature with a payload and public key string 【发布时间】:2017-12-08 07:53:57 【问题描述】:

我有一个 Base64 编码的数据 ['payload']。 然后我有一个包含有效负载签名的“签名”。 我有一个公钥。 签名算法是SHA512withRSA

如何在 Python 中验证数据的真实性? 我正在使用以下代码进行检查,但它似乎不起作用

import base64
import hashlib
from Crypto.PublicKey import RSA 
from Crypto.Signature import SHA512
from Crypto.Hash import SHA512 
from base64 import b64decode 

# Public Key
key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEpFwIarbm48m6ueG+jhpt2vCGaqXZlwR/HPuL4zH1DQ/eWFbgQtVnrta8QhQz3ywLnbX6s7aecxUzzNJsTtS8VxKAYll4E1lJUqrNdWt8CU+TaUQuFm8vzLoPiYKEXl4bX5rzMQUMqA228gWuYmRFQnpduQTgnYIMO8XVUQXl5wIDAQAB"

# Base64 Encoded payload
payload = "some_string_payload"
decoded_payload = base64.b64decode(payload)

signature = "gw5K+WvO43673XBinZOmwgrZ3ttVuZ17/7SBnzqAAD4pgiwzYbZuEwn2lev6FW01f6TL0d9cNH4WtT53bQnTlhLQOZi4mHTTtM64O7MNljSA5zjJTUl77wXK/cJM+/G6R4YgYAnjydXAZjbMKY4Z9kV0qz2spdnS7Je7Q8I1xaU="
signature_algorithm = "SHA512withRSA"
keytype = "RSA"


m = hashlib.sha512()
m.update( key )
m.update( decoded_payload )
print m
m.hexdigest()
print m


keyDER = b64decode(key)
rsakey = RSA.importKey(keyDER)

signer = SHA512.new(rsakey) 

if signer.verify(m, b64decode(signature)):
    print "Verified"
else:
    print "Not Verified"

【问题讨论】:

您提供的签名是 1024 位长,但来自 SHA512 的签名应该只有 512 位长。这意味着您要么有错误的签名,要么有错误的算法。请使用新信息更新您的问题。另外,是否可以显示生成签名的代码?我们不需要私钥。 这与您验证 RSA 签名的方式相差甚远。 signer.verify() 应该抛出异常,因为签名者实际上是一个 Hash 对象并且没有 verify 方法。 每个带有“但它似乎不起作用”这样的文字并且没有包含问题的完整描述的问题都应该作为题外话关闭。 【参考方案1】:

问题中的代码有几个错误,按出现顺序排列:

导入了两种不同的 SHA512 实现; payload 显然不是 base 64 编码的,正常的 base 64 既不代表文本也不包含 _ 字符(但是 base-64-url 包含); 甚至没有使用signature_algorithmkeytype 变量; 不应对key 进行散列以实现正常的 PSS 签名方案; m.hexdigest() 的结果被忽略; 不能通过SHA512.new(rsakey)生成签名生成类; 如前所述,您的代码甚至无法编译,因为 SHA512 类无法签名;

相反,您可以使用任何其他 PSS 示例代码。例如,使用代码here 并注意这是我要指出的问题。这是一个最小的文档更改,但似乎没有人愿意在半年内修复它。

from Crypto.Signature import PKCS1_PSS
from Crypto.Hash import SHA512
from Crypto.PublicKey import RSA
from Crypto import Random
message = 'To be signed'
key = RSA.importKey(open('privkey.der').read())
h = SHA512.new()
h.update(message)
signer = PKCS1_PSS.new(key)
signature = PKCS1_PSS.sign(h)

请注意,PSS 也可以在内部使用哈希,如果签名验证失败,您可能必须定义自己的可调用代码,更多信息here。可能最好在代码中查找 MGF1 的默认实现,复制它然后更改哈希...

【讨论】:

以上是关于python使用有效负载和公钥字符串验证数字签名的主要内容,如果未能解决你的问题,请参考以下文章

为啥需要客户端验证 JWT?

JWT 令牌签名验证 javascript

iOS RSA加解密签名和验证

iOS RSA加解密签名和验证

在 Python 中使用 RSA 公钥验证签名的许可证密钥

如何在 Java 中使用令牌和公钥验证 JWT 签名