EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Trying to sign a document with xades

Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.
#32623
Posted: 03/13/2015 17:25:22
by Gaetano Lazzo (Basic support level)
Joined: 12/02/2014
Posts: 14

I'm trying to get a document like this one:
Code
<?xml version="1.0" encoding="UTF-8"?>
<ns3:NotificaScarto xmlns:ns3="http://www.fatturapa.gov.it/sdi/messaggi/v1.0" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" versione="1.0">
  ..

  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature1">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
      <ds:Reference Id="reference-document" URI="">
        <ds:Transforms>
          <ds:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
            <XPath xmlns="http://www.w3.org/2002/06/xmldsig-filter2" Filter="subtract">/descendant::ds:Signature</XPath>
          </ds:Transform>
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue>Af7mrBbTcolNejZSr5LqgpNC0qV55QqCD8WyL5cOHok=</ds:DigestValue>
      </ds:Reference>
      <ds:Reference Id="reference-signedpropeties" Type="http://uri.etsi.org/01903#SignedProperties" URI="#SignedProperties_1">
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue>7JTjIAyrvjoYwYmbPlepQl29C84aCnynoolw1lAN7Ms=</ds:DigestValue>
      </ds:Reference>
      <ds:Reference Id="reference-keyinfo" URI="#KeyInfoId">
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue>VujVGQBsICd4GZ6RoTzLkFBKTCVaqhIGT39XqPZCGFc=</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue Id="SignatureValue1"> .. </ds:SignatureValue>
    <ds:KeyInfo Id="KeyInfoId">
      <ds:X509Data>
        <ds:X509Certificate> ..
        </ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
    <ds:Object>
      <xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="#Signature1">
        <xades:SignedProperties Id="SignedProperties_1">
          <xades:SignedSignatureProperties>
            <xades:SigningTime>2015-03-12T15:22:45Z</xades:SigningTime>
          </xades:SignedSignatureProperties>
        </xades:SignedProperties>
      </xades:QualifyingProperties>
    </ds:Object>
  </ds:Signature>
</ns3:NotificaScarto>


