Devo inviare un file XML firmato a un'agenzia governativa in Brasile. Il problema è che il digest calcolato il mio codice Java (utilizzando il Java XML Digital Signature API è diverso da quello generato con un altro strumento come XMLSECValore digerito errato per firme xml utilizzando l'API di firma digitale Java XML
Ecco il codice che uso per generare una firma XML per qualche nodo XML:.
private synchronized void sign(XmlObject obj) throws Exception {
initKeystore();
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
List<Transform> transformList = new ArrayList<Transform>();
Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
Transform c14NTransform = fac.newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
(TransformParameterSpec) null);
transformList.add(envelopedTransform);
transformList.add(c14NTransform);
Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null,
null);
SignedInfo si = fac.newSignedInfo(
fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref));
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream(System.getProperty("javax.net.ssl.keyStore")),
System.getProperty("javax.net.ssl.keyStorePassword").toCharArray());
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry("entry",
new KeyStore.PasswordProtection(System.getProperty("javax.net.ssl.keyStorePassword").toCharArray()));
X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
// Create the KeyInfo containing the X509Data.
KeyInfoFactory kif = fac.getKeyInfoFactory();
X509Data xd = kif.newX509Data(Collections.singletonList(cert));
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
// Instantiate the document to be signed.
Element el = (Element) obj.getDomNode().getFirstChild();
String id = el.getAttribute("Id");
DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), el);
// Create the XMLSignature, but don't sign it yet.
XMLSignature signature = fac.newXMLSignature(si, ki);
// Marshal, generate, and sign the enveloped signature.
signature.sign(dsc);
}
Se provo a convalidare il XML generato con xmlsec, ottengo il seguente errore:
$ xmlsec1 --verify consulta.xml
func=xmlSecOpenSSLEvpDigestVerify:file=digests.c:line=229:obj=sha1:subj=unknown:error=12:invalid data:data and digest do not match
FAIL
Ma se provo a firmare lo stesso del file (consult.xml) con xmlsec (utilizzando la stessa chiave privata), quell'errore va te:
xmlsec1 --sign --output doc-signed.xml --privkey-pem cert.pem consulta.xml
Le differenze tra consult.xml e doc-signed.xml (generato da xmlsec) sono i contenuti delle variabili SignatureValue e DigestValue:
consulta.xml:
<DigestValue>Ajn+tfX7JQc0HPNJ8KbTy7Q2f8I=</DigestValue>
...
<SignatureValue>Q1Ys0Rtj8yL2SA2NaQWQPtmNuHKK8q2anPiyLWlH7mOIjwOs0GEcD0WLUM/BZU0Q
T0kSbDTuJeTR2Ec9wu+hqXXbJ76FpX9/IyHrdyx2hLg0VhB5RRCdyBEuGlmnsFDf
XCyBotP+ZyEzolbTCN9TjCUnXNDWtFP1YapMxAIA0sth0lTpYgGJd8CSvFlHdFj+
ourf8ZGiDmSTkVkKnqDsj8O0ZLmbZfJpH2CBKicX+Ct7MUz2sqVli4XAHs6WXX+E
HJpbOKthS3WCcpG3Kw4K50yIYGTkTbWCYFxOVsMfiVy4W/Qz15Vxb8chD8LM58Ep
m/szmvnTAESxv/piDr7hyw==</SignatureValue>
doc-signed.xml:
<DigestValue>w6xElXJrZw3G86OsNkWav+pcKJo=</DigestValue>
...
<SignatureValue>YmUsnlnAY9uLhlfVBLhB8K8ArxMOkOKZJoQ6zgz55ggU6vJCO9+HWJCKQJp6Rvn/w5PCAFY0KJRb
r6/WhHML0Z+Q6TSuIL8OTvJ3iPoROAK6uy07YAflKOUklqk4uxgfMkR+hWMCyfITJVCVZo/MXmPy
g7YwmztoSlGH+p6+ND5n2u47Y2k6SpIvw3CUxwAVQkD0Hsj3G58cbUbrFCoyPVGOe4zJ9c1HPsMW
KzBEFe3QETzPJ8I1B7EEVi5oDvzXE2rMTH4K7zvNGnXpBNGwnSjEOticlqKVP5wyUD7CPwgF1Wgy
Z0njvlaW3K8YmAY8fc70v/+wSO6Fu+0zj18Xeg==</SignatureValue>
non voglio postare il resto sia file perché sono uguali e renderebbe questo post ancora più prolisso.
Da quello che posso raccogliere, l'app Web che riceve questo file XML è un'applicazione .NET e calcola un diverso digest di firma che il mio codice Java (molto simile a xmlsec). Qualche idea?
Scusa, ma sei sicuro che l'algoritmo di hash digest sia SHA1? Può essere qualcos'altro e la firma può essere ancora RSA_SHA1 (mentre leggo il tuo codice). – esej
Questo è quello che sto dicendo all'API Java da fare. Una cosa che ho notato è che se salvi il documento xmls in un file, leggo quel file e firma ciò che ho letto, il digest è calcolato correttamente. Quindi penso che forse gli spazi bianchi siano in qualche modo considerati sul lato Java o XMLSEC. Questo risolverebbe il mio problema se avessi bisogno di firmare l'xml solo una volta; il problema è che ho bisogno di farlo almeno due volte ... – Andre
Hai cheched '\ n'? –