Domanda

che posso fare con successo la validazione di riferimento manuale (canonicalize ogni elemento di riferimento -> SHA1 -> Base64 -> verifica se è la stessa del contenuto DigestValue) ma non con la verifica della SignatureValue. Ecco il SignedInfo per canonicalize e hash:

<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:

MCEwCQYFKw4DAhoFAAQU3M24VwKG02yUu6jlEH + u6R4N8Ig =

Ecco un 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 dei due calcoli. Eventuali suggerimenti? Grazie.

È stato utile?

Soluzione

MCEwCQYFKw4DAhoFAAQU3M24VwKG02yUu6jlEH+u6R4N8Ig= è Base64 codifica per una struttura ASN.1 DER-codificato: un SEQUENCE contenente primo un AlgorithmIdentifier (che afferma che questa è SHA-1, senza parametri da SHA-1 accetta nessuno), quindi un OCTET STRING che contiene la effettivo valore di 20 byte. In esadecimale, il valore è: dccdb8570286d36c94bba8e5107faee91e0df088

.

Questa struttura ASN.1 è parte dello standard RSA firma meccanismo. Si utilizza RSA decrittazione per l'accesso che la struttura, che è non-standard. Siete realmente fortunati ad avere qualcosa a tutti, dal momento che RSA crittografia e firma RSA sono due algoritmi distinti. Si dà il caso che entrambi nutrono lo stesso tipo di coppie di chiavi, e che il "vecchio stile" (alias "PKCS # 1 v1.5") schemi di firma e cifratura utilizzano tecniche di padding simili (simile ma non identico, ma è già un po 'sorprendente che l'implementazione Java di RSA non soffocare sul padding firma quando utilizzato in modalità decrittazione).

Comunque, 6l26iBH7il/yrCQW6eEfv/VqAVo= è Base64 codifica per un valore di 20 byte, che, in esadecimale, è: ea5dba8811fb8a5ff2ac2416e9e11fbff56a015a. Questo è ciò che si ottiene dal hashing la struttura XML si mostra sopra, dopo aver tolto tutti gli spazi tra i tag. Rimuovere tutti gli spazi è non corretta canonica. In realtà, per quanto ne so, spazi bianchi è influenzato solo tra gli attributi, all'interno dei tag, ma gli spazi esterni deve essere mantenuto invariato (ad eccezione di linea che termina la normalizzazione [la cosa LF / CR + LF]).

Il valore che è stato utilizzato per la generazione della firma (la dccdb85...) può essere ottenuto utilizzando l'oggetto XML si mostra e rimuovendo gli spazi iniziali. Per essere chiari: si copia + incolla l'XML in un file, quindi rimuovere gli spazi iniziali (da 0 a 3 spazi) su ogni riga. È assicurarsi che tutte le linee di fine utilizzano un singolo LF (0x0A byte) e si rimuove la LF finale (quella appena dopo </ds:SignedInfo>). Il file risultante deve avere lunghezza 930 byte, e il suo hash SHA-1 è il valore dccdb85... atteso.

Altri suggerimenti

Guardando il vostro particolare di token XML, vi posso dire alcune cose.

  • Si utilizza il metodo di canonizzazione XML Exclusive Canonicalization Versione 1.0 . Questo è un Importante fattore nel garantire che si produce il diritto digerire i valori e la firma.

  • Si utilizza lo stesso metodo di canonizzazione sia per calcolare i digest di riferimento, e per canonicalizing la SignedInfo prima di produrre la firma.

La specifica per l'Exclusive XML Canonicalizaiton versione 1.0 è prodotto da W3C e può essere trovato alla sua rispettiva W3C raccomandazione . Se si Computing vostri valori manualmente, essere sicuri che si sono conformi esattamente alle specifiche, a causa canonica è una cosa difficile da ottenere di destra, ed è molto importante fare questo in modo corretto, altrimenti i valori non saranno corretti.

Ho appena scritto un lungo articolo che descrive il processo di validazione XML Signature. L'articolo è situato alla il mio blog . Esso descrive il processo in modo molto più dettagliato di quanto la mia risposta, in quanto vi sono molte complessità di XML Signature. Esso contiene inoltre collegamenti alle specifiche prevalenti e RFC.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top