微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – SignedXml计算签名与SHA256

我正在尝试使用SHA256对 XML文档进行数字签名.

我试图用这个Security.Cryptography.dll.

这是我的代码

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription),"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

X509Certificate2 cert = new X509Certificate2(@"location of pks file","password");
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(@"input.xml");

SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = cert.PrivateKey;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

// 
// Add a signing reference,the uri is empty and so the whole document 
// is signed. 
Reference reference = new Reference();
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.Uri = "";
signedXml.AddReference(reference);

// 
// Add the certificate as key info,because of this the certificate 
// with the public key will be added in the signature part. 
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
// Generate the signature. 
signedXml.ComputeSignature();

但是我得到“指定的无效的算法”. signedXml.ComputeSignature();.谁能告诉我我做错了什么?

解决方法

X509Certificate2将私钥从pfx文件加载到不支持SHA-256的Microsoft Enhanced Cryptographic Provider v1.0(提供商类型1 a.k.a. PROV_RSA_FULL)中.

基于CNG的加密提供程序(在Vista和Server 2008中引入)支持比基于CryptoAPI的提供程序更多的算法,但是.NET代码似乎还在使用基于CryptoAPI的类,如RSACryptoServiceProvider而不是RSACng,所以我们必须解决这些限制.

但是,另一个CryptoAPI提供程序,Microsoft增强型RSA和AES加密提供程序(提供者类型24 a.k.a. PROV_RSA_AES)支持SHA-256.所以如果我们把这个私钥加入这个提供者,我们可以用它签名.

首先,您必须调整X509Certificate2构造函数,以便将密钥从X509Certificate2将其引入的提供者中导出,方法添加X509KeyStorageFlags.Exportable标志:

X509Certificate2 cert = new X509Certificate2(
    @"location of pks file","password",X509KeyStorageFlags.Exportable);

并导出私钥:

var exportedKeyMaterial = cert.PrivateKey.ToXmlString(
    /* includePrivateParameters = */ true);

然后为支持SHA-256的提供程序创建一个新的RSACryptoServiceProvider实例:

var key = new RSACryptoServiceProvider(
    new CspParameters(24 /* PROV_RSA_AES */));
key.PersistKeyInCsp = false;

并导入私钥:

key.FromXmlString(exportedKeyMaterial);

当您创建了SignedXml实例时,请告诉它使用密钥而不是cert.PrivateKey:

signedXml.SigningKey = key;

它现在可以工作.

以下是MSDN上的list of provider types and their codes.

以下是您的示例的完整调整代码

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription),X509KeyStorageFlags.Exportable);

// Export private key from cert.PrivateKey and import into a PROV_RSA_AES provider:
var exportedKeyMaterial = cert.PrivateKey.ToXmlString( /* includePrivateParameters = */ true);
var key = new RSACryptoServiceProvider(new CspParameters(24 /* PROV_RSA_AES */));
key.PersistKeyInCsp = false;
key.FromXmlString(exportedKeyMaterial);

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(@"input.xml");

SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = key;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

// 
// Add a signing reference,because of this the certificate 
// with the public key will be added in the signature part. 
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
// Generate the signature. 
signedXml.ComputeSignature();

原文地址:https://www.jb51.cc/csharp/94303.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