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