[Je suis sous plateforme WinXPPro, avec Java6 à jour et la dernière version de Bouncycastle. J'ai installé le Policy machin bidule.]
Dans le cadre de la manipulation de certificats X.509 je cherche à effectuer moi-même manuellement certaines comparaisons et notamment la comparaison du hash du certificat.
Je calcule moi même le hash du certificat à partir d'un tableau de byte extrait via MonCertificat.getEncoded().
Mon hash est toujours correct puisque lorsque je le compare avec la valeur donnée par le magasin windows ou celui de Thunderbird où j'ai les mêmes certificats ça colle pile/poil.
Donc ça c'est ok.
Maintenant lorsque je veux m'occuper de la signature du certificat elle même, là ça coince.
J'extrais la signature via MonCertificat.getSignature() puis je veux déchiffrer cette valeur via l'algorithme RSA pour obtenir le hash et le comparer à celui que j'ai calculé.
Ya pas moyen de déchiffrer sans lever une exception, même avec BouncyCastle.
Avec les providers installés de base, je me retrouve avec une BadPaddingException.
Avec BouncyCastle je me retrouve avec une DataLenghtException.
A noter que j'ai ces exception uniquement lorsque la valeur chiffrée de la signature est supérieure à 128bits.
Or sur le wiki de bouncycastle il est indiqué dans la FAQ (point n° 5) que le chiffrement RSA "will not process more than 127 bytes of data"... Ce qui me parait hallucinant, la FAQ date de 2002, peut être n'est-elle plus trop à jour
En d'autres termes, le déchiffrement ne plante pas avec de vieux certificats (longueur hash chiffré <= 128 bits), mais par contre les valeurs retournées sont incohérentes...
J'ai aussi un problème de fonctionnement de la méthode verify() de X509Certificate qui me lève une exception avec des certificats récents (alors que ceux-ci sont correct) et pas avec mon certificat ayant un hash chiffré de 128bits.
Donc voilà, je cale, je plante, j'arrive pas à comprendre où je déconne.
Je poste ici le code de déchiffrement du hash, à mettre dans une méthode de classe ou dans un static void main :
EDIT : La méthode bytesToHexString() :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 Security.addProvider(new BouncyCastleProvider()); String sNomX509 = "certificat1.globalsign.cer"; X509Certificate cert = null; try{ // // Chargement du Certificat X.509 ... // InputStream inStream = new FileInputStream(sNomX509); CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate)cf.generateCertificate(inStream); inStream.close(); //System.out.println(cert.toString()); } catch(FileNotFoundException fnfe){ System.out.println("Le fichier " + sNomX509 + " n'a pas été trouvé."); fnfe.printStackTrace(); } catch(CertificateException ce){ System.out.println("Problème avec le certificat. Probablement une erreur d'encodage du fichier."); ce.printStackTrace(); } catch(IOException ioe){ System.out.println("Erreur d'entrée/sortie."); ioe.printStackTrace(); } catch(Exception e){ System.out.println("Exception générique."); e.printStackTrace(); } // // Déchiffrement de la valeur de signature du certificat // try{ /* * Note : Le hash a été chiffré avec la clef privée du possesseur du certificat. * Il faut utiliser sa clef publique pour déchiffrer. */ byte[] byTabHashValue = null; System.out.println("Algorithme de signature du certificat : " + cert.getSigAlgName()); byTabHashValue = cert.getSignature(); System.out.println(byTabHashValue.length); System.out.println("Valeur de signature du certif : " + Conversion.bytesToHexString(byTabHashValue)); PublicKey pkPublicKey = cert.getPublicKey(); // déchiffrement de la valeur Cipher cipher = Cipher.getInstance("RSA", "BC"); cipher.init(Cipher.DECRYPT_MODE, pkPublicKey); byte[] byHashDecoded = cipher.doFinal(byTabHashValue); System.out.println("Valeur de signature du certif déchiffrée : " + Conversion.bytesToHexString(byHashDecoded)); } catch(NoSuchProviderException nsprvoe){ System.out.println("Provider inconnu."); nsprvoe.printStackTrace(); } catch(NoSuchAlgorithmException nsae){ System.out.println("Algorithme " + Checksum.SHA1 + " inconnu des providers enregistrés !"); nsae.printStackTrace(); } catch(NoSuchPaddingException nspe){ System.out.println("Pas de padding."); nspe.printStackTrace(); } catch(InvalidKeyException ike){ System.out.println("Clef invalide !"); ike.printStackTrace(); } catch(BadPaddingException bpe){ System.out.println("Mauvais padding !"); bpe.printStackTrace(); } catch(IllegalBlockSizeException ibse){ System.out.println("Taille de bloc illégale !"); ibse.printStackTrace(); }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 /** * Le tableau de byte p_TabBytes passé en paramètre est retourné sous forme de chaine * en représentation Hexadécimale. * * @param p_TabBytes * @return String La représentation hexadécimale de p_TabBytes */ public static String bytesToHexString(byte[] p_TabBytes) { StringBuffer output = new StringBuffer(""); if (p_TabBytes != null) { for (int i = 0; i < p_TabBytes.length; i++) { short intern = (short) (p_TabBytes[i] & (short) 0x00FF); output.append(leftZeroPad(Integer.toHexString(intern), 2)); } } return output.toString().toUpperCase(); } /** * add "0" to the left of the input string until length equals digitNumber value * @param String input * @param int digitNumber final number of digit */ private static String leftZeroPad(String input, int digitNumber) { String out = ""; if (input != null) { out = input; } if (digitNumber > out.length()) { while (out.length() < digitNumber) out = "0" + out; } return out.toUpperCase(); }









Répondre avec citation
Partager