2022-07-19 22:06:57 +00:00
|
|
|
using System;
|
2022-07-18 16:57:27 +00:00
|
|
|
using System.Security.Cryptography;
|
|
|
|
using System.Security.Cryptography.X509Certificates;
|
|
|
|
using System.Security.Cryptography.Xml;
|
|
|
|
using System.Xml;
|
|
|
|
|
2022-07-19 22:06:57 +00:00
|
|
|
/**
|
|
|
|
* This program reads in the following files:
|
|
|
|
* 1. Public certificate, pem format
|
|
|
|
* 2. Corresponding private key, pem format
|
|
|
|
* 3. Unsigned xml document
|
|
|
|
* 4. Signed xml document
|
|
|
|
* The two functions are SignXml() and VerifyXml() and are called in succession.
|
|
|
|
*
|
|
|
|
* XmlDocument.PreserveWhitespace(false) allows the subsequent signed xml document
|
|
|
|
* to pass validation.
|
|
|
|
*
|
|
|
|
* VerifyXml() strictly checks the cryptographic integrity of the Signature block,
|
|
|
|
* it does not verify the integrity of the certificate chain.
|
|
|
|
*/
|
2022-07-18 16:57:27 +00:00
|
|
|
public class VerifyXML
|
|
|
|
{
|
|
|
|
|
|
|
|
public static void Main(String[] args)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
const string signingAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256";
|
|
|
|
const string signingCertName = "RimSignCert.pem";
|
|
|
|
const string privateKeyFilename = "privateRimKey.pem";
|
2022-07-19 22:06:57 +00:00
|
|
|
const string unsignedFilename = "unsigned.xml";
|
|
|
|
const string signedFilename = "signed.xml";
|
|
|
|
const string signedRIM = "signedRIM.swidtag";
|
2022-07-18 16:57:27 +00:00
|
|
|
|
|
|
|
//Load public cert from file
|
|
|
|
X509Certificate2 signingCert = new X509Certificate2(signingCertName);
|
|
|
|
RSA publicKey = signingCert.GetRSAPublicKey();
|
|
|
|
//Load private key from file
|
|
|
|
string privateKeyText = System.IO.File.ReadAllText(privateKeyFilename);
|
|
|
|
//System.Console.WriteLine("Using private key: " + privateKeyText);
|
|
|
|
var privateKey = RSA.Create();
|
|
|
|
privateKey.ImportFromPem(privateKeyText);
|
|
|
|
|
|
|
|
// Load an XML file into the XmlDocument object.
|
|
|
|
XmlDocument unsignedDoc = new XmlDocument();
|
2022-07-19 22:06:57 +00:00
|
|
|
unsignedDoc.Load(unsignedFilename);
|
2022-07-18 16:57:27 +00:00
|
|
|
SignXml(unsignedDoc, privateKey);
|
2022-07-19 22:06:57 +00:00
|
|
|
unsignedDoc.Save(signedFilename);
|
2022-07-18 16:57:27 +00:00
|
|
|
|
|
|
|
// Verify the signature of the signed XML.
|
|
|
|
XmlDocument signedDoc = new XmlDocument();
|
2022-07-19 22:06:57 +00:00
|
|
|
signedDoc.Load(signedFilename);
|
2022-07-18 16:57:27 +00:00
|
|
|
bool result = VerifyXml(signedDoc, publicKey);
|
|
|
|
|
|
|
|
// Display the results of the signature verification to
|
|
|
|
// the console.
|
|
|
|
if (result)
|
|
|
|
{
|
2022-07-19 22:06:57 +00:00
|
|
|
Console.WriteLine("The XML signature is valid!");
|
2022-07-18 16:57:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Console.WriteLine("The XML signature is not valid.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
Console.WriteLine(e.Message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private static void SignXml(XmlDocument xmlDoc, RSA rsaKey)
|
|
|
|
{
|
|
|
|
if (xmlDoc == null)
|
|
|
|
throw new ArgumentException(nameof(xmlDoc));
|
|
|
|
if (rsaKey == null)
|
|
|
|
throw new ArgumentException(nameof(rsaKey));
|
|
|
|
|
|
|
|
Console.Write("Signing xml...");
|
|
|
|
|
|
|
|
// Create a SignedXml object.
|
|
|
|
SignedXml signedXml = new SignedXml(xmlDoc);
|
|
|
|
|
|
|
|
// Add the key to the SignedXml document.
|
|
|
|
signedXml.SigningKey = rsaKey;
|
|
|
|
|
|
|
|
// Create a reference to be signed.
|
|
|
|
Reference reference = new Reference();
|
|
|
|
reference.Uri = "";
|
|
|
|
|
|
|
|
// Add an enveloped transformation to the reference.
|
|
|
|
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
|
|
|
|
reference.AddTransform(env);
|
|
|
|
|
|
|
|
// Add the reference to the SignedXml object.
|
|
|
|
signedXml.AddReference(reference);
|
|
|
|
|
2022-07-19 22:06:57 +00:00
|
|
|
// Add keyinfo block
|
|
|
|
KeyInfo keyInfo = new KeyInfo();
|
|
|
|
keyInfo.AddClause(new RSAKeyValue((RSA)rsaKey));
|
|
|
|
signedXml.KeyInfo = keyInfo;
|
|
|
|
|
2022-07-18 16:57:27 +00:00
|
|
|
// Compute the signature.
|
|
|
|
signedXml.ComputeSignature();
|
|
|
|
|
|
|
|
// Get the XML representation of the signature and save
|
|
|
|
// it to an XmlElement object.
|
|
|
|
XmlElement xmlDigitalSignature = signedXml.GetXml();
|
|
|
|
|
|
|
|
// Append the element to the XML document.
|
|
|
|
xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
|
|
|
|
Console.WriteLine("Xml signed.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the signature of an XML file against an asymmetric
|
|
|
|
// algorithm and return the result.
|
2022-07-19 22:06:57 +00:00
|
|
|
private static Boolean VerifyXml(XmlDocument xmlDoc, RSA key)
|
2022-07-18 16:57:27 +00:00
|
|
|
{
|
|
|
|
// Check arguments.
|
|
|
|
if (xmlDoc == null)
|
|
|
|
throw new ArgumentException("xmlDoc");
|
|
|
|
if (key == null)
|
|
|
|
throw new ArgumentException("key");
|
|
|
|
|
|
|
|
Console.Write("Verifying signature...");
|
|
|
|
// Create a new SignedXml object and pass it
|
|
|
|
// the XML document class.
|
|
|
|
SignedXml signedXml = new SignedXml(xmlDoc);
|
|
|
|
|
|
|
|
// Find the "Signature" node and create a new
|
|
|
|
// XmlNodeList object.
|
|
|
|
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
|
|
|
|
|
|
|
|
// Throw an exception if no signature was found.
|
|
|
|
if (nodeList.Count <= 0)
|
|
|
|
{
|
|
|
|
throw new CryptographicException("Verification failed: No Signature was found in the document.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// This example only supports one signature for
|
|
|
|
// the entire XML document. Throw an exception
|
|
|
|
// if more than one signature was found.
|
|
|
|
if (nodeList.Count >= 2)
|
|
|
|
{
|
|
|
|
throw new CryptographicException("Verification failed: More than one signature was found for the document.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load the first <signature> node.
|
|
|
|
signedXml.LoadXml((XmlElement)nodeList[0]);
|
|
|
|
Boolean isValid = false;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
isValid = signedXml.CheckSignature(key);
|
2022-07-19 22:06:57 +00:00
|
|
|
}
|
|
|
|
catch (Exception e)
|
2022-07-18 16:57:27 +00:00
|
|
|
{
|
|
|
|
Console.WriteLine(e.Message);
|
|
|
|
}
|
2022-07-19 22:06:57 +00:00
|
|
|
|
2022-07-18 16:57:27 +00:00
|
|
|
// Check the signature and return the result.
|
|
|
|
return isValid;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|