Groups | Blog | Home
all groups > dotnet xml > may 2004 >

dotnet xml : XML Digital Signatures



John Campbell
5/4/2004 7:46:03 AM
Hi everyone
I've been doing my best to understand the specifics of implimentating XML Digital Signatures, but I seem to be missing a fundamental concept.
Let me start with a description of the problem I am trying to solve. In my application, people send an XML file that contains data for loans. The application then takes that data and performs various calculations returning the results in an XML file that combines both the initial data and the calculated data. The problem here is that the people who recieve this XML then want to send this to another group for the purpose of selling the loan. This third group needs to have confidence that the results of the analysis or any of the initial data was not changed prior to the purchase. This is where Digital Signatures come in. What I want to do is have a web service where the third party can send the XML that they received and validate that it has not been modified

Now to explain my confusion. In my research I have figured out that .NET contains some pretty awesome tools for making a Digital Signature by taking a hash of the data and combining it with a public and private key. In my scenario I would append the public key in the signature and the private key would be used by my validating web service. The trouble is, I can't for the life of me figure out how I set my private key.

I've been using the following code courtesy of <a href="http://www.informit.com/bookstore/product.asp?isbn=013100851X&redir=1">.NET Security and Cryptography</a

public void PerformXmlSignature(String originalFilename, String signedFilename

//load the XML documen
XmlDocument xmlDoc = new XmlDocument()
xmlDoc.PreserveWhitespace = true
xmlDoc.Load(originalFilename)

//create signature wrapper with default RSA ke
RSA key = RSA.Create()
SignedXml signedXml = new SignedXml()
signedXml.SigningKey = key

//create data object to hold the data to be signe
DataObject dataObject = new DataObject()
dataObject.Data = xmlDoc.ChildNodes

//set data object id for URI ref from elsewher
dataObject.Id = "MyDataObjectID"

//add data object to be signed to signature wrappe
signedXml.AddObject(dataObject)

//create reference object to ref data objec
Reference reference = new Reference()
reference.Uri = "#MyDataObjectID"

//add reference object to signature wrappe
signedXml.AddReference(reference)

//add key information to signature wrappe
KeyInfo keyInfo = new KeyInfo()
keyInfo.AddClause(new RSAKeyValue(key))
signedXml.KeyInfo = keyInfo

//generate the XML signatur
signedXml.ComputeSignature()

//apply XML signature to XML documen
XmlElement xmlSignature = signedXml.GetXml()
xmlDoc = new XmlDocument()
xmlDoc.PreserveWhitespace = true
XmlNode xmlNode = xmlDoc.ImportNode(xmlSignature, true)
xmlDoc.AppendChild(xmlNode)
xmlDoc.Save(signedFilename)

//let the user know what happene
Console.WriteLine("Signed XML document written to\n\t:" + signedFilename)


public void VerifyXmlSignature(String signedFilename

//load signed XML documen
XmlDocument xmlDoc = new XmlDocument()
xmlDoc.PreserveWhitespace = true
xmlDoc.Load(signedFilename)

//create signature wrapper from signed XML fil
SignedXml signedXml = new SignedXml(xmlDoc)

//get <Signature> node (assume only one exists
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")
signedXml.LoadXml((XmlElement)nodeList[0])

//let the user know what happene
if (signedXml.CheckSignature()
Console.WriteLine(signedFilename + " signature is VALID")
els
Console.WriteLine(signedFilename + " signature is NOT VALID")


pak
5/4/2004 11:36:01 PM
Hi John

Not sure if I understood correctly. Private key must not be in the digital signature. The problem you have is that you are creating the private key for each signing process, instead try to use one of the private keys that you store, and then you can use public key to verify the signature (remember that checking is signature is valid, is not enough to say if signature is trusted)

The best way to import private key is PKCS12 (pfx) and then I suggest use of Microsoft.Web.Services.Security.X509 from WSE.

private X509Certificate myCert = null
private X509CertificateStore certStore = null

certStore = X509CertificateStore.CurrentUserStore(X509CertificateStore.MyStore)
certStore.Open()
X509CertificateCollection certCollection=certStore.FindCertificateBySubjectName(comboBox_MyCerts.Text)

signedXml.SigningKey = myCert.Key;


AddThis Social Bookmark Button