EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Validating against newer Java parsers

Also by EldoS: RawDisk
Access locked and protected files in Windows, read and write disks and partitions and more.
#33760
Posted: 06/24/2015 06:18:29
by Jose Vicente Boronat Domenech (Standard support level)
Joined: 05/19/2015
Posts: 3

Hello,

I am using your Delphi library for XML in order to sign electronically documents before hand in them by uploading it to a website. At the beginning it worked right but then it started to refuse the signature. I have some other software from a different party that generates the same document and it is correctly validated.

I run some test in other different validators and most of them also fail to validate the document, and one of them run into:

Code
javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException


for element SignedProperties.

After some research found on internet this:

Quote
In Java, getElementById() finds elements by looking for attributes of type ID, not for attributes with the name of "id".

In the above example, getElementById("xyz") will return that foo element, even though the name of the attribute on it is not "id" (assuming the DOM knows that bar has an attribute type of ID).

So how does the DOM know what attribute type an attribute has? There are three ways:

Provide an XML Schema to the parser (example)
Provide a DTD to the parser
Explicitly indicate to the DOM that it is treated as an attribute type of ID.

The third option is done using the setIdAttribute() or setIdAttributeNS() or setIdAttributeNode() methods on the org.w3c.dom.Element class.
Code
Document doc;
Element fooElem;

doc = ...; // load XML document instance
fooElem = ...; // locate the element node "foo" in doc

fooElem.setIdAttribute("bar", true); // without this, 'found' would be null

Element found = doc.getElementById("xyz");


This has to be done for each element node that has one of these type of attributes on them. There is no simple built-in method to make all occurrences of attributes with a given name (e.g. "id") be of attribute type ID.

This third approach is only useful in situations where the code calling the getElementById() is separate from that creating the DOM. If it was the same code, it already has found the element to set the ID attribute so it is unlikely to need to call getElementById().


Most of my ressearch in Google for that Exception bring me to that exact same issue, and all the validating tools I am using are made in Java so the problem have to be with the IDs.

So my question is, is there any way to indicate that the attribute "ID" is the actual Id attribute for SignedProperties when signing with your library?
I am using also a references for KeyInfo so it is possible for KeyInfo too?

Thanks and regards
#33761
Posted: 06/24/2015 07:07:22
by Dmytro Bogatskyy (EldoS Corp.)

Thank you for contacting us.

Quote
So my question is, is there any way to indicate that the attribute "ID" is the actual Id attribute for SignedProperties when signing with your library?
I am using also a references for KeyInfo so it is possible for KeyInfo too?