I've written this code:
Code
        private static TElXMLSigner createSigner() {
            TElXMLSigner Signer = new TElXMLSigner();

            Signer.CanonicalizationMethod = SBXMLDefs.Unit.xcmExclCanon;
            Signer.SignatureMethodType = SBXMLSec.Unit.xmtSig;  
            Signer.SignatureType = SBXMLSec.Unit.xstEnveloped;
            Signer.SignatureMethod = SBXMLSec.Unit.xsmRSA_SHA256;
            Signer.IncludeKey = true;
            return Signer;
        }
        
        public static XmlDocument XadesSign(XmlDocument Xdoc, TElX509Certificate cert, TElX509Certificate sdiCert) {

            
            TElXMLDOMDocument doc = GetTElXmlDocument(Xdoc);

            TElXMLKeyInfoX509Data X509Data = new TElXMLKeyInfoX509Data(false);
            X509Data.Certificate = cert;
            
            X509Data.IncludeDataParams = (short)(X509Data.IncludeDataParams | SBXMLSec.Unit.xkidX509Certificate);

            X509Data.IncludeDataParams = (short)(X509Data.IncludeDataParams & (~SBXMLSec.Unit.xkidX509IssuerSerial));
            X509Data.IncludeDataParams = (short)(X509Data.IncludeDataParams & (~SBXMLSec.Unit.xkidX509SubjectName));
            X509Data.IncludeKeyValue = false;


            TElXMLSigner Signer = createSigner();
            TElXAdESSigner XAdESSigner = new TElXAdESSigner();
            
            Signer.XAdESProcessor = XAdESSigner;
            try {

                TElXMLReference RefA = new TElXMLReference();

                TElXMLXPathFilter2Transform te1 = new TElXMLXPathFilter2Transform();
                TElXMLXPathFilterItem item = new TElXMLXPathFilterItem();
                item.Filter = SBXMLTransform.Unit.xfSubtract;
                item.XPath = "/descendant::ds:Signature";
                te1.Add(item);

                RefA.TransformChain.Add(te1);
                RefA.URI = "";      
                RefA.URINode = doc.DocumentElement;
                RefA.ID = "reference-document";
                RefA.DigestMethod = SBXMLSec.Unit.xdmSHA256;

                Signer.References.Add(RefA);

                Signer.KeyData = X509Data;

                Signer.UpdateReferencesDigest();
                XAdESSigner.XAdESVersion = SBXMLAdES.Unit.XAdES_v1_3_2; //ULTIMO ERA XAdES_v1_4_1

                TElMemoryCertStorage CertStorage = new TElMemoryCertStorage();
                CertStorage.Add(X509Data.Certificate, false);

                XAdESSigner.SigningCertificates = CertStorage;

                XAdESSigner.SigningTime = DateTime.UtcNow;
                XAdESSigner.Generate(SBXMLAdES.Unit.XAdES_v1_3_2);

                XAdESSigner.QualifyingProperties.Target = "#Signature1";  
                XAdESSigner.QualifyingProperties.XAdESPrefix = "xades";
                XAdESSigner.QualifyingProperties.SignedProperties.ID = "SignedProperties_1";

                      XAdESSigner.QualifyingProperties.SignedProperties.SignedSignatureProperties.SigningCertificate.Delete(0);
                               XAdESSigner.QualifyingProperties.SignedProperties.SignedSignatureProperties.SignaturePolicyIdentifier.SignaturePolicyImplied = false;

                XAdESSigner.SigningCertificatesDigestMethod = SBXMLSec.Unit.xdmSHA256;

                Signer.GenerateSignature();

                Signer.Signature.ID = "Signature1";
                Signer.Signature.KeyInfo.ID = "KeyInfoId";  
                Signer.Signature.SignatureValue.ID = "SignatureValue1";

                Signer.Signature.SignedInfo.SigPropRef.DigestMethod = SBXMLSec.Unit.xdmSHA256;
                Signer.Signature.SignedInfo.SigPropRef.ID = "reference-signedpropeties";

                TElXMLReference RefB = new TElXMLReference();
                RefB.URI = "#KeyInfoId";        
                RefB.URIData = Signer.Signature.SignatureValue.Value;
                RefB.ID = "reference-keyinfo";
                RefB.DigestMethod = SBXMLSec.Unit.xdmSHA256;

                Signer.References.Add(RefB);
                Signer.UpdateReferencesDigest();

                TElXMLDOMNode SigNode = doc.DocumentElement;
                Signer.Save(ref SigNode);

            }
            finally {
                Signer.Dispose();
                XAdESSigner.Dispose();
            }


But I get this XML instead of what I want:
Code
..
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature1">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <ds:Reference Id="reference-document" URI="">
        <ds:Transforms>
          <ds:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
            <XPath Filter="subtract" xmlns="http://www.w3.org/2002/06/xmldsig-filter2">/descendant::ds:Signature</XPath>
          </ds:Transform>
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <ds:DigestValue>Tmv28oBLONOk1GKz7ew7ugjy14YybNKzVvG8mTvu0AQ=</ds:DigestValue>
      </ds:Reference>
      <ds:Reference Id="reference-keyinfo" URI="#KeyInfoId">
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <ds:DigestValue>4BflkQukDVaEPtsUPB7aeTgg7EG2GIKxfcS/2bpCjkE=</ds:DigestValue>
      </ds:Reference>
      <ds:Reference Id="reference-signedpropeties" Type="http://uri.etsi.org/01903#SignedProperties" URI="#SignedProperties_1">
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <ds:DigestValue>/pfTsNIM3ojONES2nFFzS7v3pdk15cJnYFyAIJLuoHM=</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue Id="SignatureValue1">..</ds:SignatureValue>
    <ds:KeyInfo Id="KeyInfoId">
      <ds:X509Data>
        <ds:X509Certificate>..</ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
    <ds:Object>
      <xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="#Signature1">
        <xades:SignedProperties Id="SignedProperties_1">
          <xades:SignedSignatureProperties>
            <xades:SigningTime>2015-03-13T22:20:19.212Z</xades:SigningTime>
          </xades:SignedSignatureProperties>
        </xades:SignedProperties>
      </xades:QualifyingProperties>
    </ds:Object>
  </ds:Signature>

that does not validate cause it says it has been modified after the signing, and it does contain unattandable certificates (or something like that).
I can't figure out how to correct my code.
#32624
Posted: 03/14/2015 05:03:51
by Gaetano Lazzo (Basic support level)
Joined: 12/02/2014
Posts: 14

I've also tried a more simple implementation ad it does fail also:
Code
  public static XmlDocument XadesSign(XmlDocument Xdoc, TElX509Certificate cert, TElX509Certificate sdiCert) {


            TElXMLDOMDocument doc = GetTElXmlDocument(Xdoc);
            TElXMLSigner Signer = new TElXMLSigner();
            TElXAdESSigner XAdESSigner = new TElXAdESSigner();
            Signer.XAdESProcessor = XAdESSigner;
            try {
                TElXMLReference Ref = new TElXMLReference();
                Ref.TransformChain.Add(new TElXMLEnvelopedSignatureTransform());
                Ref.URI = "";
                Ref.URINode = doc.DocumentElement;
                Ref.DigestMethod = SBXMLSec.Unit.xdmSHA256;
                Signer.References.Add(Ref);

                TElXMLKeyInfoX509Data X509Data = new TElXMLKeyInfoX509Data(false);
                X509Data.Certificate = cert;
                X509Data.IncludeDataParams = (short)(X509Data.IncludeDataParams & (~SBXMLSec.Unit.xkidX509IssuerSerial));
                X509Data.IncludeDataParams = (short)(X509Data.IncludeDataParams & (~SBXMLSec.Unit.xkidX509SubjectName));
                X509Data.IncludeDataParams = (short)(X509Data.IncludeDataParams & (~SBXMLSec.Unit.xkidX509SKI));
                X509Data.IncludeKeyValue = false;

                Signer.CanonicalizationMethod = SBXMLDefs.Unit.xcmExclCanon;
                Signer.SignatureMethodType = SBXMLSec.Unit.xmtSig;  
                Signer.SignatureType = SBXMLSec.Unit.xstEnveloped;
                Signer.SignatureMethod = SBXMLSec.Unit.xsmRSA_SHA256;
                Signer.IncludeKey = true;
                Signer.KeyData = X509Data;
                Signer.UpdateReferencesDigest();
                XAdESSigner.XAdESVersion = SBXMLAdES.Unit.XAdES_v1_3_2;
                XAdESSigner.SigningTime = DateTime.UtcNow;
                XAdESSigner.SigningCertificatesDigestMethod = SBXMLSec.Unit.xdmSHA256;

                Signer.GenerateSignature();

                TElXMLDOMNode SigNode = doc.DocumentElement;
                Signer.Save(ref SigNode);

            }
            finally {
                Signer.Dispose();
                XAdESSigner.Dispose();
            }
            return GetMsXmlDocument(doc);


This is the code I use for converting a TelXMLDOMDOcument into an XmlDocument:
Code
       public static XmlDocument GetMsXmlDocument(TElXMLDOMDocument xml) {
            MemoryStream Ms = new MemoryStream();
            XmlDocument xm = new XmlDocument();
            xml.SaveToStream(Ms, SBXMLDefs.Unit.xcmNone, new SBXMLCharsets.TElXMLUTF8Codec());
            Ms.Seek(0, System.IO.SeekOrigin.Begin);
            xm.Load(Ms);
            return xm;
        }


and this is how I get the certificate:

Code
                TElX509Certificate c = new TElX509Certificate();
                int res=               c.LoadFromFileAuto(nomeFileFirmaNodo, pwdFirmaNodo);                
                if (res == 0) {
                    c.LoadKeyFromFileAuto(nomeFileFirmaNodo, pwdFirmaNodo);
                    return c;
                }
                return null;


I load the certificate from a PEM file composed like this:

Code
ag Attributes
    friendlyName: signature
    localKeyID: E9 2E 11 3E ....
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----
Bag Attributes
    friendlyName: signature
    localKeyID: E9 2E 11 3E ....
subject=/C=IT/O=AGENCY.../CODE.../OU=Invio Dati/CN= NAME SURMANE /CF /001
issuer=/C=IT/O=Agenzia delle Entrate/OU=Servizi Telematici/CN=CA Agenzia delle Entrate
-----BEGIN CERTIFICATE-----
..
-----END CERTIFICATE-----



Please help me, where I'm doing wrong?
Validators tell me that the document has been modified after the sign, or the sign is not valid.
#32625
Posted: 03/14/2015 05:23:58
by Eugene Mayevski (EldoS Corp.)

Thank you for contacting us.

Did you check the sample projects provided with SecureBlackbox? If not, please start with them and see if the correct document is created.


Sincerely yours
Eugene Mayevski
#32626
Posted: 03/14/2015 07:52:30
by Dmytro Bogatskyy (EldoS Corp.)

Hello,

Could you please try to define "ds" prefix for XPath filter item, for example:
Code
item.NamespaceMap.Add("ds", "http://www.w3.org/2000/09/xmldsig#");

When you are creating a new reference and then calculating a reference digest value, the reference is not attached to a signature element yet. So, XPath transform doesn't know how to resolve ds prefix and the expression may evaluate incorrectly.
#32627
Posted: 03/14/2015 09:24:43
by Gaetano Lazzo (Basic support level)
Joined: 12/02/2014
Posts: 14

I've found solution by myself, now it validates.
Problem was in the conversion from TElXMLDOMDocument to XmlDocument.
I changed it into
Code
public static XmlDocument GetMsXmlDocument(TElXMLDOMDocument xml) {
            MemoryStream Ms = new MemoryStream();
            XmlDocument xm = new XmlDocument();
            xm.PreserveWhitespace = true;
            xml.SaveToStream(Ms, SBXMLDefs.Unit.xcmNone, new SBXMLCharsets.TElXMLUTF8Codec());
            Ms.Seek(0, System.IO.SeekOrigin.Begin);
            xm.Load(Ms);
            return xm;
        }

and now it validates
#32628
Posted: 03/14/2015 09:27:01
by Gaetano Lazzo (Basic support level)
Joined: 12/02/2014
Posts: 14

Thanks to all, I'll send it again to the official validator (we are doing a preparatory test with a public company) and if I've other problems I'll come back here
Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.

Reply

Statistics

Topic viewed 1181 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!