C# Support for RSA SHA 256 signing for individual XML elements

后端 未结 2 1674
借酒劲吻你
借酒劲吻你 2021-01-07 03:58

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

相关标签:
2条回答
  • 2021-01-07 04:28

    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.

    0 讨论(0)
  • 2021-01-07 04:48

    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.

    0 讨论(0)
提交回复
热议问题