XML-DSig schema ( http://www.w3.org/TR/xmldsig-core/xml...schema.xsd ) defines Id attribute as follows:
Quote

<attribute name="Id" type="ID" use="optional"/>

It is possible that this third party java application is not aware of this XML schema.
Unfortunately, there is no property that allows to change Id attribute name. But, you can use TElXMLSigner.OnFormatElement event for this. For example, place a following code to the event handler:
Code
String s = Element.getAttribute("Id");
if (s != "")
{
  Element.RemoveAttribute("Id");
  Element.setAttribute("ID", s);
}
#33762
Posted: 06/24/2015 07:48:34
by Jose Vicente Boronat Domenech (Standard support level)
Joined: 05/19/2015
Posts: 3

Thanks for your fast answer.

I forgot to tell you some details but I assume you have deduced most of it.
The signature we are using is XAdES EPES 1.3.2 and generating it with the AdvanceSigner example for delphi with some modifications.

I have already tried what you suggested. The error stops appearing for SignedProperties, but same error shows for KeyInfo. In the other document I have, the one which validates, it is used Id not ID like in the wrong one.

It is possible that it may be caused because of the place where namespaces are declared?

In the document that validates the structure is:

Code
<fe:Facturae xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:fe="http://www.facturae.es/Facturae/2014/v3.2.1/Facturae">
  <ds:Signature xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#" Id="Signature664376">
     <ds:Object>
        <etsi:QualifyingProperties Target="#Signature664376">


In the one generated with Blackbox:

Code
<facE:Facturae xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#" xmlns:facE="http://www.facturae.es/Facturae/2014/v3.2.1/Facturae">
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-471423579">
     <ds:Object>
   <etsi:QualifyingProperties xmlns:etsi="http://uri.etsi.org/01903
            /v1.3.2#" Target="#Signature-471423579">
#33764
Posted: 06/24/2015 08:41:34
by Dmytro Bogatskyy (EldoS Corp.)

Hello,

Quote
It is possible that it may be caused because of the place where namespaces are declared?

Usually, the place where namespace declared (if it declared in the node that using it or in the parent node) or the prefix name should not be important. Of course, you shouldn't change them after signing. But, sometimes, some applications have own rules.
Quote
In the document that validates the structure is:
<fe:Facturae xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:fe="http://www.facturae.es/Facturae/2014/v3.2.1/Facturae">

Please use the following code as a reference to sign factura electronic xml documents:
Code
procedure FacturaESign(XMLDocument : TElXMLDOMDocument; Cert : TElX509Certificate);
var
  Signer : TElXMLSigner;
  XAdESSigner: TElXAdESSigner;
  X509KeyInfoData: TElXMLKeyInfoX509Data;
  DataFormat : TElXMLDataObjectFormat;
  Ref : TElXMLReference;
  URL : string;
  Buf : ByteArray;
  k : Integer;
begin
  Signer := TElXMLSigner.Create(nil);
  XAdESSigner := TElXAdESSigner.Create(nil);
  X509KeyInfoData := TElXMLKeyInfoX509Data.Create(false);
  try
    Signer.XAdESProcessor := XAdESSigner;
    Signer.SignatureMethodType := xmtSig;
    Signer.SignatureMethod := xsmRSA_SHA1;
    Signer.CanonicalizationMethod := xcmCanon;
    Signer.IncludeKey := true;

    k := Signer.References.Add;
    Ref := Signer.References[k];
    Ref.DigestMethod := xdmSHA1;
    Ref.ID := 'Ref1';
    Ref.URI := '';
    Ref.URINode := XMLDocument.DocumentElement;
    Ref.TransformChain.AddEnvelopedSignatureTransform();

    Signer.UpdateReferencesDigest();

    k := Signer.References.Add;
    Ref := Signer.References[k];
    Ref.DigestMethod := xdmSHA1;
    Ref.URI := '#Certificate1';

    XAdESSigner.XAdESVersion := XAdES_v1_3_2;
    XAdESSigner.Included := [xipSignerRole];
    XAdESSigner.SigningTime := UTCNow;
    XAdESSigner.SignerRole.ClaimedRoles.AddText(XAdESSigner.XAdESVersion, XMLDocument, 'emisor');

    URL := 'http://www.facturae.es/politica_de_firma_formato_facturae/politica_de_firma_formato_facturae_v3_1.pdf';
    XAdESSigner.PolicyId.SigPolicyId.Identifier := URL;
    XAdESSigner.PolicyId.SigPolicyId.IdentifierQualifier := xqtNone;
    XAdESSigner.PolicyId.SigPolicyId.Description := 'Pol√≠tica de Firma FacturaE v3.1';
    XAdESSigner.PolicyId.SigPolicyHash.DigestMethod := DigestMethodToURI(xdmSHA1);
    // uncomment to calculate a digest value or use precalculated value
    //Buf := DownloadData(URL);
    //XAdESSigner.PolicyId.SigPolicyHash.DigestValue := CalculateDigest(@Buf[0], Length(Buf), xdmSHA1);
    XAdESSigner.PolicyId.SigPolicyHash.DigestValue := ConvertFromBase64String('Ohixl6upD6av8N7pEvDABhEL6hM=');

    XAdESSigner.SigningCertificates := TElMemoryCertStorage.Create(nil);
    XAdESSigner.OwnSigningCertificates := true;
    XAdESSigner.SigningCertificates.Add(Cert);

    XAdESSigner.Generate(XAdES_EPES);

    XAdESSigner.QualifyingProperties.XAdESPrefix := 'etsi';

    DataFormat := TElXMLDataObjectFormat.Create(XAdESSigner.XAdESVersion);
    DataFormat.Description := 'Factura electr√≥nica';
    DataFormat.MimeType := 'text/xml';
    DataFormat.ObjectReference := '#Ref1';
    XAdESSigner.QualifyingProperties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Add(DataFormat);

    X509KeyInfoData.IncludeKeyValue := true;
    X509KeyInfoData.IncludeDataParams := [xkidX509Certificate];
    X509KeyInfoData.Certificate := Cert;
    Signer.KeyData := X509KeyInfoData;

    Signer.GenerateSignature;
    Signer.Signature.KeyInfo.ID := 'Certificate1';

    Signer.SaveEnveloped(XMLDocument.DocumentElement);    
  finally
    FreeAndNil(X509KeyInfoData);
    FreeAndNil(Signer);
    FreeAndNil(XAdESSigner);
  end;
end;
#33765
Posted: 06/24/2015 08:53:57
by Jose Vicente Boronat Domenech (Standard support level)
Joined: 05/19/2015
Posts: 3

Thank you very much,

it seems very good
I'll adapt it and check it

Thanks and regards
Also by EldoS: RawDisk
Access locked and protected files in Windows, read and write disks and partitions and more.

Reply

Statistics

Topic viewed 1128 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!