ATTENTION: WiBit.Net will be temporarily taken offline for routine maintenance on 9/22/2018. The site is expected to be down for 2-3 hours.
We apologize for any inconvenience.

X.509 Digital Signature SHA256 (In C#)




Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Net;
using System.IO;
using System.Security.Cryptography;


namespace net.wibit
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument doc = new XmlDocument();
            using (WebClient client = new WebClient())
                doc.LoadXml(client.DownloadString("https://www.wibit.net/labWebService/rest/getCoursesForCurriculum/1"));


            X509Certificate2 cert = new X509Certificate2(
                @"/path/to/cert.pfx",
                "CERT_PASSWORD",
                X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable
            );

            SignWithCertificateSHA256(doc, cert);
            File.WriteAllText(
                @"signed.xml",
                PrettyXml(doc)
            );

            Console.WriteLine(
                ValidateXmlDocumentWithCertificate(doc)
            );
        }
        // *********************************************************************************
        // *********************************************************************************
        // *********************************************************************************
        public static void SignWithCertificateSHA256(XmlDocument doc, X509Certificate2 cert)
        {
            // CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
            RSAPKCS1SHA256SignatureDescription.Register();
            if (doc.DocumentElement.Attributes["ID"] == null) doc.DocumentElement.SetAttribute("ID", Guid.NewGuid().ToString());

            RSACryptoServiceProvider key = new RSACryptoServiceProvider(new CspParameters(24));
            key.PersistKeyInCsp = false;
            key.FromXmlString(
                cert.PrivateKey.ToXmlString(true)
            );

            Reference reference = new Reference();
            reference.Uri = "#" + doc.DocumentElement.Attributes["ID"].Value;
            reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
            reference.AddTransform(new XmlDsigExcC14NTransform());
            reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";

            KeyInfo keyInfo = new KeyInfo();
            keyInfo.AddClause(new KeyInfoX509Data(cert));

            SignedXml sig = new SignedXml(doc);
            sig.SigningKey = key;
            sig.AddReference(reference);
            sig.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
            sig.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
            sig.KeyInfo = keyInfo;
            sig.ComputeSignature();

            XmlElement signature = sig.GetXml();

            doc.DocumentElement.InsertBefore(signature, doc.DocumentElement.ChildNodes[0]);
        }
        // *********************************************************************************
        // *********************************************************************************
        // *********************************************************************************
        public static bool ValidateXmlDocumentWithCertificate(XmlDocument doc)
        {
            try
            {
                X509Certificate2 cert = new X509Certificate2(
                    Convert.FromBase64String(
                        ((XmlElement)doc.GetElementsByTagName("Signature")[0]).GetElementsByTagName("X509Certificate")[0].InnerText
                    )
                );

                return ValidateXmlDocumentWithCertificate(doc, cert);
            }
            catch
            {
                return false;
            }
        }
        // *********************************************************************************
        // *********************************************************************************
        // *********************************************************************************
        public static bool ValidateXmlDocumentWithCertificate(XmlDocument doc, X509Certificate2 cert)
        {
            try
            {
                XmlElement signatureNode = (XmlElement)doc.GetElementsByTagName("Signature")[0];
                SignedXml signedXml = new SignedXml(doc);
                signedXml.LoadXml(signatureNode);
                return signedXml.CheckSignature(cert, true);
            }
            catch
            {
                return false;
            }
        }
        // *********************************************************************************
        // *********************************************************************************
        // *********************************************************************************
        public static string PrettyXml(XmlDocument doc)
        {
            StringBuilder stringBuilder = new StringBuilder();

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;

            using (var xmlWriter = XmlWriter.Create(stringBuilder, settings))
            {
                doc.Save(xmlWriter);
            }

            return stringBuilder.ToString();
        }
        // *********************************************************************************
        // *********************************************************************************
        // *********************************************************************************
    }
}

	


RSAPKCS1SHA256SignatureDescription.cs


// https://gist.github.com/sneal/f35de432115b840c4c1f

using System.Security.Cryptography;

namespace net.wibit
{
    public class RSAPKCS1SHA256SignatureDescription : SignatureDescription
    {
        public static void Register()
        {
            CryptoConfig.AddAlgorithm(
                typeof(RSAPKCS1SHA256SignatureDescription),
                "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
        }
        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;
        }

        public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
        {
            var asymmetricSignatureFormatter =
                (AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
            asymmetricSignatureFormatter.SetKey(key);
            asymmetricSignatureFormatter.SetHashAlgorithm("SHA256");
            return asymmetricSignatureFormatter;
        }
    }
}