makdimka077 / xades4j

Automatically exported from code.google.com/p/xades4j
GNU Lesser General Public License v3.0
0 stars 0 forks source link

signature validation failure #66

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hello,

I try to check a signature of a XML file at the following URL : 
http://references.modernisation.gouv.fr/sites/default/files/TSL-FR.xml

The certificate used for the signature is in the file. So I inspired of the 
code from the issue 37 
(http://code.google.com/p/xades4j/issues/detail?id=37&can=1)

The signature verification process is ok except in the class 
xades4j.verification.CertRefUtils on the method findCertRef

the following equality fails : 
cert.getIssuerX500Principal().equals(certRefIssuerPrincipal)

But the other equality certRef.serialNumber.equals(cert.getSerialNumber()) 
return true.

When I compare the two X500Principal, it's seems that the special character 
"é" has not been parsed properly and so the equality is not true.

if I replace the equality by a new equality :
new 
X500Principal(cert.getIssuerX500Principal().getName(X500Principal.RFC1779)).equa
ls(certRefIssuerPrincipal)

then the result is true and the signature is validated.

Is this a bug when the signature is extracted? the alternative equality is safe?

thank you in advance :)

François

PS : i'm french so sorry for my poor english...

Original issue reported on code.google.com by francois...@gmail.com on 22 Apr 2013 at 9:10

GoogleCodeExporter commented 9 years ago
Hi,

As I can understand from the java docs

http://docs.oracle.com/javase/6/docs/api/javax/security/auth/x500/X500Principal.
html#getName(java.lang.String))

the names are RFC 2253 by default. The equality could fail if the name on the 
'certRef' was generated in a different format.

I'm not sure if the alternative comparison is always valid... seems that you 
may loose some fields from the DN. I guess it comes down to how the string 
representation of the X.500 dDN was generated to the 'certRef' (assuming the 
name in the certificate is the correct one). Note that the equals method uses 
getName with the CANONICAL format:

http://docs.oracle.com/javase/6/docs/api/javax/security/auth/x500/X500Principal.
html#equals(java.lang.Object)

If you call getName(X500Principal.CANONICAL) on both principals what are the 
differences? Where do you see the invaçid "é"? Maybe it is a problem on 
deserialization or something like that.

Original comment by luis.fgoncalv on 25 Apr 2013 at 10:55

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Hello luis and thank you for your response.
When I inspect cert.getX500Principal() and certRefIssuerPrincipal, I have the 
following answers
From cert.getX500Principal() : 
CANONCICAL
c=fr,2.5.4.17=#13053735353732,l=paris cedex 12,street=139 rue de 
bercy,ou=dpae,o=#1437446972656374696f6e2047e96ee972616c65206465206c61204d6f64657
26e69736174696f6e206465206c2745746174202844474d4529,2.5.4.12=#130f4c617572656e74
20566f696c6c6f74,cn=#14206c617572656e742e766f696c6c6f744066696e616e6365732e676f7
5762e6672

RFC1779
C=FR, OID.2.5.4.17=75572, L=Paris Cedex 12, STREET=139 rue de Bercy, OU=DPAE, 
O=Direction Générale de la Modernisation de l'Etat (DGME), 
OID.2.5.4.12=Laurent Voillot, CN=laurent.voillot@finances.gouv.fr

RFC2253
C=FR,2.5.4.17=#13053735353732,L=Paris Cedex 12,STREET=139 rue de 
Bercy,OU=DPAE,O=Direction G�n�rale de la Modernisation de l'Etat 
(DGME),2.5.4.12=#130f4c617572656e7420566f696c6c6f74,CN=laurent.voillot@finances.
gouv.fr

From certrefIssuerPrincipal
CANONICAL
c=fr,2.5.4.17=#13053735353732,l=paris cedex 12,street=139 rue de 
bercy,ou=dpae,o=direction générale de la modernisation de l'etat 
(dgme),2.5.4.12=#130f4c617572656e7420566f696c6c6f74,cn=laurent.voillot@finances.
gouv.fr

RFC1779
C=FR, OID.2.5.4.17=75572, L=Paris Cedex 12, STREET=139 rue de Bercy, OU=DPAE, 
O=Direction Générale de la Modernisation de l'Etat (DGME), 
OID.2.5.4.12=Laurent Voillot, CN=laurent.voillot@finances.gouv.fr

RFC2253
C=FR,2.5.4.17=#13053735353732,L=Paris Cedex 12,STREET=139 rue de 
Bercy,OU=DPAE,O=Direction Générale de la Modernisation de l'Etat 
(DGME),2.5.4.12=#130f4c617572656e7420566f696c6c6f74,CN=laurent.voillot@finances.
gouv.fr

As I told you, I think something is wrong when I extract the certificate. And 
the fields with special characters like “é” seem to cause problem. In the 
canonical form, the fields with the special characters “é” and the CN are 
encoded in hexadecimal but I think they shouldn’t be.
I suspected like you a problem occuring when the certificate is deserialized. 
For his extraction, I used the following code: 

public interface MyKeySelectorResult {

    public X509Certificate getCertificate();

    public Key getKey();

}

public static MyKeySelectorResult getX509FromXadesFile(InputStream fileInput) 
throws Exception {

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    Document doc = dbf.newDocumentBuilder().parse(fileInput);

    // Find Signature element
    NodeList nl = doc.getElementsByTagName("ds:Signature");
    if (nl.getLength() == 0) {
        throw new Exception("Cannot find Signature element");
    }

    DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(), nl.item(0));
    XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

    XMLSignature signature = fac.unmarshalXMLSignature(valContext);
    KeyInfo keyInfo = signature.getKeyInfo();

    if (keyInfo == null) {
        throw new KeySelectorException("ERROR: KeyInfo object null!");
    }
    Iterator<?> hKeyInfo = keyInfo.getContent().iterator();
    while (hKeyInfo.hasNext()) {
        XMLStructure hX509Data = (XMLStructure) hKeyInfo.next();
        if (!(hX509Data instanceof X509Data))
            continue;
        X509Data x509Data = (X509Data) hX509Data;
        Iterator<?> hX509Certificate = x509Data.getContent().iterator();
        while (hX509Certificate.hasNext()) {
            Object oX509Certificate = hX509Certificate.next();
            if (!(oX509Certificate instanceof X509Certificate))
                continue;
            final X509Certificate x509Certificate = ((X509Certificate) oX509Certificate);
            final PublicKey key = x509Certificate.getPublicKey();
            return new MyKeySelectorResult() {
                public Key getKey() {
                    return key;
                }
                public X509Certificate getCertificate() {
                    return x509Certificate;
                }
            };
        }
    }
    throw new KeySelectorException("ERROR: No X509Certificate found!");

}

What’s wrong with my code?
Thank you in advance
François

Original comment by francois...@gmail.com on 26 Apr 2013 at 8:42

GoogleCodeExporter commented 9 years ago
Your code seems correct... I don't understand the difference. Can you try to 
copy the base64 certificate from the signature file, save it to a separate file 
and then load it on a separate program to check the issuer name? May it's 
something wrong on the original encoding of the certificate. I'm running out of 
ideas..

Original comment by luis.fgoncalv on 12 May 2013 at 10:12

GoogleCodeExporter commented 9 years ago
did you find the problem? Is this still an issue?

Original comment by luis.fgoncalv on 4 Sep 2013 at 10:34

GoogleCodeExporter commented 9 years ago

Original comment by luis.fgoncalv on 4 Sep 2013 at 10:37