Posso eseguire correttamente la convalida del riferimento manuale (canonicalizzare ogni elemento di riferimento -> SHA1 -> Base64 -> verificare se è lo stesso del contenuto di DigestValue) ma non riesco con la verifica di SignatureValue. Ecco il SignedInfo per canonicalize e hash:Verifica manuale della firma XML
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#element-1-1291739860070-11803898">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>d2cIarD4atw3HFADamfO9YTKkKs=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#timestamp">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>YR/fZlwJdw+KbyP24UYiyDv8/Dc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
Ater rimuovendo tutti gli spazi tra i tag (e in modo da ottenere l'intero elemento su una sola riga), ottengo questo digest SHA1 (in Base64):
6l26iBH7il/yrCQW6eEfv/VqAVo =
Ora mi aspetto di trovare lo stesso digest dopo la decifratura del contenuto SignatureValue, ma ho un differente e più valore:
MCEwCQYFKw4DAhoFAAQ U3M24VwKG02yUu6jlEH + u6R4N8Ig =
Ecco po 'di codice java per l'decyption:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(new File(inputFilePath));
NodeList nl = doc.getElementsByTagName("ds:SignatureValue");
if (nl.getLength() == 0) {
throw new Exception("Cannot find SignatureValue element");
}
String signature = "OZg96GMrGh0cEwbpHwv3KDhFtFcnzPxbwp9Xv0pgw8Mr9+NIjRlg/G1OyIZ3SdcOYqqzF4/TVLDi5VclwnjBAFl3SEdkyUbbjXVAGkSsxPQcC4un9UYcecESETlAgV8UrHV3zTrjAWQvDg/YBKveoH90FIhfAthslqeFu3h9U20=";
X509Certificate cert = X509Certificate.getInstance(new FileInputStream(<a file path>));
PublicKey pubkey = cert.getPublicKey();
Cipher cipher = Cipher.getInstance("RSA","SunJCE");
cipher.init(Cipher.DECRYPT_MODE, pubkey);
byte[] decodedSignature = Base64Coder.decode(signature);
cipher.update(decodedSignature);
byte[] sha1 = cipher.doFinal();
System.out.println(Base64Coder.encode(sha1));
La cosa che mi confonde tanto è che i due digest hanno dimensioni diverse, ma naturalmente ho anche bisogno di ottenere esattamente lo stesso valore dai due calcoli. Eventuali suggerimenti? Grazie.
"Ater rimuove tutti gli spazi tra i tag" ... è giusto? Guardando http://www.w3.org/TR/2001/REC-xml-c14n-20010315#Example-WhitespaceInContent sembra che tu stia rimuovendo troppo spazio bianco. –
Grazie per la risposta. Capisco il tuo punto ma, come ho detto all'inizio della domanda, posso fare validamente riferimento alla validazione (due riferimenti, non può essere un incidente) dello stesso messaggio SOAP e solo rimuovendo quegli spazi, quindi devo assumere è giusto. – Johnca
La Canonizzazione è molto più che rimuovere gli spazi bianchi. Gestisce i problemi del prefisso dello spazio dei nomi, l'ordinamento degli attributi e in generale tutto ciò che modifica l'ordine dei byte del file phisicaly (e quindi il digest dell'hash), ma non modifica l'infoset XML (== il significato del payload dell'XML) – m0sa