I have encountered a blocker with the .NET Framework version 4.5 to do with signing of XML with digital signatures.
My problem is based around the need to sign indi
I am also looking at the Oasis ebms stuff.
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();
}
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.
However, the signing of attachments seems to be a real problem in .NET - I don't think the relevant transforms are supported at all.
Unfortunately Andrew's answer is not applicable when the private key cannot be exported.
I am using a smart-card and so far I have found no way of using SignedXML with SHA-256. This feature seems to be broken in the current implementation of RSACryptoServiceProvider.
The only solution in my opinion would be to switch from CSP to PKCS#11 and then use BouncyCastle.Net. And rewrite everything.