python - 签名验证需要哪些必要信息?

标签 python openssl cryptography rsa pycrypto

我写了一个基于rsa的签名验证完整流程的测试demo,这有助于我弄清楚流程的逻辑。

# https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa

# Preparation phase
# Generate key pairs
# private_key contains the both private key and public key
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)

# Serilize the keys
from cryptography.hazmat.primitives import serialization

pem = private_key.private_bytes(
   encoding=serialization.Encoding.PEM,
   format=serialization.PrivateFormat.PKCS8,
   encryption_algorithm=serialization.BestAvailableEncryption(b'mypassword')
)
with open('private-key.pem', 'wb') as f:
    f.write(pem)
    f.close()

public_key = private_key.public_key()
pem = public_key.public_bytes(
   encoding=serialization.Encoding.PEM,
   format=serialization.PublicFormat.SubjectPublicKeyInfo
)
with open('public-key.pem', 'wb') as f:
    f.write(pem)
    f.close()

# Signer
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric import utils

with open('private-key.pem', 'rb') as f:
    private_key = serialization.load_pem_private_key(
        f.read(),
        password=b'mypassword',
        backend=default_backend()
    )

    chosen_hash = hashes.SHA256()
    hasher = hashes.Hash(chosen_hash, default_backend())
    hasher.update(b"data & ")
    hasher.update(b"more data")
    digest = hasher.finalize()

    signature = private_key.sign(
        digest,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        utils.Prehashed(chosen_hash)
    )

    with open('signature', 'wb') as f:
        f.write(signature)
        f.close()

# Verifier
chosen_hash = hashes.SHA256()
hasher = hashes.Hash(chosen_hash, default_backend())
hasher.update(b"data & ")
hasher.update(b"more data")
digest = hasher.finalize()

hasher1 = hashes.Hash(chosen_hash, default_backend())
hasher1.update(b"data & more data")
digest1 = hasher1.finalize()
print(digest == digest1)

with open('signature', 'rb') as f:
    signature = f.read()

with open('public-key.pem', 'rb') as f:
    public_key  = serialization.load_pem_public_key(
        f.read(),
        backend=default_backend()
    )

    if isinstance(public_key, rsa.RSAPublicKey):
        public_key.verify(
            signature,
            digest,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            utils.Prehashed(chosen_hash)
        )

问题:

验证时是否必须将填充类型(例如 PSS)已知为输入?

但是在 CLI Generate EC KeyPair from OpenSSL command line

openssl dgst -sha256 -verify public.pem -signature msg.signature.txt msg.digest.txt

为什么这里没有提到填充?我认为无论 key 对算法(ECC还是RSA)不同,(标准?)验证方法的输入参数应该是相同的。

另一个问题,我在python中看到有isinstance(public_key, rsa.RSAPublicKey)可以找出 key 的算法。

验证方法也需要算法类型吗?

就像库内部可能有这样的 ecc_verify rsa_verify 方法。

顺便说一句,根据我的理解,verify 方法参数(与 openssl CLI 相同):

  • 公钥
  • 哈希类型
  • 签名

最佳答案

Does the padding type(eg. PSS) having to be known as input when verification?

是的,填充是一个必需的配置参数,应该事先知道。

Why here didn't mention the padding?

ECDSA签名验证不需要填充;它与 RSA 签名生成/验证有显着不同。

它只有一个使用的标准,就像之前 RSA 的情况一样(PKCS#1 v1.5 填充)。 PSS 是在 2.0 版本发布后才添加到 RSA PKCS#1 标准中的。

Does the algorithm type also necessary for the verification method?

尽管可能没有直接攻击,但您应该假设验证算法是预先已知的,就像填充方法一样。 PKCS#1 中描述的 RSA 至少有两个签名生成函数,其他标准中还有更多 - 尽管这些函数根本不常见。

BTW for my understanding, the verify method parameter(same as openssl CLI):

正如您已经看到的,RSA PSS 使用两个哈希函数,一个用于对输入数据进行哈希处理,另一个用于用于填充的内部 MGF1 函数。所以哈希类型不是只有一种,而是两种。哈希类型不一定相同,并且实现在确定 MGF1 哈希的方式上有所不同(像您一样明确指定它是最好的)。

关于python - 签名验证需要哪些必要信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58228689/

相关文章:

openssl - 如何列出 OpenSSL 信任的证书?

python - SQLAlchemy 核心 - 如何使 ResultProxy 对于模式列名不区分大小写?

android - 如何阻止从 SL4A 启动的 WebView 隐藏通知栏?

Python: "not"关键字放置

ssl - 无法重启 nginx https 证书例程私钥不匹配

c# - 我的三重 DES 包装程序有什么问题?

python - 可以从现有日期时间实例创建的自定义日期时间子类?

ssl - 如何测试中间人 HTTPS 代理?

linux - 加密/解密在两个不同的 openssl 版本之间不能很好地工作

c# - 写入流时计算哈希