.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
相关产品推荐
相关产品推荐

