签名验证需要哪些必要信息?
What is the necessary info need by signature verification?
我写了一个基于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)作为输入?
但是在openssl CLI Generate EC KeyPair from OpenSSL command line
openssl dgst -sha256 -verify public.pem -signature msg.signature.txt msg.digest.txt
为什么这里没有提到padding?我认为无论密钥对算法(ECC或RSA)是否不同,(标准?)验证方法的输入参数应该是相同的。
另一个问题,我在python中看到有isinstance(public_key, rsa.RSAPublicKey)
可以找出密钥的算法
验证方法是否也需要算法类型?
像lib里面可能有这样的ecc_verify
rsa_verify
方法。
顺便说一句,据我了解,verify
方法参数(与 openssl CLI 相同):
- public键
- 哈希类型
- 签名
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 padding) 一样。 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 哈希方面有所不同(最好像您一样明确指定它)。
我写了一个基于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)作为输入?
但是在openssl CLI Generate EC KeyPair from OpenSSL command line
openssl dgst -sha256 -verify public.pem -signature msg.signature.txt msg.digest.txt
为什么这里没有提到padding?我认为无论密钥对算法(ECC或RSA)是否不同,(标准?)验证方法的输入参数应该是相同的。
另一个问题,我在python中看到有isinstance(public_key, rsa.RSAPublicKey)
可以找出密钥的算法
验证方法是否也需要算法类型?
像lib里面可能有这样的ecc_verify
rsa_verify
方法。
顺便说一句,据我了解,verify
方法参数(与 openssl CLI 相同):
- public键
- 哈希类型
- 签名
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 padding) 一样。 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 哈希方面有所不同(最好像您一样明确指定它)。