在Django中实现C# RSA SHA1签名功能遇报错求助
解决Django中RSA SHA1签名与C#不一致及DER编码错误问题
首先,我们先对比你的C#代码和Python代码的核心差异,然后一步步修复问题:
问题分析
你的C#签名逻辑是:
- 直接将输入字符串
data转为UTF-8字节数组 - 使用SHA1哈希算法对该字节数组进行签名(
SignData内部会完成哈希计算) - 签名结果转为Base64返回
而你的Python代码存在三个关键问题:
- 对输入
data做了额外的Base64编码(C#中没有这一步) - 哈希算法初期不匹配,改SHA1后仍有流程错误
- 私钥格式可能不兼容(C#用XML格式私钥,Python默认解析PEM格式)
修复步骤
1. 修正签名流程,匹配C#逻辑
去掉不必要的Base64编码,改用SHA1哈希算法,调整后的代码如下:
from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA1 # 替换为SHA1哈希类 from base64 import b64encode import logging logger = logging.getLogger(__name__) def sign_data(data, private_key_path): # 1. 将data转为UTF-8字节数组(和C#一致,不做额外Base64编码) message = bytes(data, 'utf-8') # 2. 使用SHA1哈希(匹配C#的SHA1CryptoServiceProvider) digest = SHA1.new() digest.update(message) # 3. 导入私钥 private_key = None logger.info(private_key_path) with open(private_key_path, "r") as key_file: private_key = RSA.importKey(key_file.read()) # 4. 使用PKCS1_v1_5签名(和C#的RSACryptoServiceProvider默认签名格式一致) signer = PKCS1_v1_5.new(private_key) sig = signer.sign(digest) # 5. 签名结果转Base64返回(转为字符串更符合Django使用场景) return b64encode(sig).decode('utf-8')
2. 解决私钥格式兼容问题
你的C#代码中使用XML格式的RSA私钥,而PyCryptodome的RSA.importKey默认支持PEM格式(如-----BEGIN RSA PRIVATE KEY-----开头的格式)。如果你的私钥是XML格式,需要先转换为PEM格式,或者用Python解析XML提取密钥参数:
解析XML私钥的代码示例:
import xml.etree.ElementTree as ET from Crypto.PublicKey import RSA def import_rsa_from_xml(xml_string): root = ET.fromstring(xml_string) modulus = int(root.find('./Modulus').text, 16) exponent = int(root.find('./Exponent').text, 16) d = int(root.find('./D').text, 16) p = int(root.find('./P').text, 16) q = int(root.find('./Q').text, 16) dp = int(root.find('./DP').text, 16) dq = int(root.find('./DQ').text, 16) qi = int(root.find('./InverseQ').text, 16) return RSA.construct((modulus, exponent, d, p, q, dp, dq, qi))
然后在sign_data中替换私钥导入部分:
with open(private_key_path, "r") as key_file: private_key = import_rsa_from_xml(key_file.read())
3. 验证签名一致性
修复后,你可以用相同的data和私钥分别在C#和Python中测试签名结果,应该会得到一致的Base64字符串。
为什么会出现DER编码错误?
当你改用SHA1时出现ValueError("Trying to DER encode an unknown object"),是因为你可能没有正确导入SHA1哈希类,或者哈希对象类型不匹配,导致签名时无法生成正确的ASN.1 DER编码的签名结构。使用正确的SHA1.new()生成哈希对象后,这个问题会自动解决。
内容的提问来源于stack exchange,提问作者Jack Park
相关产品推荐
相关产品推荐

