Python中如何用PKCS12证书签名SHA256哈希后的XML请求?
使用PKCS12证书签名SOAP XML请求的正确实现
问题
要向SOAP API发送请求,需按以下流程处理:
- 对XML请求内容生成SHA256哈希
- 使用PKCS12证书中的RSA私钥对哈希值签名
尝试用PyCryptodome(Crypto库)实现时触发IndexError,换用cryptography库能成功加载PKCS12证书,但不清楚如何用该库完成签名流程,求可行的实现代码。
失败的Crypto库实现代码
from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA from Crypto.Signature import pkcs1_15 with open("/my/cert/file.p12", "rb") as f: cert_data = f.read() private_key = RSA.import_key(cert_data, passphrase="some_passphrase") signer = pkcs1_15.new(private_key) hash = SHA256.new(xml_data) signature = signer.sign(hashed)
报错信息
security/crypto.py:25: in __init__ private_key = RSA.import_key(cert.certificate, passphrase=cert.passphrase) /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/PublicKey/RSA.py:851: in import_key return _import_keyDER(extern_key, passphrase) /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/PublicKey/RSA.py:746: in _import_keyDER return decoding(extern_key, passphrase) /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/PublicKey/RSA.py:697: in _import_pkcs1_private der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:610: in decode result = DerObject.decode(self, der_encoded, strict=strict) /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:228: in decode self._decodeFromStream(s, strict) /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:623: in _decodeFromStream DerObject._decodeFromStream(self, s, strict) /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:245: in _decodeFromStream length = self._decodeLen(s) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <Crypto.Util.asn1.DerSequence object at 0x7f03288f97d0> s = <Crypto.Util.asn1.BytesIO_EOF object at 0x7f0328890310> def _decodeLen(self, s): """Decode DER length octets from a file.""" length = s.read_byte() if length > 127: encoded_length = s.read(length & 0x7F) > if bord(encoded_length[0]) == 0: E IndexError: index out of range /Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:205: IndexError
正确的cryptography库实现方案
cryptography库可以通过组合哈希与签名步骤,实现和Crypto库一致的PKCS#1 v1.5签名逻辑,以下是完整可行代码:
完整实现代码
import base64 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.serialization import pkcs12 # 1. 加载PKCS12证书中的私钥 with open("/my/cert/file.p12", "rb") as f: private_key, certificate, additional_certs = pkcs12.load_key_and_certificates( f.read(), password=b"some_passphrase" # 密码需传入字节类型 ) # 2. 准备XML请求数据(确保为字节类型,字符串需先encode转换) xml_data = "your_soap_xml_content_here".encode("utf-8") # 3. 执行签名:自动完成SHA256哈希+RSA-PKCS#1 v1.5签名 signature = private_key.sign( xml_data, padding.PKCS1v15(), hashes.SHA256() ) # 4. 将签名转为Base64格式(SOAP API通常要求此可传输格式) base64_signature = base64.b64encode(signature).decode("utf-8") print(base64_signature)
可选:手动哈希后签名(与Crypto库逻辑完全对齐)
如果需要先手动计算哈希再签名,可替换签名步骤为:
# 手动计算SHA256哈希 digest = hashes.Hash(hashes.SHA256()) digest.update(xml_data) hashed_data = digest.finalize() # 对哈希值签名 signature = private_key.sign( hashed_data, padding.PKCS1v15(), hashes.SHA256() )
内容的提问来源于stack exchange,提问作者Woody1193
相关产品推荐
相关产品推荐

