问题描述
我遇到了.NET Framework 4.5版的阻止程序,该程序与使用数字签名的XML签名有关.
I have encountered a blocker with the .NET Framework version 4.5 to do with signing of XML with digital signatures.
我的问题是基于需要使用RSA SHA-256算法使用X.509证书对单个XML元素进行签名.我已经阅读了许多有关此主题的.NET帖子,似乎有一种解决方案最初是在CLR安全性项目RSAPKCS1SHA256SignatureDescription.cs类中开发的.RSAPKCS1SHA256SignatureDescription当然已经被合并到.net运行时中,并且从.NET 4.5开始,现在可以在分布式二进制System.Deployment.dll下使用.我曾尝试在.NET中使用上述解决方案来使用RSA SHA-256签名特定的XML元素,但尚未取得任何成功.
My problem is based around the need to sign individual XML elements with X.509 certificate with the RSA SHA-256 algorithm. I have read many .NET posts on this topic and it appears that there is a solution originally developed in the CLR Security project RSAPKCS1SHA256SignatureDescription.cs class. RSAPKCS1SHA256SignatureDescription has of course since been incorporated into the .net runtime and as of .NET 4.5 is now available under the distributed binary System.Deployment.dll. I have attempted the above solution in .NET to sign specific XML elements with RSA SHA-256 however have yet to have any success.
我正在尝试使用WSSE令牌对符合Oasis ebms标准的SOAP消息进行签名.请注意,编写该类是为了满足带附件的肥皂(SwA)和对单个附件进行签名的要求.我的代码如下
I am trying to sign a SOAP message complying with the Oasis ebms standard with a WSSE Token. Please be aware that the class is written to cater for Soap With Attachments (SwA) and signing individual attachments.My code is as follows
我的代码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.IdentityModel.Tokens;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Deployment.Internal.CodeSigning;
namespace TestCSharpX509CertificateRSSHA256
{
public class SignatureSupportUtility
{
private bool IsSignatureContentTransform
{
get
{
return true;
//get IsSignatureContentTransform
}
}
public SignatureSupportUtility()
{
Register();
}
private static void Register()
{
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
}
private void Sign(Message message, string[] elementIdsToSign, string[] attachmentsToSign, string wssNamespace, X509Certificate2 certificate)
{
//Prepare XML to encrypt and sign
var element = this.PrepareEncyrptSign(message);
bool signEntireDocument = true;
string elementToBeSigned = string.Empty;
var signedMessage = new XmlDocument();
signedMessage.AppendChild(signedMessage.ImportNode(element, true));
SignatureType signAs = SignatureType.InternallyDetached;
signedMessage.PreserveWhitespace = false;
OverrideSignedXml signedXml = new OverrideSignedXml(signedMessage);
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
if (elementIdsToSign != null && elementIdsToSign.Length > 0)
{
bool isContentTransform = this.IsSignatureContentTransform;
foreach (string s in elementIdsToSign)
{
// Create a reference to be signed.
Reference reference = new Reference(string.Format("#{0}", s));
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
}
signEntireDocument = false;
}
// Reference attachments to sign
if (attachmentsToSign != null && attachmentsToSign.Length > 0)
{
bool isContentTransform = this.IsSignatureContentTransform;
foreach (string attachmentId in attachmentsToSign)
{
// Create a reference to be signed.
Reference reference = new Reference(string.Format("{0}{1}", Constants.CidUriScheme, attachmentId));
reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
if (isContentTransform)
{
AttachmentContentSignatureTransform env = new AttachmentContentSignatureTransform();
reference.AddTransform(env);
}
else
{
AttachmentCompleteSignatureTransform env = new AttachmentCompleteSignatureTransform();
reference.AddTransform(env);
}
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
}
signEntireDocument = false;
}
if (signEntireDocument)
{
Reference reference = new Reference();
reference.Uri = "";
reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
signedXml.AddReference(reference);
signAs = SignatureType.Enveloped;
}
string x509CertificateReferenceId = string.Format("{0}-{1}", Constants.IdAttributeName, Guid.NewGuid().ToString("N"));
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509SecurityTokenReference(string.Format("#{0}", x509CertificateReferenceId), wssNamespace));
signedXml.KeyInfo = keyInfo;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
RSA key = (RSACryptoServiceProvider)certificate.PrivateKey;
signedXML.SigningKey = key;
CidWebRequest.Message = message;
signedXml.ComputeSignature();
var xmlSignature = signedXml.GetXml();
XmlDocument unsignedEnvelopeDoc = new XmlDocument();
unsignedEnvelopeDoc.LoadXml(message.MessageAsString); }}}
using System;
using System.Collections.Generic;
using System.IO;
using System.IdentityModel.Tokens;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Deployment.Internal.CodeSigning;
namespace TestCSharpX509CertificateRSSHA256
{
public sealed class OverrideSignedXml : SignedXml
{
public OverrideSignedXml()
: base()
{
}
public OverrideSignedXml(XmlDocument doc)
: base(doc)
{
}
public override XmlElement GetIdElement(XmlDocument document, string idValue)
{
XmlElement element = base.GetIdElement(document, idValue);
if (element == null)
{
XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("wsu", ="http://docs.oasis-open. org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
element = document.SelectSingleNode("//*[@wsu:Id=\"" + idValue + "\"]", nsmgr) as XmlElement;
}
return element;
}
}
}
我的SignatureSupportUtility类中的Sign方法应该足以对单个XML元素或整个消息进行签名,但是我一直收到一个密码学异常,声称不支持SHA-256.考虑到RSAPKCS1SHA256SignatureDescription.cs已注册,我认为此异常无效.但是,观察到SignedXML类不包含SHA-256的名称空间,而仅包含SHA-128的名称空间,我开始怀疑是否支持SHA 256(无论注册如何).
The Sign method in my SignatureSupportUtility class should be adequate to sign individual XML elements or the whole message, however I keep receiving a Cryptography exception claiming that the SHA-256 is not supported. I think this exception should not be valid observing that the RSAPKCS1SHA256SignatureDescription.cs is registered. However observing that the SignedXML class does not include the namespace for SHA-256 and only SHA-128 I am beginning to doubt if the SHA 256 is supported regardless of registration.
有人可以建议我如何最好地解决我的问题,以及如何通过RSA SHA 256算法使用X.509证书对XML签名吗?
Could someone please advise me on how best to resolve my issue and be able to sign XML with an X.509 certificate via RSA SHA 256 algorithm?
推荐答案
我也在寻找Oasis ebms的东西.
I am also looking at the Oasis ebms stuff.
我找不到我从中获得的文章,但是我使用的是4.5中的该类:
I cannot find the article I took this from but I used that class that is in 4.5:
public class RsaPkCs1Sha256SignatureDescription : SignatureDescription
{
public RsaPkCs1Sha256SignatureDescription()
{
KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider";
DigestAlgorithm = "System.Security.Cryptography.SHA256Managed";
FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
}
public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
var asymmetricSignatureDeformatter = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm);
asymmetricSignatureDeformatter.SetKey(key);
asymmetricSignatureDeformatter.SetHashAlgorithm("SHA256");
return asymmetricSignatureDeformatter;
}
,然后使用类似这样的符号进行签名(已编辑了一些无关的位):
and then use something like this to sign (have edited some irrelevant bits out):
public XmlElement SignDocument(XmlDocument doc, List<string> idsToSign)
{
CryptoConfig.AddAlgorithm(typeof(RsaPkCs1Sha256SignatureDescription), @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
var cspParams = new CspParameters(24) { KeyContainerName = "XML_DISG_RSA_KEY" };
var key = new RSACryptoServiceProvider(cspParams);
key.FromXmlString(_x509SecurityToken.Certificate.PrivateKey.ToXmlString(true));
var signer = new SoapSignedXml(doc) { SigningKey = key };
signer.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
var keyInfo = new KeyInfo();
keyInfo.AddClause(new SecurityTokenReference(_x509SecurityToken, SecurityTokenReference.SerializationOptions.Embedded));
signer.KeyInfo = keyInfo;
signer.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
var cn14Transform = new XmlDsigExcC14NTransform();
string referenceDigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
foreach (string id in idsToSign)
{
var reference = new Reference("#" + id);
reference.AddTransform(cn14Transform);
reference.DigestMethod = referenceDigestMethod;
signer.AddReference(reference);
}
signer.ComputeSignature();
return signer.GetXml();
}
似乎可以正常工作,并在另一端验证OK.前几天与Holodeck进行了测试,我认为签名元素缺少的时间戳失败了.
seems to work and verifies OK at the other end. Tested with Holodeck the other day and I think it failed on a timestamp that was missing from the signature elements.
但是,附件的签名似乎是.NET中的一个实际问题-我认为根本不支持相关的转换.
However, the signing of attachments seems to be a real problem in .NET - I don't think the relevant transforms are supported at all.
这篇关于C#支持单个XML元素的RSA SHA 256签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!