c# - SignedXml 使用 SHA256 计算签名

标签 c# xml encryption digital-signature

我正在尝试使用 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 文件加载到 Microsoft Enhanced Cryptographic Provider v1.0(提供程序类型 1 又名 PROV_RSA_FULL) 不支持 SHA-256。

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

但是,另一个 CryptoAPI 提供程序 Microsoft Enhanced RSA and AES Cryptographic Provider(提供程序类型 24 a.k.a. PROV_RSA_AES)确实支持 SHA-256。因此,如果我们将私钥输入该提供程序,我们就可以使用它进行签名。

首先,您必须调整您的 X509Certificate2 构造函数,使 key 能够从 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 实例后,告诉它使用key 而不是cert.PrivateKey:

signedXml.SigningKey = key;

它现在可以工作了。

这是 list of provider types and their codes在 MSDN 上。

这是您的示例的完整调整代码:

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

X509Certificate2 cert = new X509Certificate2(@"location of pks file", "password", 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, 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();

关于c# - SignedXml 使用 SHA256 计算签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29005876/

相关文章:

c# - 如何在 C# 中将函数作为参数传递?

c# - 谷歌相册 API mediaItems :batchCreate : NOT_IMAGE: There was an error while trying to create this media item

c# - 作为实例变量的类组合

c# - 使用 ACL 保护 WCF 配置文件

python - xml.etree.ElementTree 获取节点深度

html - 为什么 <?xml version ="1.0"encoding ="UTF-8"?> 不应该放在最上面?

xml - Illustrator SVG 效果编码问题

Javascript 到 Java AES

python - 图像中存储的像素值会自动更改。如果图像再次在另一个函数中打开

Javascript 到 Ruby 加密