Pregunta

que puedo hacer con éxito la validación manual de referencia (canonicalize cada elemento referenciado -> SHA1 -> Base 64 -> comprobar si es el mismo del contenido DigestValue) pero fallar con la verificación de la SignatureValue. Aquí está la SignedInfo a canonicalize y almohadilla:

<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 la eliminación de todos los espacios entre las etiquetas (y así conseguir todo el elemento en una sola línea), obtengo este SHA1 (en base 64):

6l26iBH7il / yrCQW6eEfv / VqAVo =

Ahora espero encontrar el mismo implícita después de la desencriptación del contenido SignatureValue, pero me da un differente y ya valor:

MCEwCQYFKw4DAhoFAAQU3M24VwKG02yUu6jlEH + u6R4N8Ig =

Aquí hay un código java para el 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));

Lo que me confunde mucho es que los dos compendios tienen diferente tamaño, pero por supuesto que también es necesario para obtener exactamente el mismo valor a partir de los dos cálculos. ¿Alguna sugerencia? Gracias.

¿Fue útil?

Solución

MCEwCQYFKw4DAhoFAAQU3M24VwKG02yUu6jlEH+u6R4N8Ig= es la codificación Base64 para una estructura ASN.1 DER-codificada: a SEQUENCE que contiene primero una AlgorithmIdentifier (que establece que este es SHA-1, sin parámetros desde SHA-1 acepta ninguna), entonces un OCTET STRING que contiene el del valor actual de 20 bytes. En hexadecimal, el valor es: dccdb8570286d36c94bba8e5107faee91e0df088

.

Esta estructura ASN.1 es parte de la norma firma RSA mecanismo. Está utilizando RSA descifrado para acceder a esa estructura, que no es estándar. Esté de suerte de conseguir nada en absoluto, ya que RSA cifrado y firma RSA son dos algoritmos distintos. Se da la circunstancia de que ambos se alimentan de la misma clase de pares de claves, y que el "viejo estilo" (también conocido como "PKCS # 1 v1.5") esquemas de firma y cifrado, utilizan técnicas de relleno similares (similares pero no idénticas, sino que es ya un poco sorprendente que la aplicación Java de RSA no ahogarse con el relleno de la firma cuando se utiliza en modo de descifrado).

De todos modos, 6l26iBH7il/yrCQW6eEfv/VqAVo= es codificación Base64 para un valor de 20 bytes, lo que, en hexadecimal, es: ea5dba8811fb8a5ff2ac2416e9e11fbff56a015a. Esto es lo que se obtiene por hashing la estructura XML que muestran más arriba, después de haber eliminado todos los espacios en blanco entre las etiquetas. La eliminación de todos los espacios en blanco es no Canonicalización adecuada. En realidad, por lo que yo sé, los espacios en blanco se ve afectado sólo entre atributos, dentro de las etiquetas, pero los espacios en blanco externa debe mantenerse sin cambios (a excepción de final de línea normalización [lo LF / CR + LF]).

El valor que se utiliza para la generación de la firma (la dccdb85...) se puede obtener mediante el objeto XML mostrar y quitando los espacios iniciales. Para que quede claro: copiar + pegar el XML en un archivo, a continuación, quitar los espacios iniciales (0 a 3 espacios) en cada línea. Se asegura de que todas las líneas de fin de utilizar un único LF (0x0A byte) y retire la LF final (el uno justo después de </ds:SignedInfo>). El archivo resultante debe tener una longitud de 930 bytes, y su hash SHA-1 es el valor esperado dccdb85....

Otros consejos

En cuanto a su ficha XML particular, me puede decir algunas cosas.

  • Está utilizando el método Canonicalización XML exclusiva Canonicalización Version 1.0 . Esta es una muy IMPORTANTE Factor para asegurar que usted produce el derecho de digerir valores y firma.

  • Está utilizando el mismo método Canonicalización tanto para el cálculo de los compendios de referencia, y para la canonizan SignedInfo antes de producir la firma.

La especificación para Exclusivo XML Canonicalizaiton Version 1.0 es producido por W3C y se puede encontrar en su respectivo Recomendación W3C . Si está calculando sus valores manualmente, asegúrese de que son conformes a la especificación exactamente, porque canónicos es una cosa difícil de lograr, y es muy importante hacer esto correctamente, de lo contrario sus valores serán incorrectas.

Yo sólo escribió un extenso artículo que describe el proceso de validación de la firma XML. El artículo se encuentra en mi blog . En él se describe el proceso en mucho más detalle que mi respuesta, ya que hay muchas complejidades a la firma XML. También contiene enlaces a las especificaciones prevalentes y RFC.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top