Question

Je peux faire avec succès la validation manuelle de référence (canoniser chaque élément référencé -> SHA1 -> base64 -> vérifier si elle est la même du contenu DigestValue) mais j'échoue avec la vérification de la SignatureValue. Voici la SignedInfo canoniser et hachage:

<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 supprimant tous les espaces entre les balises (et ainsi obtenir tout l'élément sur une seule ligne), j'obtiens ce SHA1 (en base64):

6l26iBH7il / yrCQW6eEfv / VqAVo =

Maintenant, je pense trouver le même digérer après le décryptage du contenu de SignatureValue, mais je reçois un differente et plus Valeur:

MCEwCQYFKw4DAhoFAAQU3M24VwKG02yUu6jlEH + u6R4N8Ig =

Voici un code java pour 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 seule chose qui me confond bien que les deux ont digests taille différente, mais bien sûr, je dois aussi obtenir exactement la même valeur des deux calculs. Aucune suggestion? Merci.

Était-ce utile?

La solution

MCEwCQYFKw4DAhoFAAQU3M24VwKG02yUu6jlEH+u6R4N8Ig= est base64 codant pour une structure ASN.1-codé DER: un premier SEQUENCE contenant un AlgorithmIdentifier (qui précise que cela est SHA-1, sans paramètres depuis le SHA-1 accepte none), puis un OCTET STRING qui contient le réelle valeur de 20 octets. En hexadécimal, la valeur est: dccdb8570286d36c94bba8e5107faee91e0df088

.

Cette structure ASN.1 fait partie de la norme signature RSA mécanisme. Vous utilisez RSA décryptage pour accéder cette structure, qui est non standard. Vous êtes vraiment chanceux d'obtenir quoi que ce soit, puisque le cryptage RSA et signature RSA sont deux algorithmes distincts. Il se trouve que les deux se nourrissent du même genre de paires de clés, et que la signature « ancienne » (alias « PKCS # 1 v1.5 ») et les systèmes de chiffrement utilisent des techniques de remplissage similaires (similaires mais non identiques, il est déjà un peu surprenant de constater que la mise en œuvre Java de RSA n'a pas étouffer sur le rembourrage de signature lorsqu'il est utilisé en mode de déchiffrement).

Quoi qu'il en soit, 6l26iBH7il/yrCQW6eEfv/VqAVo= est codage base64 pour une valeur de 20 octets, ce qui, en hexadécimal, est la suivante: ea5dba8811fb8a5ff2ac2416e9e11fbff56a015a. C'est ce que vous obtenez en hachant la structure XML vous montrer ci-dessus, après avoir enlevé tous les espaces entre les balises. Suppression de tous les espaces est pas canonicalisation bon. En fait, pour autant que je sache, les espaces est affecté uniquement entre les attributs, dans les balises, mais les espaces extérieurs doit être maintenu inchangé (sauf pour la normalisation de fin de ligne [la chose LF / CR + LF]).

La valeur qui a été utilisée pour la génération de signature (le dccdb85...) peut être obtenu en utilisant l'objet XML vous montrer et en supprimant les espaces principaux. Pour être clair: vous copiez + collez le XML dans un fichier, puis retirez les espaces principaux (0 à 3 places) sur chaque ligne. Vous assurez-vous que toutes les fin de lignes utilisent un seul LF (octet 0x0A) et que vous supprimez la finale LF (celui juste après </ds:SignedInfo>). Le fichier résultant doit avoir une longueur de 930 octets, et son hachage SHA-1 est la valeur dccdb85... attendue.

Autres conseils

En regardant votre jeton XML particulier, je peux vous dire quelques petites choses.

  • Vous utilisez la méthode Canonicalisation XML exclusif Canonicalisation Version 1.0 . Ceci est très IMPORTANT facteur en veillant à ce que vous produisez la bonne digestion des valeurs et la signature.

  • Vous utilisez la même méthode de calcul Canonicalisation aussi bien pour les digestions de référence, et pour canonisant SignedInfo avant de produire la signature.

La spécification XML exclusive Canonicalizaiton Version 1.0 est produit par le W3C et se trouve à sa respective mon blog . Il décrit le processus beaucoup plus de détails que ma réponse, car il y a beaucoup de subtilités à la signature XML. Il contient également des liens vers les spécifications courantes et RFCs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top