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

.NET中使用SHA256验证ECDSA签名问题求助

ECDSA签名验证失败的解决方法

问题核心

你提供的签名并非原始ECDSA(r,s)签名对,而是PKCS#7(CMS)格式的封装签名,这是直接调用VerifyData或BouncyCastle Signer验证失败的主要原因。同时需确保数据编码、哈希算法与遗留系统一致。

解决方案:使用.NET内置SignedCms验证PKCS#7签名

以下是修正后的验证代码,直接解析PKCS#7签名并完成验证:

using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Text;

class SignatureVerification
{
    private static void Main(string[] args)
    {
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

        var publicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwhDZNphi4J1EiBCQwZ1WBCYbnf9Ne6UqPuLLGJPTj5++io9pxT3McYgFFFPb7HdfJCrPsKmTVwlw9Z1RpQru6g==";
        var signature = "BEgwRgIhAPqcBPjRROiwTBUFTF50iDXSBn+e71c3fIj9kgfxUbAZAiEAR6KM+u8D6TWtaKVdH8EjLxWJf4Vm/u2Z5YptKEjTgHs=";
        var data = ";\"4399901879126\";\"302.1302.006\";\"4005249001296\";\"20240627151654328\";";

        // 将公钥转换为临时X509证书(仅用于承载公钥信息,无需私钥)
        var pubKeyBytes = Convert.FromBase64String(publicKey);
        var ecdsa = ECDsa.Create();
        ecdsa.ImportSubjectPublicKeyInfo(pubKeyBytes, out _);
        var cert = new X509Certificate2();
        cert = cert.CopyWithPrivateKey(ecdsa);

        // 执行PKCS#7签名验证
        bool isValid = VerifyPkcs7Signature(Encoding.Latin1.GetBytes(data), Convert.FromBase64String(signature), cert);
        Console.WriteLine(isValid ? "验证成功" : "验证失败");
        Console.ReadLine();
    }

    public static bool VerifyPkcs7Signature(byte[] data, byte[] pkcs7Signature, X509Certificate2 verifyingCert)
    {
        var signedCms = new SignedCms(new ContentInfo(data));
        signedCms.Decode(pkcs7Signature);

        var verifyParams = new X509Certificate2Collection(verifyingCert);
        return signedCms.CheckSignature(verifyParams, true);
    }
}

关键说明

  • PKCS#7签名解析:SignedCms类专门处理PKCS#7格式签名,会自动解析签名中的哈希算法、原始签名值等信息,无需手动处理复杂的ASN.1结构。
  • 公钥转换:SignedCms需要证书对象完成验证,这里用公钥临时构造证书(仅用于承载公钥,实际验证不需要私钥)。
  • 编码一致性:代码保留Encoding.Latin1,确保与遗留系统的数据编码匹配,这是验证成功的必要前提。

备选方案:提取原始ECDSA签名值验证

若不想使用SignedCms,可解析PKCS#7签名提取原始(r,s)对,再用ECDSA直接验证(需依赖BouncyCastle库):

using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Security;
using System.Linq;

public static bool VerifyRawEcdsaSignature(byte[] pubKeyBytes, byte[] data, byte[] pkcs7Signature)
{
    // 解析PKCS#7签名,提取原始签名值
    var cms = new CmsSignedData(pkcs7Signature);
    var signerInfos = cms.GetSignerInfos();
    var signer = signerInfos.GetSigners().Cast<SignerInformation>().First();
    var rawSignature = signer.GetSignature();

    // 验证原始ECDSA签名
    var publicKey = PublicKey.CreateFromSubjectPublicKeyInfo(pubKeyBytes, out _);
    var ecdsa = publicKey.GetECDsaPublicKey();
    return ecdsa.VerifyData(data, rawSignature, HashAlgorithmName.SHA256);
}

内容的提问来源于stack exchange,提问作者wvdhouten

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:30:54