7

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.

Alex Jorgenson
  • 891
  • 1
  • 13
  • 17
UncleZen
  • 289
  • 1
  • 4
  • 22
  • 5
    I resolved this issue (thanks Phillip) as follows: /* add the following lines of code after var signingCertificate = GetCertificate();*/ CspParameters cspParams = new CspParameters(24); cspParams.KeyContainerName = "XML_DISG_RSA_KEY"; RSACryptoServiceProvider key = new RSACryptoServiceProvider(cspParams); key.FromXmlString(signingCertificate.PrivateKey.ToXmlString(true)); /*assign the new key to signer's SigningKey */ metadataSigner.SigningKey = key; – UncleZen Aug 03 '12 at 18:00
  • thx UncleZen that fixed it but cspParams.KeyContainerName = "XML_DISG_RSA_KEY" is not neccessary it works also without it. – BitSchupser Oct 07 '13 at 11:20

3 Answers3

3

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);

minhj
  • 31
  • 2
  • This does not answers the question – Avi Turner Jun 16 '13 at 04:04
  • 5
    That does not answer the question, but after implementing UncleZen's solution you would get the error "Key not valid for use in specified state" if the key was not flagged as exportable. – BitSchupser Oct 07 '13 at 12:23
3

string signatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

This signature method is not implemented in .NET according to https://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signedinfo.signaturemethod(v=vs.110).aspx

yaras
  • 31
  • 3
1

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.

Gokulnath
  • 1,166
  • 15
  • 29