You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django中实现C# RSA SHA1签名功能遇报错求助

解决Django中RSA SHA1签名与C#不一致及DER编码错误问题

首先,我们先对比你的C#代码和Python代码的核心差异,然后一步步修复问题:

问题分析

你的C#签名逻辑是:

  • 直接将输入字符串data转为UTF-8字节数组
  • 使用SHA1哈希算法对该字节数组进行签名(SignData内部会完成哈希计算)
  • 签名结果转为Base64返回

而你的Python代码存在三个关键问题:

  1. 对输入data做了额外的Base64编码(C#中没有这一步)
  2. 哈希算法初期不匹配,改SHA1后仍有流程错误
  3. 私钥格式可能不兼容(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:02:43