I am trying to write a function to sign an XML file using SHA256. The resulting file has the correct digest value. Everything else seems to be correct as well, except for the Signature Value. My function is below. I believe I'm currently signing the entire file. I only need to sign a portion of the file (everything inside of ). How do I specify only a portion of the XML to sign?
public static void SignXmlFile(string FileName, string SignedFileName)
{
//Load the *.p12 file into the certificate
X509Certificate2 cert = new X509Certificate2(@"C:\...\filename.p12", "password");
//Create a new XML Document
XmlDocument doc = new XmlDocument();
//Format the document to ignore white spaces
doc.PreserveWhitespace = false;
//Load the passed XML file using the file name
doc.Load(new XmlTextReader(FileName));
//adding algorithm for 256. Will change the actual values below.
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
//Create a signed XML object
SignedXml signedXml = new SignedXml(doc);
//Add the key to the Signed XML document
signedXml.SigningKey = cert.PrivateKey;
//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);
//Set the Signature, Canonicalization, and Digets Methods
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
//Add the new reference to the signedXml
signedXml.SignedInfo.AddReference(reference);
//Create a new KeyInfo object
KeyInfo keyInfo = new KeyInfo();
//Add subject name and key to the keyInfo to sign
KeyInfoX509Data keyData = new KeyInfoX509Data(cert);
keyData.AddSubjectName(cert.SubjectName.Name);
keyInfo.AddClause(keyData);
//Add the KeyInfo object to the signed XML object
signedXml.KeyInfo = keyInfo;
//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
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
//Save the signed XML document to the specified file
using (XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false)))
{
doc.WriteTo(xmltw);
xmltw.Close();
}
}