J'ai une requête XML signée, qui est rejetée par la 3ème partie en raison d'une signature non valide. Par conséquent, j'ai écrit mon propre code de validation de signature pour voir ce qui ne va pas. Cependant, j'obtiens NPE en validant la signature XML que je viens de créer. Voici ce que le XML ressemble (je l'ai enlevé les parties non pertinentes):Java NPE lors de la validation de ma propre signature XML
<?xml version="1.0" encoding="UTF-8"?>
<envelope xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="some_third_party.xsd">
<header>...</header>
<body>...</body>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="MySignature">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>AaV+ejxBF8GjJvIZA9Bonw81Z1Y=</DigestValue>
</Reference>
<Reference Type="http://www.w3.org/2000/09/xmldsig#SignatureProperties" URI="#SignatureProperties">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>qcofYVnQ/n7sxKJPT5rG0+UYbjg=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>XXX</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>XXX</X509Certificate>
</X509Data>
</KeyInfo>
<Object Id="SignatureProperties">
<SignatureProperties xmlns="">
<SignatureProperty Id="TimeStamp" Target="#MySignature">
<TimeStamp>
<Date>2017-03-01</Date>
<Time>09:06:36.779+01:00</Time>
</TimeStamp>
</SignatureProperty>
</SignatureProperties>
</Object>
</Signature>
</envelope>
Lorsque je tente de valider cette signature, je reçois NPE sur la ligne commentée (il se passe réellement lorsque unmarshalling la signature, avant la réelle validation):
// Omitted: extract the X509 Certificate from the document
DOMValidateContext valContext = new DOMValidateContext(cert.getPublicKey(), signature);
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");
XMLSignature xmlSignature;
try {
// Null pointer exception here!
xmlSignature = factory.unmarshalXMLSignature(valContext);
} catch (MarshalException e) {
// Handle exception
}
Pour être complet, voici comment je crée la signature:
try {
XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");
Reference ref = xmlSignatureFactory.newReference("",
xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList(xmlSignatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
null,
null);
Reference signatureRef = xmlSignatureFactory.newReference("#SignatureProperties",
xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null),
null,
"http://www.w3.org/2000/09/xmldsig#SignatureProperties",
null);
SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(xmlSignatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
xmlSignatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Arrays.asList(ref, signatureRef));
XMLObject xmlObject = xmlSignatureFactory.newXMLObject(Collections.singletonList(new DOMStructure(timestamp)),
"SignatureProperties", null, null);
KeyInfoFactory keyInfoFactory = xmlSignatureFactory.getKeyInfoFactory();
List<Object> x509Content = new ArrayList<>();
x509Content.add(certificate);
X509Data xd = keyInfoFactory.newX509Data(x509Content);
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(xd));
XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo,
Collections.singletonList(xmlObject), SIGNATURE_ID, null);
DOMSignContext signContext = new DOMSignContext(privateKey, document.getDocumentElement());
xmlSignature.sign(signContext);
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
// Handle exception
}
Toute idée de ce que je fais mal ici?
Edit: a ajouté le stacktrace pour montrer où NPE est jeté exactement:
java.lang.NullPointerException: null
at org.jcp.xml.dsig.internal.dom.DOMXMLObject.<init>(DOMXMLObject.java:120)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.<init>(DOMXMLSignature.java:171)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshal(DOMXMLSignatureFactory.java:193)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshalXMLSignature(DOMXMLSignatureFactory.java:150)
Edit 2: Je dois aussi mentionner que les deux le contenu SignedValue et X509Certificate ont des espaces blancs après la création de la signature, ce qui fait un peu bizarre de me . Par exemple.
<X509Certificate>MIIG8DCCBdigAwIBAgIUJZSmBORuGuXyx48f04sNGHT+RhwwDQYJKoZIhvcNAQELBQAwWzELMAkG
A1UEBhMCQ0gxEzARBgNVBAoTClBvc3QgQ0ggQUcxDTALBgNVBAsTBFBST0QxKDAmBgNVBAMTH1BL
SSBTd2lzc1Bvc3QgTWFjaGluZSBBRVAgQ0EgRzMwHhcNMTcwMTI2MTIzMTQ0WhcNMjAwMTI2MTIz
MTQ0WjCBsTELMAkGA1UEBhMCQ0gxCzAJBgNVBAgTAkZSMSAwHgYDVQQKExdEaWUgU2Nod2VpemVy
...
Avez-vous une trace de la pile ? –
Oui, j'ai maintenant ajouté la trace de la pile. – Egemen
Êtes-vous sûr que 'signature' n'est pas nulle? –