/// <summary> /// Añade una transformación XPath al contenido a firmar /// </summary> /// <param name="XPathString"></param> private void AddXPathTransform(SignatureDocument sigDocument, Dictionary <string, string> namespaces, string XPathString) { XmlDocument document; if (sigDocument.Document != null) { document = sigDocument.Document; } else { document = new XmlDocument(); } XmlElement xPathElem = document.CreateElement("XPath"); foreach (var ns in namespaces) { var attr = document.CreateAttribute("xmlns:" + ns.Key); attr.Value = ns.Value; xPathElem.Attributes.Append(attr); } xPathElem.InnerText = XPathString; XmlDsigXPathTransform transform = new XmlDsigXPathTransform(); transform.LoadInnerXml(xPathElem.SelectNodes(".")); Reference reference = sigDocument.XadesSignature.SignedInfo.References[0] as Reference; reference.AddTransform(transform); }
public void TransformFactoryCreateXPathNamespaceTest() { string testNamespace1Uri = "http://www.codeplex.com/clrsecurity/testnamespace1"; string testNamespace2Uri = "http://www.codeplex.com/clrsecurity/testnamespace2"; string xpathQuery = "ancestor-or-self::*[@_Id='testns1:signme']"; var namespaces = new Dictionary <string, string>(); namespaces["testns1"] = testNamespace1Uri; namespaces["testns2"] = testNamespace2Uri; XmlDsigXPathTransform transform = TransformFactory.CreateXPathTransform(xpathQuery, namespaces); Assert.IsNotNull(transform); // XmlDSigXPathTransform doesn't directly expose its state, so we validate that the transform is // setup correctly via its output XML. XmlElement transformXml = transform.GetXml(); XmlNodeList xpathElements = transformXml.GetElementsByTagName("XPath"); Assert.AreEqual(1, xpathElements.Count); XmlElement xpathXml = xpathElements[0] as XmlElement; Assert.AreEqual(xpathQuery, xpathXml.InnerText); Assert.AreEqual(testNamespace1Uri, xpathXml.GetNamespaceOfPrefix("testns1")); Assert.AreEqual(testNamespace2Uri, xpathXml.GetNamespaceOfPrefix("testns2")); }
public void TransformSimple() { XmlDsigXPathTransform t = new XmlDsigXPathTransform(); XmlDocument xpdoc = new XmlDocument(); string ns = "http://www.w3.org/2000/09/xmldsig#"; string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'>*|@*|namespace::*</XPath>"; // not absolute path.. so @* and namespace::* does not make sense. xpdoc.LoadXml(xpath); t.LoadInnerXml(xpdoc.ChildNodes); XmlDocument doc = new XmlDocument(); doc.LoadXml("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>"); t.LoadInput(doc); XmlNodeList nl = (XmlNodeList)t.GetOutput(); Assert.AreEqual(XmlNodeType.Document, nl [0].NodeType); Assert.AreEqual(XmlNodeType.Element, nl [1].NodeType); Assert.AreEqual("element", nl [1].LocalName); Assert.AreEqual(XmlNodeType.Element, nl [2].NodeType); Assert.AreEqual("foo", nl [2].LocalName); Assert.AreEqual(XmlNodeType.Element, nl [3].NodeType); Assert.AreEqual("bar", nl [3].LocalName); // MS.NET bug - ms.net returns ns node even when the // current node is ns node (it is like returning // attribute from attribute nodes). // Assert.AreEqual (XmlNodeType.Attribute, nl [4].NodeType); // Assert.AreEqual ("xmlns", nl [4].LocalName); }
// Resolve the specified base and relative Uri's . private static Uri ResolveUris(Uri baseUri, string relativeUri) { //<Snippet6> XmlUrlResolver xmlResolver = new XmlUrlResolver(); xmlResolver.Credentials = System.Net.CredentialCache.DefaultCredentials; XmlDsigXPathTransform xmlTransform = new XmlDsigXPathTransform(); xmlTransform.Resolver = xmlResolver; //</Snippet6> Uri absoluteUri = xmlResolver.ResolveUri(baseUri, relativeUri); if (absoluteUri != null) { Console.WriteLine( "\nResolved the base Uri and relative Uri to the following:"); Console.WriteLine(absoluteUri.ToString()); } else { Console.WriteLine( "Unable to resolve the base Uri and relative Uri"); } return(absoluteUri); }
public static Transform fromURI(string uri) { Transform t = null; switch (uri) { case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315": t = new XmlDsigC14NTransform(); break; case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments": t = new XmlDsigC14NWithCommentsTransform(); break; case "http://www.w3.org/2000/09/xmldsig#enveloped-signature": t = new XmlDsigEnvelopedSignatureTransform(); break; case "http://www.w3.org/TR/1999/REC-xpath-19991116": t = new XmlDsigXPathTransform(); break; case "http://www.w3.org/TR/1999/REC-xslt-19991116": t = new XmlDsigXsltTransform(); break; case "http://www.w3.org/2001/10/xml-exc-c14n#": t = new XmlDsigExcC14NTransform(); break; } return(t); }
// Create the XML that represents the transform. private static XmlDsigXPathTransform CreateXPathTransform(string xpath, IDictionary <string, string> namespaces) { // create the XML that represents the transform XmlDocument doc = new XmlDocument(); XmlElement xpathElem = doc.CreateElement("XPath"); xpathElem.InnerText = xpath; // Add the namespaces that should be in scope for the XPath expression if (namespaces != null) { foreach (string ns in namespaces.Keys) { XmlAttribute nsAttr = doc.CreateAttribute("xmlns", ns, "http://www.w3.org/2000/xmlns/"); nsAttr.Value = namespaces[ns]; xpathElem.Attributes.Append(nsAttr); } } // Build a transform from the inputs XmlDsigXPathTransform xpathTransform = new XmlDsigXPathTransform(); xpathTransform.LoadInnerXml(xpathElem.SelectNodes(".")); return(xpathTransform); }
public string MakeTransforms(int signatureNumber, int referenceNumber, int transformChainNumber) { SignedXml signedXml = new SignedXml(); signedXml.LoadXml((XmlElement)this._tempdocument.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")[signatureNumber]); Signature signature = signedXml.Signature; Reference reference = (Reference)signature.SignedInfo.References[referenceNumber]; Transform transform = reference.TransformChain[transformChainNumber]; string result = ""; if (transform.ToString().Equals("System.Security.Cryptography.Xml.XmlDsigXPathTransform")) { XmlNode node = null; XmlDocument doc = new XmlDocument(); XmlDsigXPathTransform xpathTransform = (XmlDsigXPathTransform)transform; XmlElement xpathElement = xpathTransform.GetXml(); string xpath = xpathElement.InnerText; XmlNamespaceManager manager = new XmlNamespaceManager(this._inputDocument.NameTable); XmlElement bodyElement = (XmlElement)this._inputDocument.GetElementsByTagName("s:Body")[0]; manager.AddNamespace("s", bodyElement.NamespaceURI); manager.AddNamespace("tns", "http://tempuri.org/"); node = this._tempdocument.SelectSingleNode(xpath, manager); StringWriter stringWriter = new StringWriter(); XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter); xmlTextWriter.Formatting = Formatting.Indented; XmlElement element = (XmlElement)node; element.Normalize(); element.WriteTo(xmlTextWriter); this.transformedElement = element; result = stringWriter.ToString(); } if (transform.ToString().Equals("System.Security.Cryptography.Xml.XmlDsigEnvelopedSignatureTransform")) { } if (transform.ToString().Equals("System.Security.Cryptography.Xml.XmlDsigExcC14NTransform")) { Stream stream; if (transformedElement != null) { stream = this._canonicalizator.CanonicalizeNode(transformedElement); StreamReader sreader = new StreamReader(stream); string canonString = sreader.ReadToEnd(); result = canonString; } else { ArrayList references = this.GetSignatureReferences(signatureNumber); XmlElement referenceElement = (XmlElement)references[referenceNumber]; stream = this._canonicalizator.CanonicalizeNode(referenceElement); StreamReader sreader = new StreamReader(stream); string canonString = sreader.ReadToEnd(); result = canonString; } } return(result); }
// Sign an XML file and save the signature in a new file. public static void SignXmlFile(string FileName, string SignedFileName, RSA Key, string XPathString) { // 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 it's name. doc.Load(new XmlTextReader(FileName)); // Create a SignedXml object. SignedXml signedXml = new SignedXml(doc); // Add the key to the SignedXml document. signedXml.SigningKey = Key; // Create a reference to be signed. Reference reference = new Reference(); reference.Uri = ""; // Create an XmlDsigXPathTransform object using // the helper method 'CreateXPathTransform' defined // later in this sample. XmlDsigXPathTransform XPathTransform = CreateXPathTransform(XPathString); // Add the transform to the reference. reference.AddTransform(XPathTransform); // Add the reference to the SignedXml object. signedXml.AddReference(reference); // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate). KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new RSAKeyValue((RSA)Key)); 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)); // Save the signed XML document to a file specified // using the passed string. XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false)); doc.WriteTo(xmltw); xmltw.Close(); }
// MS.NET looks incorrect, or something incorrect in this test code; It turned out nothing to do with function here() public void FunctionHereObsolete() { XmlDsigXPathTransform t = new XmlDsigXPathTransform(); XmlDocument xpdoc = new XmlDocument(); string ns = "http://www.w3.org/2000/09/xmldsig#"; // string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'>here()</XPath>"; string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'></XPath>"; xpdoc.LoadXml(xpath); t.LoadInnerXml(xpdoc.ChildNodes); XmlDocument doc = new XmlDocument(); doc.LoadXml("<element a='b'><foo><bar>test</bar></foo></element>"); t.LoadInput(doc); XmlNodeList nl = (XmlNodeList)t.GetOutput(); Assert.AreEqual(0, nl.Count, "0"); doc.LoadXml("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); #if NET_2_0 Assert.AreEqual(0, nl.Count, "1"); #else Assert.AreEqual(1, nl.Count, "1"); #endif doc.LoadXml("<element xmlns='urn:foo'><foo xmlns='urn:bar'><bar>test</bar></foo></element>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); #if NET_2_0 Assert.AreEqual(0, nl.Count, "2"); #else Assert.AreEqual(2, nl.Count, "2"); #endif doc.LoadXml("<element xmlns='urn:foo' xmlns:x='urn:x'><foo xmlns='urn:bar'><bar>test</bar></foo></element>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); #if NET_2_0 Assert.AreEqual(0, nl.Count, "3"); #else Assert.AreEqual(3, nl.Count, "3"); #endif doc.LoadXml("<envelope><Signature xmlns='http://www.w3.org/2000/09/xmldsig#'><XPath>blah</XPath></Signature></envelope>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); #if NET_2_0 Assert.AreEqual(0, nl.Count, "4"); #else Assert.AreEqual(1, nl.Count, "4"); Assert.AreEqual(XmlNodeType.Attribute, nl [0].NodeType, "NodeType"); #endif }
// This implementation is different from the enveloped signature transform in the XmlDSig specification - the version defined in the specification would not allow for multiple independent signatures in the same document private static Transform GetEnvelopedSignatureTransform() { XmlDocument document = new XmlDocument(); document.LoadXml("<ds:XPath xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">not(ancestor-or-self::ds:Signature)</ds:XPath>"); XmlDsigXPathTransform transform = new XmlDsigXPathTransform(); transform.LoadInnerXml(document.SelectNodes("/*")); return(transform); }
private static XmlDsigXPathTransform CreateXPathTransform(string xPathString) { var doc = new XmlDocument(); doc.LoadXml("<XPath xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"></XPath>"); var xPathElem = (XmlElement)doc.SelectSingleNode("XPath"); xPathElem.InnerText = xPathString; var xForm = new XmlDsigXPathTransform(); xForm.LoadInnerXml(xPathElem.SelectNodes(".")); return(xForm); }
public static XmlDocument Sign(XmlDocument document, X509Certificate2 certificate) { var signedXml = new SignedXml(document) { SigningKey = certificate.PrivateKey, SignedInfo = { SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" } }; var reference = new Reference { Uri = "", DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256" }; var envTransform = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(envTransform); var xpathTransform = new XmlDsigXPathTransform(); var transformBody = new XmlDocument(); transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature)</dsig:XPath>"); xpathTransform.LoadInnerXml(transformBody.SelectNodes("/*[1]")); reference.AddTransform(xpathTransform); signedXml.AddReference(reference); var keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(certificate)); signedXml.KeyInfo = keyInfo; signedXml.ComputeSignature(); var result = new XmlDocument(); result.AppendChild(result.ImportNode(document.DocumentElement, true)); var xmlSignature = signedXml.GetXml(); result.DocumentElement.AppendChild(result.ImportNode(xmlSignature, true)); return(result); }
/// <summary> /// Construye el documento enveloped /// </summary> private void CreateEnvelopedDocument() { Reference reference = new Reference(); _xadesSignedXml = new XadesSignedXml(_document); reference.DigestMethod = "http://www.w3.org/2001/10/xml-exc-c14n#"; reference.Id = "r-id-1"; reference.Type = ""; reference.Uri = ""; //for (int i = 0; i < _document.DocumentElement.Attributes.Count; i++) //{ // if (_document.DocumentElement.Attributes[i].Name.Equals("id", StringComparison.InvariantCultureIgnoreCase)) // { // reference.Uri = "#" + _document.DocumentElement.Attributes[i].Value; // break; // } //} // ** XmlDsigEnvelopedSignatureTransform xmlDsigEnvelopedSignatureTransform = new XmlDsigEnvelopedSignatureTransform(); //xmlDsigEnvelopedSignatureTransform.Algorithm = "http://www.w3.org/TR/1999/REC-xpath-19991116"; XmlDocument doc = new XmlDocument(); XmlElement xpathElem = doc.CreateElement("XPath"); xpathElem.InnerText = "not(ancestor-or-self::ds:Signature)"; XmlDsigXPathTransform xform = new XmlDsigXPathTransform(); xform.LoadInnerXml(xpathElem.SelectNodes(".")); xform.Algorithm = "http://www.w3.org/TR/1999/REC-xpath-19991116"; //xform.PropagatedNamespaces.Add("xmlns:ds", "http://www.w3.org/2000/09/xmldsig#"); reference.AddTransform(xform); XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(); reference.AddTransform(transform); //reference.AddTransform(xmlDsigEnvelopedSignatureTransform); _objectReference = reference.Id; _xadesSignedXml.AddReference(reference); }
/// <summary> /// Firma un documento XML con un certificado digital, ademas incluye el certificado en el documento /// </summary> /// <param name="xmlIn"></param> /// <param name="x509Certificate"></param> /// <returns></returns> public static XmlDocument SignXml(XmlDocument xmlIn, X509Certificate2 x509Certificate) { //var s = Environment.UserName; var xmlReturn = new XmlDocument(); xmlReturn.LoadXml(xmlIn.OuterXml); var nsmgr = new XmlNamespaceManager(xmlReturn.NameTable); nsmgr.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/"); xmlReturn.PreserveWhitespace = true; var reference = new Reference(""); var signedXml = new SignedXml( (XmlElement) xmlReturn.SelectSingleNode("soapenv:Envelope", nsmgr).SelectSingleNode("soapenv:Body", nsmgr)); var keyInfo = new KeyInfo(); // ASIGNACION DE METODOS Y UBICACIUN DE ELEMENTOS A FIRMAR XmlDsigXPathTransform xPathTransform = CreateXPathTransform("ancestor-or-self::soap:Body"); signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl; var canMethod = ((XmlDsigExcC14NTransform)(signedXml.SignedInfo.CanonicalizationMethodObject)); reference.AddTransform(xPathTransform); reference.AddTransform(new XmlDsigC14NTransform()); signedXml.AddReference(reference); keyInfo.AddClause(new KeyInfoX509Data(x509Certificate)); signedXml.KeyInfo = keyInfo; signedXml.SigningKey = x509Certificate.PrivateKey; // FIRMA signedXml.ComputeSignature(); XmlElement xmlDigitalSignature = signedXml.GetXml(); // INSERTAR FIRMA EN CABECERA xmlReturn.SelectSingleNode("soapenv:Envelope", nsmgr).SelectSingleNode("soapenv:Header", nsmgr).AppendChild( xmlReturn.ImportNode(xmlDigitalSignature, true)); return(xmlReturn); }
private void AddXPathTransform(SignatureDocument sigDocument, Dictionary <string, string> namespaces, string XPathString) { XmlDocument xmlDocument = (sigDocument.Document == null) ? new XmlDocument() : sigDocument.Document; XmlElement xmlElement = xmlDocument.CreateElement("XPath"); foreach (KeyValuePair <string, string> @namespace in namespaces) { XmlAttribute xmlAttribute = xmlDocument.CreateAttribute("xmlns:" + @namespace.Key); xmlAttribute.Value = @namespace.Value; xmlElement.Attributes.Append(xmlAttribute); } xmlElement.InnerText = XPathString; XmlDsigXPathTransform xmlDsigXPathTransform = new XmlDsigXPathTransform(); xmlDsigXPathTransform.LoadInnerXml(xmlElement.SelectNodes(".")); Reference reference = sigDocument.XadesSignature.SignedInfo.References[0] as Reference; reference.AddTransform(xmlDsigXPathTransform); }
public void TransformFactoryCreateXPathTest() { string xpathQuery = "ancestor-or-self::*[@_Id='signme']"; XmlDsigXPathTransform transform = TransformFactory.CreateXPathTransform(xpathQuery); Assert.IsNotNull(transform); // XmlDSigXPathTransform doesn't directly expose its state, so we validate that the transform is // setup correctly via its output XML. XmlElement transformXml = transform.GetXml(); XmlNodeList xpathElements = transformXml.GetElementsByTagName("XPath"); Assert.AreEqual(1, xpathElements.Count); XmlElement xpathXml = xpathElements[0] as XmlElement; Assert.AreEqual(xpathQuery, xpathXml.InnerText); }
// Create the XML that represents the transform. private static XmlDsigXPathTransform CreateXPathTransform(string XPathString) { // Create a new XMLDocument object. XmlDocument doc = new XmlDocument(); // Create a new XmlElement. XmlElement xPathElem = doc.CreateElement("XPath"); // Set the element text to the value // of the XPath string. xPathElem.InnerText = XPathString; // Create a new XmlDsigXPathTransform object. XmlDsigXPathTransform xForm = new XmlDsigXPathTransform(); // Load the XPath XML from the element. xForm.LoadInnerXml(xPathElem.SelectNodes(".")); // Return the XML that represents the transform. return(xForm); }
public void FullChain() { TransformChain chain = new TransformChain(); XmlDsigBase64Transform base64 = new XmlDsigBase64Transform(); chain.Add(base64); Assert.Equal(base64, chain[0]); Assert.Equal(1, chain.Count); XmlDsigC14NTransform c14n = new XmlDsigC14NTransform(); chain.Add(c14n); Assert.Equal(c14n, chain[1]); Assert.Equal(2, chain.Count); XmlDsigC14NWithCommentsTransform c14nc = new XmlDsigC14NWithCommentsTransform(); chain.Add(c14nc); Assert.Equal(c14nc, chain[2]); Assert.Equal(3, chain.Count); XmlDsigEnvelopedSignatureTransform esign = new XmlDsigEnvelopedSignatureTransform(); chain.Add(esign); Assert.Equal(esign, chain[3]); Assert.Equal(4, chain.Count); XmlDsigXPathTransform xpath = new XmlDsigXPathTransform(); chain.Add(xpath); Assert.Equal(xpath, chain[4]); Assert.Equal(5, chain.Count); XmlDsigXsltTransform xslt = new XmlDsigXsltTransform(); chain.Add(xslt); Assert.Equal(xslt, chain[5]); Assert.Equal(6, chain.Count); }
public static XmlDsigXPathTransform CreateXPathTransform(string xpath, IDictionary <string, string> namespaces) { if (xpath == null) { throw new ArgumentNullException("xpath"); } // XmlDsigXPath transform only sets its XPath query when it loads itself from XML. In order to // setup the transform, we'll build up XML representing the transform, and then load that XML // into the transform. XmlDocument doc = new XmlDocument(); XmlElement xpathElement = doc.CreateElement("XPath"); // The XPath query is the text value of the XPath node of the transform. xpathElement.InnerText = xpath; // Add the namespaces that should be in scope for the XPath expression. if (namespaces != null) { foreach (string namespaceAlais in namespaces.Keys) { // Namespaces in scope for the XPath query must be declared on the XPath element. For // each namespace mapping, generate a namespace declaration attribute to apply to the // XPath element. XmlAttribute namespaceDeclaration = doc.CreateAttribute("xmlns", namespaceAlais, "http://www.w3.org/2000/xmlns/"); namespaceDeclaration.Value = namespaces[namespaceAlais]; xpathElement.Attributes.Append(namespaceDeclaration); } } // Build a transform from the XML representation XmlDsigXPathTransform xpathTransform = new XmlDsigXPathTransform(); xpathTransform.LoadInnerXml(xpathElement.SelectNodes(".")); return(xpathTransform); }
public void FunctionHereObsolete() { XmlDsigXPathTransform t = new XmlDsigXPathTransform(); XmlDocument xpdoc = new XmlDocument(); string ns = "http://www.w3.org/2000/09/xmldsig#"; string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'></XPath>"; xpdoc.LoadXml(xpath); t.LoadInnerXml(xpdoc.ChildNodes); XmlDocument doc = new XmlDocument(); doc.LoadXml("<element a='b'><foo><bar>test</bar></foo></element>"); t.LoadInput(doc); XmlNodeList nl = (XmlNodeList)t.GetOutput(); Assert.Equal(0, nl.Count); doc.LoadXml("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); Assert.Equal(0, nl.Count); doc.LoadXml("<element xmlns='urn:foo'><foo xmlns='urn:bar'><bar>test</bar></foo></element>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); Assert.Equal(0, nl.Count); doc.LoadXml("<element xmlns='urn:foo' xmlns:x='urn:x'><foo xmlns='urn:bar'><bar>test</bar></foo></element>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); Assert.Equal(0, nl.Count); doc.LoadXml("<envelope><Signature xmlns='http://www.w3.org/2000/09/xmldsig#'><XPath>blah</XPath></Signature></envelope>"); t.LoadInput(doc); nl = (XmlNodeList)t.GetOutput(); Assert.Equal(0, nl.Count); }
public void TransformSimple() { XmlDsigXPathTransform t = new XmlDsigXPathTransform(); XmlDocument xpdoc = new XmlDocument(); string ns = "http://www.w3.org/2000/09/xmldsig#"; string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'>*|@*|namespace::*</XPath>"; // not absolute path.. so @* and namespace::* does not make sense. xpdoc.LoadXml(xpath); t.LoadInnerXml(xpdoc.ChildNodes); XmlDocument doc = new XmlDocument(); doc.LoadXml("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>"); t.LoadInput(doc); XmlNodeList nl = (XmlNodeList)t.GetOutput(); Assert.Equal(XmlNodeType.Document, nl[0].NodeType); Assert.Equal(XmlNodeType.Element, nl[1].NodeType); Assert.Equal("element", nl[1].LocalName); Assert.Equal(XmlNodeType.Element, nl[2].NodeType); Assert.Equal("foo", nl[2].LocalName); Assert.Equal(XmlNodeType.Element, nl[3].NodeType); Assert.Equal("bar", nl[3].LocalName); }
// Třída podepíše certifikátem dokument XML a přidá časové razítko // Pokud je již dokument podepsaný, přidá se další podpis public XmlDocument SignWithTimestamp(XmlDocument doc, X509Certificate2 cert, string tsURL, string tsUsername, string tsPassword) { // před podepisováním z dokumentu odstraníme komentáře (.NET s nimi má problémy pokud se kombinují s XPath transformacemi) XmlDocument strippedDoc = RemoveComments(doc); // definice mapování prefixů na jmenné prostory XmlNamespaceManager manager = new XmlNamespaceManager(strippedDoc.NameTable); manager.AddNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#"); // zjištění kolik podpisů již v dokumentu je int signatures = strippedDoc.SelectNodes("//dsig:Signature", manager).Count; string signatureID = (signatures + 1).ToString(); // vytvoření elementu Object pro časové razítko XmlElement objectElement = doc.CreateElement("Object", "http://www.w3.org/2000/09/xmldsig#"); // spočítání otisku certifikátu SHA256 sha256 = new SHA256Managed(); string certHash = Convert.ToBase64String(sha256.ComputeHash(cert.GetRawCertData())); objectElement.InnerXml = @"<xades:QualifyingProperties xmlns:xades='http://uri.etsi.org/01903/v1.3.2#' Target='#Signature-" + signatureID + @"' xmlns='http://www.w3.org/2000/09/xmldsig#'> <xades:SignedProperties Id='Signature-" + signatureID + @"-SignedProperties'> <xades:SignedSignatureProperties> <xades:SigningTime>" + XmlConvert.ToString(DateTime.Now.ToUniversalTime(), XmlDateTimeSerializationMode.RoundtripKind) + @"</xades:SigningTime> <xades:SigningCertificate> <xades:Cert> <xades:CertDigest> <DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'></DigestMethod> <DigestValue>" + certHash + @"</DigestValue> </xades:CertDigest> <xades:IssuerSerial> <X509IssuerName>" + cert.IssuerName + @"</X509IssuerName> <X509SerialNumber>" + cert.GetSerialNumberString() + @"</X509SerialNumber> </xades:IssuerSerial> </xades:Cert> </xades:SigningCertificate> </xades:SignedSignatureProperties> <xades:SignedDataObjectProperties> <xades:DataObjectFormat ObjectReference='#Signature-" + signatureID + @"-Document-Reference'> <xades:MimeType>application/xml</xades:MimeType> </xades:DataObjectFormat> </xades:SignedDataObjectProperties> </xades:SignedProperties> <xades:UnsignedProperties> <xades:UnsignedSignatureProperties> <xades:SignatureTimeStamp> <xades:EncapsulatedTimeStamp Encoding='http://uri.etsi.org/01903/v1.2.2#DER'></xades:EncapsulatedTimeStamp> </xades:SignatureTimeStamp> </xades:UnsignedSignatureProperties> </xades:UnsignedProperties> </xades:QualifyingProperties>"; // objekt sloužící pro vytvoření podpisu CustomIdSignedXml signedXml = new CustomIdSignedXml(strippedDoc, objectElement); // podepisovat budeme privátním klíčem z certifikátu signedXml.SigningKey = cert.PrivateKey; // podepisovat budeme pomocí RSA-SHA256 signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; // reference na podepisovaný dokument ("" znamená celý dokument) Reference reference = new Reference(); reference.Uri = ""; reference.Id = "Signature-" + signatureID + "-Document-Reference"; // pro výpočet otisku se bude používat SHA-256 reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; // digitální podpis bude přímo součástí dokumentu XML (tzv. "enveloped signature") XmlDsigEnvelopedSignatureTransform envTransform = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(envTransform); // navíc budeme používat XPath transoformaci, která dovoluje přidat několik podpisů najednou XmlDsigXPathTransform xpathTransform = new XmlDsigXPathTransform(); // příprava definice XPath transformace jako struktura XML signature XmlDocument transformBody = new XmlDocument(); // podoba XPath filtru se liší podle počtu podpisů if (signatures == 0) { transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature)</dsig:XPath>"); } else { transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature) or not(ancestor-or-self::dsig:Signature/preceding-sibling::dsig:Signature[" + signatures + "])</dsig:XPath>"); } // načtení definice XPath transformace do objektu xpathTransform.LoadInnerXml(transformBody.SelectNodes("/*[1]")); // přidání XPath transformace reference.AddTransform(xpathTransform); // přidání reference do podpisu signedXml.AddReference(reference); // reference na SignedProperties -- XAdES-BES vyžaduje podpis certifikátu Reference spReference = new Reference(); spReference.Uri = "#Signature-" + signatureID + "-SignedProperties"; // pro výpočet otisku se bude používat SHA-256 spReference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; // přidání reference do podpisu signedXml.AddReference(spReference); // přidání certifikátu do podpisu KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(cert)); signedXml.KeyInfo = keyInfo; // přidání objektu s časovým razítkem do podpisu DataObject dataObj = new DataObject(); dataObj.LoadXml(objectElement); signedXml.AddObject(dataObj); // výpočet podpisu signedXml.ComputeSignature(); // získání XML reprezentace podpisu XmlElement xmlSignature = signedXml.GetXml(); // k podpisu přidáme identifikátor, tak jak doporučuje standard ISDOC xmlSignature.SetAttribute("Id", "Signature-" + signatureID); // XML dokument pro podepsaný výsledek XmlDocument result = new XmlDocument(); // bílé znaky musíme zachovat, jinak se špatně spočte hash result.PreserveWhitespace = true; // načtení původního dokumentu result.AppendChild(result.ImportNode(strippedDoc.DocumentElement, true)); // připojení podpisu na konec dokumentu XML result.DocumentElement.AppendChild(result.ImportNode(xmlSignature, true)); // Spočítání otisku digitálního podpisu byte[] digest; digest = sha256.ComputeHash(signedXml.SignatureValue); // generátor požadavků na časové razítko TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); // vytvoření dat pro požadavek na timestamp server TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha256, digest); // získání surových dat pro poslání na timestamp server byte[] reqData = request.GetEncoded(); // inicializace požadavku na timestamp server HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(tsURL); httpReq.Method = "POST"; httpReq.ContentType = "application/timestamp-query"; httpReq.ContentLength = reqData.Length; httpReq.Credentials = new NetworkCredential(tsUsername, tsPassword); // odeslání požadavku na timestamp server Stream reqStream = httpReq.GetRequestStream(); reqStream.Write(reqData, 0, reqData.Length); reqStream.Close(); // přečtení odpovědi HttpWebResponse httpResp = (HttpWebResponse)httpReq.GetResponse(); Stream respStream = new BufferedStream(httpResp.GetResponseStream()); TimeStampResponse response = new TimeStampResponse(respStream); respStream.Close(); // Console.WriteLine("Status razítkování: " + response.Status); // Console.WriteLine("Čas razítka: " + response.TimeStampToken.TimeStampInfo.GenTime.ToLocalTime()); string timestamp = Convert.ToBase64String(response.GetEncoded()); // doplnění získaného časového razítka do dokumentu XmlNamespaceManager nsmng = new XmlNamespaceManager(result.NameTable); nsmng.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); nsmng.AddNamespace("xades", "http://uri.etsi.org/01903/v1.3.2#"); XmlElement etsElement = (XmlElement)result.SelectSingleNode("//*[@Id = 'Signature-" + signatureID + "']/ds:Object/xades:QualifyingProperties/xades:UnsignedProperties/xades:UnsignedSignatureProperties/xades:SignatureTimeStamp/xades:EncapsulatedTimeStamp", nsmng); etsElement.InnerText = timestamp; return(result); }
// Třída podepíše certifikátem dokument XML // Pokud je již dokument podepsaný, přidá se další podpis public XmlDocument Sign(XmlDocument doc, X509Certificate2 cert) { // před podepisováním z dokumentu odstraníme komentáře (.NET s nimi má problémy pokud se kombinují s XPath transformacemi) XmlDocument strippedDoc = RemoveComments(doc); // definice mapování prefixů na jmenné prostory XmlNamespaceManager manager = new XmlNamespaceManager(strippedDoc.NameTable); manager.AddNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#"); // zjištění kolik podpisů již v dokumentu je int signatures = strippedDoc.SelectNodes("//dsig:Signature", manager).Count; // objekt sloužící pro vytvoření podpisu SignedXml signedXml = new SignedXml(strippedDoc); // podepisovat budeme privátním klíčem z certifikátu signedXml.SigningKey = cert.PrivateKey; // podepisovat budeme pomocí RSA-SHA256 signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; // reference na podepisovaný dokument ("" znamená celý dokument) Reference reference = new Reference(); reference.Uri = ""; // pro výpočet otisku se bude používat SHA-256 reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; // digitální podpis bude přímo součástí dokumentu XML (tzv. "enveloped signature") XmlDsigEnvelopedSignatureTransform envTransform = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(envTransform); // navíc budeme používat XPath transoformaci, která dovoluje přidat několik podpisů najednou XmlDsigXPathTransform xpathTransform = new XmlDsigXPathTransform(); // příprava definice XPath transformace jako struktura XML signature XmlDocument transformBody = new XmlDocument(); // podoba XPath filtru se liší podle počtu podpisů if (signatures == 0) transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature)</dsig:XPath>"); else transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature) or not(ancestor-or-self::dsig:Signature/preceding-sibling::dsig:Signature[" + signatures + "])</dsig:XPath>"); // načtení definice XPath transformace do objektu xpathTransform.LoadInnerXml(transformBody.SelectNodes("/*[1]")); // přidání XPath transformace reference.AddTransform(xpathTransform); // přidání reference do podpisu signedXml.AddReference(reference); // přidání certifikátu do podpisu KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(cert)); signedXml.KeyInfo = keyInfo; // výpočet podpisu signedXml.ComputeSignature(); // získání XML reprezentace podpisu XmlElement xmlSignature = signedXml.GetXml(); // k podpisu přidáme identifikátor, tak jak doporučuje standard ISDOC xmlSignature.SetAttribute("Id", "Signature-" + (signatures + 1)); // XML dokument pro podepsaný výsledek XmlDocument result = new XmlDocument(); // bílé znaky musíme zachovat, jinak se špatně spočte hash result.PreserveWhitespace = true; // načtení původního dokumentu result.AppendChild(result.ImportNode(strippedDoc.DocumentElement, true)); // připojení podpisu na konec dokumentu XML result.DocumentElement.AppendChild(result.ImportNode(xmlSignature, true)); return result; }
// Třída podepíše certifikátem dokument XML a přidá časové razítko // Pokud je již dokument podepsaný, přidá se další podpis public XmlDocument SignWithTimestamp(XmlDocument doc, X509Certificate2 cert, string tsURL, string tsUsername, string tsPassword) { // před podepisováním z dokumentu odstraníme komentáře (.NET s nimi má problémy pokud se kombinují s XPath transformacemi) XmlDocument strippedDoc = RemoveComments(doc); // definice mapování prefixů na jmenné prostory XmlNamespaceManager manager = new XmlNamespaceManager(strippedDoc.NameTable); manager.AddNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#"); // zjištění kolik podpisů již v dokumentu je int signatures = strippedDoc.SelectNodes("//dsig:Signature", manager).Count; string signatureID = (signatures + 1).ToString(); // vytvoření elementu Object pro časové razítko XmlElement objectElement = doc.CreateElement("Object", "http://www.w3.org/2000/09/xmldsig#"); // spočítání otisku certifikátu SHA256 sha256 = new SHA256Managed(); string certHash = Convert.ToBase64String(sha256.ComputeHash(cert.GetRawCertData())); objectElement.InnerXml = @"<xades:QualifyingProperties xmlns:xades='http://uri.etsi.org/01903/v1.3.2#' Target='#Signature-" + signatureID + @"' xmlns='http://www.w3.org/2000/09/xmldsig#'> <xades:SignedProperties Id='Signature-" + signatureID + @"-SignedProperties'> <xades:SignedSignatureProperties> <xades:SigningTime>" + XmlConvert.ToString(DateTime.Now.ToUniversalTime(), XmlDateTimeSerializationMode.RoundtripKind) + @"</xades:SigningTime> <xades:SigningCertificate> <xades:Cert> <xades:CertDigest> <DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'></DigestMethod> <DigestValue>" + certHash + @"</DigestValue> </xades:CertDigest> <xades:IssuerSerial> <X509IssuerName>" + cert.IssuerName + @"</X509IssuerName> <X509SerialNumber>" + cert.GetSerialNumberString() + @"</X509SerialNumber> </xades:IssuerSerial> </xades:Cert> </xades:SigningCertificate> </xades:SignedSignatureProperties> <xades:SignedDataObjectProperties> <xades:DataObjectFormat ObjectReference='#Signature-" + signatureID + @"-Document-Reference'> <xades:MimeType>application/xml</xades:MimeType> </xades:DataObjectFormat> </xades:SignedDataObjectProperties> </xades:SignedProperties> <xades:UnsignedProperties> <xades:UnsignedSignatureProperties> <xades:SignatureTimeStamp> <xades:EncapsulatedTimeStamp Encoding='http://uri.etsi.org/01903/v1.2.2#DER'></xades:EncapsulatedTimeStamp> </xades:SignatureTimeStamp> </xades:UnsignedSignatureProperties> </xades:UnsignedProperties> </xades:QualifyingProperties>"; // objekt sloužící pro vytvoření podpisu CustomIdSignedXml signedXml = new CustomIdSignedXml(strippedDoc, objectElement); // podepisovat budeme privátním klíčem z certifikátu signedXml.SigningKey = cert.PrivateKey; // podepisovat budeme pomocí RSA-SHA256 signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; // reference na podepisovaný dokument ("" znamená celý dokument) Reference reference = new Reference(); reference.Uri = ""; reference.Id = "Signature-" + signatureID + "-Document-Reference"; // pro výpočet otisku se bude používat SHA-256 reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; // digitální podpis bude přímo součástí dokumentu XML (tzv. "enveloped signature") XmlDsigEnvelopedSignatureTransform envTransform = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(envTransform); // navíc budeme používat XPath transoformaci, která dovoluje přidat několik podpisů najednou XmlDsigXPathTransform xpathTransform = new XmlDsigXPathTransform(); // příprava definice XPath transformace jako struktura XML signature XmlDocument transformBody = new XmlDocument(); // podoba XPath filtru se liší podle počtu podpisů if (signatures == 0) transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature)</dsig:XPath>"); else transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature) or not(ancestor-or-self::dsig:Signature/preceding-sibling::dsig:Signature[" + signatures + "])</dsig:XPath>"); // načtení definice XPath transformace do objektu xpathTransform.LoadInnerXml(transformBody.SelectNodes("/*[1]")); // přidání XPath transformace reference.AddTransform(xpathTransform); // přidání reference do podpisu signedXml.AddReference(reference); // reference na SignedProperties -- XAdES-BES vyžaduje podpis certifikátu Reference spReference = new Reference(); spReference.Uri = "#Signature-" + signatureID + "-SignedProperties"; // pro výpočet otisku se bude používat SHA-256 spReference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; // přidání reference do podpisu signedXml.AddReference(spReference); // přidání certifikátu do podpisu KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(cert)); signedXml.KeyInfo = keyInfo; // přidání objektu s časovým razítkem do podpisu DataObject dataObj = new DataObject(); dataObj.LoadXml(objectElement); signedXml.AddObject(dataObj); // výpočet podpisu signedXml.ComputeSignature(); // získání XML reprezentace podpisu XmlElement xmlSignature = signedXml.GetXml(); // k podpisu přidáme identifikátor, tak jak doporučuje standard ISDOC xmlSignature.SetAttribute("Id", "Signature-" + signatureID); // XML dokument pro podepsaný výsledek XmlDocument result = new XmlDocument(); // bílé znaky musíme zachovat, jinak se špatně spočte hash result.PreserveWhitespace = true; // načtení původního dokumentu result.AppendChild(result.ImportNode(strippedDoc.DocumentElement, true)); // připojení podpisu na konec dokumentu XML result.DocumentElement.AppendChild(result.ImportNode(xmlSignature, true)); // Spočítání otisku digitálního podpisu byte[] digest; digest = sha256.ComputeHash(signedXml.SignatureValue); // generátor požadavků na časové razítko TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); // vytvoření dat pro požadavek na timestamp server TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha256, digest); // získání surových dat pro poslání na timestamp server byte[] reqData = request.GetEncoded(); // inicializace požadavku na timestamp server HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(tsURL); httpReq.Method = "POST"; httpReq.ContentType = "application/timestamp-query"; httpReq.ContentLength = reqData.Length; httpReq.Credentials = new NetworkCredential(tsUsername, tsPassword); // odeslání požadavku na timestamp server Stream reqStream = httpReq.GetRequestStream(); reqStream.Write(reqData, 0, reqData.Length); reqStream.Close(); // přečtení odpovědi HttpWebResponse httpResp = (HttpWebResponse)httpReq.GetResponse(); Stream respStream = new BufferedStream(httpResp.GetResponseStream()); TimeStampResponse response = new TimeStampResponse(respStream); respStream.Close(); // Console.WriteLine("Status razítkování: " + response.Status); // Console.WriteLine("Čas razítka: " + response.TimeStampToken.TimeStampInfo.GenTime.ToLocalTime()); string timestamp = Convert.ToBase64String(response.GetEncoded()); // doplnění získaného časového razítka do dokumentu XmlNamespaceManager nsmng = new XmlNamespaceManager(result.NameTable); nsmng.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); nsmng.AddNamespace("xades", "http://uri.etsi.org/01903/v1.3.2#"); XmlElement etsElement = (XmlElement)result.SelectSingleNode("//*[@Id = 'Signature-" + signatureID +"']/ds:Object/xades:QualifyingProperties/xades:UnsignedProperties/xades:UnsignedSignatureProperties/xades:SignatureTimeStamp/xades:EncapsulatedTimeStamp", nsmng); etsElement.InnerText = timestamp; return result; }
private string Sign(XmlDocument xmlInput, PrivateKeyManager key, CertificateX509 certificate, string dSigType, string canonicalizationType, string keyInfoType, string xpath, string id) { bool flag = inicializeInstanceVariables(key, certificate); if (!flag) { return(""); } SignatureElementType signatureElementType; if (!SecurityUtils.compareStrings(xpath, "")) { if (xpath[0] == '#') { signatureElementType = SignatureElementType.id; if (id == null || SecurityUtils.compareStrings(id, "")) { this.error.setError("DS021", "identifier attribute name missing"); return(""); } } else { signatureElementType = SignatureElementType.path; } } else { signatureElementType = SignatureElementType.document; } /***WHITESPACES***/ xmlInput.PreserveWhitespace = true; CanonicalizerWrapper canon = CanonicalizerWrapperUtils.getCanonicalizerWrapper(canonicalizationType, this.error); CanonicalizerWrapper canonW = CanonicalizerWrapperUtils.getCanonicalizerWrapper(canonicalizationType, this.error); if (this.HasError()) { return(""); } Reference reference = new Reference(); XmlNode parentNode; SignedXml signedXml; switch (signatureElementType) { case SignatureElementType.path: XmlNode pathNode = SignatureUtils.getNodeFromPath(xmlInput, xpath, this.error); XmlElement pathElement = pathNode as XmlElement; if (this.HasError() || pathElement == null) { return(""); } parentNode = pathNode.ParentNode; signedXml = new SignedXml(pathElement); XmlDsigXPathTransform XPathTransform = CreateXPathTransform(xpath); reference.Uri = pathNode.NamespaceURI; reference.AddTransform(XPathTransform); break; case SignatureElementType.id: XmlNode idNode = SignatureUtils.getNodeFromID(xmlInput, id, xpath, this.error); XmlElement idElement = idNode as XmlElement; if (this.HasError() || idElement == null) { return(""); } reference.Uri = xpath; signedXml = new SignedXml(idElement); parentNode = idNode.ParentNode; break; default: signedXml = new SignedXml(xmlInput); parentNode = xmlInput.DocumentElement; reference.Uri = ""; break; } signedXml.SigningKey = this.privateKey; signedXml.SignedInfo.CanonicalizationMethod = CanonicalizerWrapperUtils.getCanonicalizationMethodAlorithm(canonW, this.error); if (this.HasError()) { return(""); } XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env); addCanonTransform(reference, canonW); signedXml.AddReference(reference); KeyInfo keyInfo = createKeyInfo(certificate, keyInfoType); if (keyInfo != null) { signedXml.KeyInfo = keyInfo; } try { signedXml.ComputeSignature(); } catch (Exception) { this.error.setError("DS023", "Error on signing"); return(""); } XmlElement xmlDigitalSignature = null; try { xmlDigitalSignature = signedXml.GetXml(); } catch (Exception) { this.error.setError("DS028", "Error at signing"); return(""); } parentNode.AppendChild(xmlDigitalSignature); // xmlInput.DocumentElement.AppendChild(xmlInput.ImportNode(xmlDigitalSignature, true)); return(SignatureUtils.XMLDocumentToString(xmlInput, this.error)); }
// Encrypt the text in the specified XmlDocument. private static void ShowTransformProperties(XmlDocument xmlDoc) { //<Snippet1> // Create a new XMLDocument object. XmlDocument doc = new XmlDocument(); // Create a new XmlElement. XmlElement xPathElem = doc.CreateElement("XPath"); // Set the element text to the value // of the XPath string. xPathElem.InnerText = "ancestor-or-self::PRODUCTS"; // Create a new XmlDsigXPathTransform object. XmlDsigXPathTransform xmlTransform = new XmlDsigXPathTransform(); // Load the XPath XML from the element. xmlTransform.LoadInnerXml(xPathElem.SelectNodes(".")); //</Snippet1> // Ensure the transform is using the proper algorithm. //<Snippet3> xmlTransform.Algorithm = SignedXml.XmlDsigXPathTransformUrl; //</Snippet3> // Retrieve the XML representation of the current transform. //<Snippet9> XmlElement xmlInTransform = xmlTransform.GetXml(); //</Snippet9> Console.WriteLine("\nXml representation of the current transform: "); Console.WriteLine(xmlInTransform.OuterXml); // Retrieve the valid input types for the current transform. //<Snippet4> Type[] validInTypes = xmlTransform.InputTypes; //</Snippet4> // Verify the xmlTransform can accept the XMLDocument as an // input type. for (int i = 0; i < validInTypes.Length; i++) { if (validInTypes[i] == xmlDoc.GetType()) { // Load the document into the transfrom. //<Snippet11> xmlTransform.LoadInput(xmlDoc); //</Snippet11> try { // This transform is created for demonstration purposes. XmlDsigXPathTransform secondTransform = new XmlDsigXPathTransform(); //<Snippet12> string classDescription = secondTransform.ToString(); //</Snippet12> //<Snippet10> xmlTransform.LoadInnerXml(xPathElem.SelectNodes("."));; //</Snippet10> } catch (CryptographicException) { Console.WriteLine("Caught exception while trying to " + "load the specified Xml document. The document " + "requires an XPath element to be valid."); } break; } } //<Snippet5> Type[] validOutTypes = xmlTransform.OutputTypes; //</Snippet5> for (int i = validOutTypes.Length - 1; i >= 0; i--) { if (validOutTypes[i] == typeof(System.Xml.XmlDocument)) { try { //<Snippet7> Type xmlDocumentType = typeof(System.Xml.XmlDocument); XmlDocument xmlDocumentOutput = (XmlDocument) xmlTransform.GetOutput(xmlDocumentType); //</Snippet7> // Display to the console the Xml before and after // encryption. Console.WriteLine("Result of the GetOutput method call" + " from the current transform: " + xmlDocumentOutput.OuterXml); } catch (Exception ex) { Console.WriteLine("Unexpected exception caught: " + ex.ToString()); } break; } else if (validOutTypes[i] == typeof(System.Xml.XmlNodeList)) { try { Type xmlNodeListType = typeof(System.Xml.XmlNodeList); XmlNodeList xmlNodes = (XmlNodeList) xmlTransform.GetOutput(xmlNodeListType); // Display to the console the Xml before and after // encryption. Console.WriteLine("Encoding the following message: " + xmlDoc.InnerText); Console.WriteLine("Nodes of the XmlNodeList retrieved " + "from GetOutput:"); for (int j = 0; j < xmlNodes.Count; j++) { Console.WriteLine("Node " + j + " has the following name: " + xmlNodes.Item(j).Name + " and the following InnerXml: " + xmlNodes.Item(j).InnerXml); } } catch (Exception ex) { Console.WriteLine("Unexpected exception caught: " + ex.ToString()); } break; } else { //<Snippet8> object outputObject = xmlTransform.GetOutput(); //</Snippet8> } } }
// Třída podepíše certifikátem dokument XML // Pokud je již dokument podepsaný, přidá se další podpis public XmlDocument Sign(XmlDocument doc, X509Certificate2 cert) { // před podepisováním z dokumentu odstraníme komentáře (.NET s nimi má problémy pokud se kombinují s XPath transformacemi) XmlDocument strippedDoc = RemoveComments(doc); // definice mapování prefixů na jmenné prostory XmlNamespaceManager manager = new XmlNamespaceManager(strippedDoc.NameTable); manager.AddNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#"); // zjištění kolik podpisů již v dokumentu je int signatures = strippedDoc.SelectNodes("//dsig:Signature", manager).Count; // objekt sloužící pro vytvoření podpisu SignedXml signedXml = new SignedXml(strippedDoc); // podepisovat budeme privátním klíčem z certifikátu signedXml.SigningKey = cert.PrivateKey; // podepisovat budeme pomocí RSA-SHA256 signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; // reference na podepisovaný dokument ("" znamená celý dokument) Reference reference = new Reference(); reference.Uri = ""; // pro výpočet otisku se bude používat SHA-256 reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"; // digitální podpis bude přímo součástí dokumentu XML (tzv. "enveloped signature") XmlDsigEnvelopedSignatureTransform envTransform = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(envTransform); // navíc budeme používat XPath transoformaci, která dovoluje přidat několik podpisů najednou XmlDsigXPathTransform xpathTransform = new XmlDsigXPathTransform(); // příprava definice XPath transformace jako struktura XML signature XmlDocument transformBody = new XmlDocument(); // podoba XPath filtru se liší podle počtu podpisů if (signatures == 0) { transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature)</dsig:XPath>"); } else { transformBody.LoadXml("<dsig:XPath xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'>not(ancestor-or-self::dsig:Signature) or not(ancestor-or-self::dsig:Signature/preceding-sibling::dsig:Signature[" + signatures + "])</dsig:XPath>"); } // načtení definice XPath transformace do objektu xpathTransform.LoadInnerXml(transformBody.SelectNodes("/*[1]")); // přidání XPath transformace reference.AddTransform(xpathTransform); // přidání reference do podpisu signedXml.AddReference(reference); // přidání certifikátu do podpisu KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(cert)); signedXml.KeyInfo = keyInfo; // výpočet podpisu signedXml.ComputeSignature(); // získání XML reprezentace podpisu XmlElement xmlSignature = signedXml.GetXml(); // k podpisu přidáme identifikátor, tak jak doporučuje standard ISDOC xmlSignature.SetAttribute("Id", "Signature-" + (signatures + 1)); // XML dokument pro podepsaný výsledek XmlDocument result = new XmlDocument(); // bílé znaky musíme zachovat, jinak se špatně spočte hash result.PreserveWhitespace = true; // načtení původního dokumentu result.AppendChild(result.ImportNode(strippedDoc.DocumentElement, true)); // připojení podpisu na konec dokumentu XML result.DocumentElement.AppendChild(result.ImportNode(xmlSignature, true)); return(result); }
public XmlElement ApplyTransform(Reference reference) { XmlNode node = null; TransformChain transformChain = reference.TransformChain; int transCounter = transformChain.Count; IEnumerator enumerator = transformChain.GetEnumerator(); Stream transformstream = new MemoryStream(); if (reference.Uri.Equals("")) { this._inputDocument.Save(transformstream); transformstream.Position = 0; } else { XmlNodeReader reader = new XmlNodeReader((XmlNode)this._reference); XmlWriter writer = new XmlTextWriter(transformstream, Encoding.UTF8); writer.WriteNode(reader, false); writer.Flush(); transformstream.Position = 0; } for (int i = 0; i < transCounter; i++) { enumerator.MoveNext(); Transform trans = (Transform)enumerator.Current; string typ = trans.ToString(); switch (typ) { case "System.Security.Cryptography.Xml.XmlDsigEnvelopedSignatureTransform": if (!reference.Uri.Equals("")) { for (int j = 0; j < _referenceList.Count; j++) { XmlElement temp = (XmlElement)this._referenceList[j]; string uri = "#" + temp.Attributes["Id"].Value; if (uri.Equals(reference.Uri)) { node = temp; } } XmlNode signatureNode = (node as XmlElement).GetElementsByTagName("ds:Signature") != null ? (node as XmlElement).GetElementsByTagName("ds:Signature")[0] as XmlNode : null; if (signatureNode != null) { node.RemoveChild(signatureNode); } } break; case "System.Security.Cryptography.Xml.XmlDsigExcC14NTransform": if (!reference.Uri.Equals("")) { for (int j = 0; j < _referenceList.Count; j++) { XmlElement temp = (XmlElement)this._referenceList[j]; string uri = "#" + temp.Attributes["Id"].Value; if (uri.Equals(reference.Uri)) { node = temp; } } } break; case SignedXml.XmlDsigEnvelopedSignatureTransformUrl: { } break; case "System.Security.Cryptography.Xml.XmlDsigXPathTransform": XmlDocument doc = new XmlDocument(); XmlDsigXPathTransform xpathTransform = (XmlDsigXPathTransform)trans; XmlElement xpathElement = xpathTransform.GetXml(); string xpath = xpathElement.InnerText; XmlNamespaceManager xmlNameSpaceManager = new XmlNamespaceManager(this._inputDocument.NameTable); XmlElement bodyElement = (XmlElement)this._inputDocument.GetElementsByTagName("s:Body")[0]; xmlNameSpaceManager.AddNamespace("s", bodyElement.NamespaceURI); xmlNameSpaceManager.AddNamespace("tns", "http://tempuri.org/"); xmlNameSpaceManager.AddNamespace("xenc", "http://www.w3.org/2001/04/xmlenc#"); xmlNameSpaceManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis -200401-wss-wssecurity-secext-1.0.xsd"); node = this._inputDocument.SelectSingleNode(xpath, xmlNameSpaceManager); break; } } return((XmlElement)node); }
public bool ValidateReferences(SignedXml signedXml) { byte[] digest; ArrayList references = signedXml.SignedInfo.References; int singatureReferenceCounter = 1; foreach (Reference reference in references) { string uri = reference.Uri; string hashAlgorithm = reference.DigestMethod; if (!uri.Equals("")) { this._referenceList.Clear(); SignatureReference sigReference = new SignatureReference(); sigReference.nr = singatureReferenceCounter; singatureReferenceCounter++; sigReference.references = new ArrayList(); ArrayList newList = new ArrayList(); newList = this.FindXmlElementByURI(uri, this._inputDocument.ChildNodes[0].NextSibling); XmlElement referenceElement = (XmlElement)newList[0]; XmlElement clonedReferenceElement = (XmlElement)referenceElement.Clone(); newList = (ArrayList)this._referenceList.Clone(); sigReference.references.Add(clonedReferenceElement); this._signatureReferenceList.Add(sigReference); } if (uri.Equals("")) { XmlNode node = null; SignatureReference sigReference = new SignatureReference(); sigReference.nr = singatureReferenceCounter; singatureReferenceCounter++; ArrayList list = new ArrayList(); XmlDocument doc = new XmlDocument(); Transform trans = reference.TransformChain[0]; XmlDsigXPathTransform xpathTransform = (XmlDsigXPathTransform)trans; XmlElement xpathElement = xpathTransform.GetXml(); string xpath = xpathElement.InnerText; XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(this._inputDocument.NameTable); XmlElement bodyElement = (XmlElement)this._inputDocument.GetElementsByTagName("s:Body")[0]; xmlNamespaceManager.AddNamespace("s", bodyElement.NamespaceURI); xmlNamespaceManager.AddNamespace("tns", "http://tempuri.org/"); xmlNamespaceManager.AddNamespace("xenc", "http://www.w3.org/2001/04/xmlenc#"); xmlNamespaceManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis -200401-wss-wssecurity-secext-1.0.xsd"); node = this._inputDocument.SelectSingleNode(xpath, xmlNamespaceManager); list.Add((XmlElement)node.Clone()); sigReference.references = list; this._signatureReferenceList.Add(sigReference); } XmlElement referenceTransformed = this.ApplyTransform(reference); digest = this.DigestElement(referenceTransformed, hashAlgorithm, ""); string digestValue = Convert.ToBase64String(digest); this._tracer.appendReferenceValidation(uri, digestValue); string convertedDigest = Convert.ToBase64String(reference.DigestValue); if (convertedDigest.Equals(digestValue)) { return(true); } else { return(false); } } return(false); }