Signing an Xml Document using RSA-SHA256 signature method issue

14.3k views Asked by At

I am using the method below to sign Xml Documents:

public static XmlDocument SignDocument(XmlDocument doc)
    {
        string signatureCanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
        string signatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
        string digestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256";

        string signatureReferenceURI = "#_73e63a41-156d-4fda-a26c-8d79dcade713";

        CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), signatureMethod);

        var signingCertificate = GetCertificate();

        SignedXml signer = new SignedXml(doc);
        signer.SigningKey = signingCertificate.PrivateKey;
        signer.KeyInfo = new KeyInfo();
        signer.KeyInfo.AddClause(new KeyInfoX509Data(signingCertificate));

        signer.SignedInfo.CanonicalizationMethod = signatureCanonicalizationMethod;
        signer.SignedInfo.SignatureMethod = signatureMethod;

        XmlDsigEnvelopedSignatureTransform envelopeTransform = new XmlDsigEnvelopedSignatureTransform();
        XmlDsigExcC14NTransform cn14Transform = new XmlDsigExcC14NTransform();

        Reference signatureReference = new Reference();
        signatureReference.Uri = signatureReferenceURI;
        signatureReference.AddTransform(envelopeTransform);
        signatureReference.AddTransform(cn14Transform);
        signatureReference.DigestMethod = digestMethod;

        signer.AddReference(signatureReference);

        signer.ComputeSignature();
        XmlElement signatureElement = signer.GetXml();

        doc.DocumentElement.AppendChild(signer.GetXml());

        return doc;
    }


        private static X509Certificate2 GetCertificate()
    {

        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2 card = null;
        foreach (X509Certificate2 cert in store.Certificates)
        {
            if (!cert.HasPrivateKey) continue;

            if (cert.Thumbprint.Equals("a_certain_thumb_print", StringComparison.OrdinalIgnoreCase))
            {
                card = cert;
                break;
            }
        }
        store.Close();

        return card;
    }

An exception of type System.Security.Cryptography.CryptographicException is thrown when trying to compute the signature with the error message Invalid algorithm specified. Any ideas?

Machine: Windows Server 2008 R2

.Net Framework: 4.0.

IDE: Visual Studio 2010.

3

There are 3 answers

2
minhj On

Thanks so much for this blog. It actually solved my problem. By the way, if certificate is loaded from file, it should be exportable: X509Certificate2 x509Key = new X509Certificate2("xxxxx.pfx", "123", X509KeyStorageFlags.Exportable);

0
Gokulnath On

The reply from @minhj mentions about some blog, but the link is not there.

However, adding the class mentioned here and registering it fixed the problem. Seems it should be registered only once per app domain.

0
yaras On