Example #1
0
        public bool VerifyXmlFile(XmlDocument xmlDocument)
        {
            if (xmlDocument == null)
            {
                throw new ArgumentException($"{nameof(xmlDocument)} cannot be null. Please supply a valid xml document");
            }

            var signedXml           = new CustomIdSignedXml(xmlDocument);
            var nodeList            = xmlDocument.GetElementsByTagName(SignatureElementName, NS2);
            var xmlDigitalSignature = (XmlElement)nodeList[0];

            if (xmlDigitalSignature == null)
            {
                return(true);
            }

            signedXml.LoadXml(xmlDigitalSignature);

            // Check the signature and return the result.
            return(signedXml.CheckSignature());
        }
Example #2
0
        public void Hack()
        {
            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            doc.Load(@"C:\TMP\cache.xml");

            SignedXml sig = new CustomIdSignedXml(doc);
            XmlNodeList nodeList = doc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");
            foreach (XmlElement e in nodeList)
            {
                sig.LoadXml(e);
                Assert.IsTrue(sig.CheckSignature());
            }
        }
Example #3
0
    // 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;
    }
Example #4
0
    // 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);
    }
Example #5
0
        public string SignXmlFile(XmlDocument xmlDocument, X509Certificate2 certificate, string xmlSignatureSyntax)
        {
            if (xmlDocument == null)
            {
                throw new ArgumentException($"{nameof(xmlDocument)} cannot be null. Please supply a valid xml document");
            }
            if (certificate == null)
            {
                throw new ArgumentException($"{nameof(certificate)} cannot be null. Please supply a valid certificate");
            }
            if (string.IsNullOrWhiteSpace(xmlSignatureSyntax))
            {
                throw new ArgumentException($"{nameof(xmlSignatureSyntax)} cannot be null. Please supply a valid XmlSignatureSyntax");
            }

            // Load xml and set signing parameters
            var signedXml = new CustomIdSignedXml(xmlDocument);

            signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl;
            signedXml.SignedInfo.SignatureMethod        = SignatureMethod;
            signedXml.SigningKey = certificate.GetRSAPrivateKey();;

            // Set the namespases
            var nsmgr = new XmlNamespaceManager(xmlDocument.NameTable);

            nsmgr.AddNamespace("ns", xmlSignatureSyntax);
            nsmgr.AddNamespace("ns2", NS2);

            // Select message node for signing
            var reference = new Reference();

            reference.DigestMethod = DigestMethod;
            reference.Uri          = "#" + xmlDocument.SelectSingleNode($"//ns:{MessageElementName}", nsmgr)
                                     .Attributes["messageId"].Value;
            signedXml.AddReference(reference);

            // Set signing key and sign xml data
            var keyInfo = new KeyInfo();

            keyInfo.AddClause(new KeyInfoX509Data(certificate));
            signedXml.KeyInfo = keyInfo;
            signedXml.ComputeSignature();

            // Get signature
            var xmlDigitalSignature = signedXml.GetXml();

            // Assign ds prefix
            AssignNameSpacePrefixToElementTree(xmlDigitalSignature, CustomPrefix);

            //load SignedInfo and compute final signature based on correct SignedInfo
            signedXml.LoadXml(xmlDigitalSignature);
            signedXml.SignedInfo.References.Clear();
            signedXml.ComputeSignature();

            // Replace signature
            ReplaceSignature(xmlDigitalSignature, Convert.ToBase64String(signedXml.SignatureValue));

            // Append signature to the xml doc
            xmlDocument.DocumentElement.AppendChild(xmlDocument.ImportNode(xmlDigitalSignature, true));

            using var stringWriter  = new StringWriter();
            using var xmlTextWriter = new XmlTextWriter(stringWriter);
            xmlDocument.WriteTo(xmlTextWriter);
            xmlTextWriter.Flush();
            return(stringWriter.ToString());
        }