IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Sécurité Java Discussion :

Calculer le MD5/SHA-256 d'un fichier


Sujet :

Sécurité Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 80
    Points
    80
    Par défaut Calculer le MD5/SHA-256 d'un fichier
    Bonjour à tous,
    je n'arrive pas à trouver un exemple de code permettant de calculer le MD5 ou le SHA-256 d'un fichier. J'ai bien trouvé la librairie java.security.MessageDigest mais je ne vois pas comment l'utiliser dans le cadre d'un fichier... Est-ce que quelqu'un a un bout de code ou un lien pour m'aider?

    Merci et bonne journée!

  2. #2
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 085
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 085
    Points : 8 004
    Points
    8 004
    Par défaut
    Avec ceci tu pourra obtenir le MD5 d'un String. A toi de modifier pour lire a partir d'un fichier un String ou carrement les bytes directement...

    Bonne chance.

    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
     
    public class MD5
    {
     
    	/*
    	 * Encode la chaine passé en paramètre avec l’algorithme MD5
    	 * @param key : la chaine à encoder
    	 * @return la valeur (string) hexadécimale sur 32 bits
    	 */
     
    	public static String encode(String key)
    	{
     
    		byte[] uniqueKey = key.getBytes();
    		byte[] hash = null;
     
    		try
    		{
    			// on récupère un objet qui permettra de crypter la chaine
    			hash = MessageDigest.getInstance("MD5").digest(uniqueKey);
    		}
    		catch (NoSuchAlgorithmException e)
    		{
    			throw new Error("no MD5 support in this VM");
    		}
    		StringBuffer hashString = new StringBuffer();
    		for (int i = 0; i < hash.length; ++i)
    		{
    			String hex = Integer.toHexString(hash[i]);
    			if (hex.length() == 1)
    			{
    				hashString.append("0");
    				hashString.append(hex.charAt(hex.length() - 1));
    			}
    			else
    			{
    				hashString.append(hex.substring(hex.length() - 2));
    			}
    		}
    		return hashString.toString();
    	}
     
    	// méthode principale
     
    	public static void main(String[] args)
    	{
    		System.out.println("La chaine : P@ssWord, cryptée via MD5 donne : " + MD5.encode("P@ssWord"));
    	}
     
    }

  3. #3
    Membre éprouvé Avatar de Jidefix
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    742
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : Septembre 2006
    Messages : 742
    Points : 1 154
    Points
    1 154
    Par défaut
    Par ailleurs j'ai lu là:
    http://www.developpez.net/forums/d19...r-octet-octet/
    que tu n'étais pas obligé de lire le fichier entier pour le hasher (en effet si le fichier est gros genre plusieurs centaines de MO, ta RAM risque de prendre cher)

    Ils parlent d'un algo en C, mais avec un peu d'effort c'est surement transposable en java

    Good luck!

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 80
    Points
    80
    Par défaut
    Mouais mouais... je me suis mis depuis peu au Java. Je viens du monde PHP où tout est si facile. Je pensais que Java s'en approchait du point de vue des fonctions prêtes à l'emploi, mais c'est quand même pas comparable.

    Enfin, ça fait un peu plus travailler les bases. Je suis en train de m'inspirer de l'exemple de wax78. Je vous tiens au courant quand j'ai fini...



  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 80
    Points
    80
    Par défaut
    Ben finalement, il suffit de réfléchir un peu et de comprendre ce qui est écrit... et ça s'adapte assez bien. En fait, j'ai trouvé un autre exemple sur le net: https://svn.lal.in2p3.fr/projects/XW...putStream.java et https://svn.lal.in2p3.fr/projects/XW...ommon/MD5.java

    Voilà ce que j'en ai fait:
    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
     
    public static String strEmpreinte(String _strPath, String _strAlgo) throws Exception {
     
        byte[] abBuffer = new byte[65536];
        int iNbRead;
     
        InputStream isF = new BufferedInputStream(new FileInputStream(_strPath));
        java.security.MessageDigest ODigest = java.security.MessageDigest.getInstance(_strAlgo);
        while ((iNbRead = isF.read(abBuffer)) != -1) {
          ODigest.update(abBuffer, 0, iNbRead);
        }
     
        char[] acHexa = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',};
     
        byte[] abDigest = ODigest.digest();
        char acRetour[] = new char[abDigest.length * 2];
        for (int i = 0, x = 0; i < abDigest.length; i++) {
          acRetour[x++] = acHexa[(abDigest[i] >>> 4) & 0xf];
          acRetour[x++] = acHexa[abDigest[i] & 0xf];
        }
        return new String(acRetour);
     
    }
    Bon, c'est un peu sauvage quant à la gestion des exceptions, mais c'est à vous de voir pour rendre un peu plus clean.
    Merci à tous pour vos suggestions ... enfin, surtout Jidefix et wax78 .
    arobase plus!

  6. #6
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 085
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 085
    Points : 8 004
    Points
    8 004
    Par défaut
    Mais de rien, si nous avons pu ne serait-ce que te diriger vers une solution, cela est parfait

  7. #7
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    salut a tous,

    j'ai besoin d'utiliser l'algo SHA-256. j'étais tombé sur ce site là avant : http://www.owasp.org/index.php/Hashing_Java

    ça va peut-etre vous sembler evident quand vous lirez le premier exemple mais moi ça m'a étonné de voir qu'en faisant comme il est dit, j'obtiens le même haché pour deux chaines qui sont relativement similaires et même pire, le même haché en utilisant SHA-1 et SHA-256 .

    en adaptant le code de wax78, tout rentre dans l'ordre et j'obtiens deux hachés différents pour deux chaines différentes... logique !

    sauf que j'ai peur de ne pas trop comprendre ce qui se passe à partir du moment où il utilise StringBuffer et la boucle sur les bytes de hach. quelqu'un peut m'expliquer ça en gros?
    et puis, est ce que ça sert a quelque chose d'utiliser la méthode reset() avant digest()?

    ps : je suis plutôt débutant en java, vous l'aurez surement remarqué

  8. #8
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    bonjour,
    apparemment personne n'a eu le temps de me répondre pendant le week-end. Avec un peu de chance quelqu'un passera par là ce matin qui sait...
    et sinon au fait comment on fait pour revenir de la chaine hexa au tableau de bytes svp ?

  9. #9
    Invité
    Invité(e)
    Par défaut
    Salut,
    Tu peux nous donner ton code (il y en a plusieurs sur ton lien) et les entrées/résultats obtenus ? Ca me parait bizarre ce que tu dis, de trouver une collision aussi facilement comme ca avec deux chaines qui se ressemblent...
    Pour HSA-1 et SHA-256 c'est encore plus bizarre que les résultats des deux algorithmes n'ont pas la même taille (160 bits pour SHA-1 et 256 pour SHA-256)
    Bref donne ici le code exact ainsi que tes tests
    A plus

  10. #10
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    non en fait mon erreur vient de mon interprétation du tableau de byte retourné. d'ailleurs je ne comprend toujours pas a quoi correspond la chaine qu'on obtient en faisant un system.out d'un tableau de byte. jusque là je n'utilisais que les types classique int, String, etc.

    en fait là j'ai besoin d'enregistrer le byte[] dans une base de données et pouvoir le réutiliser après. la conversion en une chaine hexa qu'a donné wax me convient mais je n'arrive pas a revenir a mon byte[] initial.

    j'ai vu qu'avec : String hex = Integer.toHexString(byte[i])
    - les bytes positifs donnent une chaine "xx" que je peut reconvertir en byte facilement avec Byte.parseByte("xx", 16)
    - les bytes negatifs donnent une chaine "ffffffxx".

    je suis en ce moment même en train d'essayer de trouver comment revenir au byte pour les négatifs. une idée? ou peut etre un autre moyen de revenir de la chaine générée avec le code de wax sans avoir a analyser byte par byte et de savoir le signe de chaque byte.

    merci d'avance. et navré si je pose des questions betes. j'apprend sur le tas comme la plupart des internautes

  11. #11
    Invité
    Invité(e)
    Par défaut
    En fait la chaine retournée est probablement encodée en Base64 (peut-on la voir ?). Pour ce faire, tu as des bibliothèques qui font la conversion byte[] -> String et réciproquement (Apache commons par exemple en a une)

    la méthode System.out.println() appliquée à un objet appelle sa méthode toString qui apr défaute retourne le type et l'adresse en mémoire de l'objet, si elle n'est pas surchargée. Pour un tableau d'octets tu auras
    [quote]
    [B@e48e1b
    [/code]
    Pour avopir une représentation compréhenseible utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Arrays.toString(tonTableau);

  12. #12
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    la méthode System.out.println() appliquée à un objet appelle sa méthode toString qui apr défaute retourne le type et l'adresse en mémoire de l'objet, si elle n'est pas surchargée. Pour un tableau d'octets tu auras
    [B@e48e1b
    c'était effectivement ça. merci pour l'explication.

    En fait la chaine retournée est probablement encodée en Base64 (peut-on la voir ?)
    quelle chaine exactement? (qu'il n y ait pas de confusion)

    sinon comme j'ai dit la représentation en hexadécimal me convient parfaitement, seulement je n'ai pas réussi à retrouver mes bytes de départ à partir de la chaine. pourrais-tu (ou quelqu'un d'autres y a pas de souci ) m'aider? je rappelle que j'utilise le code de wax suivant :

    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
     
    // code quelconque
    byte [] hash = // code quelconque
    StringBuffer hashString = new StringBuffer();
    		for (int i = 0; i < hash.length; ++i)
    		{
    			String hex = Integer.toHexString(hash[i]);
    			if (hex.length() == 1)
    			{
    				hashString.append("0");
    				hashString.append(hex.charAt(hex.length() - 1));
    			}
    			else
    			{
    				hashString.append(hex.substring(hex.length() - 2));
    			}
    		}
    j'obtiens par exemple : 09be1ca775160873

    si j'applique un Byte.parseByte("cc", 16) à chaque paire de caractères de la chaine j'ai une erreur. En regardant de plus près j'ai remarqué que si le byte de départ est positif, ça donne une chaine "xx" qui ne pose aucun problème avec Byte.parseByte("xx"). par contre, un byte négatif donne une chaine"FFFFFFxx" avec laquelle je n'arrive pas a faire le chemin inverse, ni avec Byte.parseByte("FFFFFFxx") ni Byte.parseByte("xx").

    encore merci

  13. #13
    Invité
    Invité(e)
    Par défaut
    Oups pardon oui j'avais mal lu...
    Sinon ouais pourquoi ne pas utiliser Base64 ? C'est assez standard comme encodage de tableau d'octet, l'algo est simple et très souvent utilisé (surtout en cryptographie), et donc les bibliothèques existantes font les conversions à double sens byte[] <-> String

  14. #14
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    mes bytes sont compris entre -128 et 127 non? et d'après une recherche rapide il me semble que pour Base64 les valeur sont entre 0 et 63

  15. #15
    Invité
    Invité(e)
    Par défaut
    Non ta chaine sera composée de 64 caractéres différents, mais ta petite recherche a dû aussi te montrer que tu regroupes les bits de tes octets pour avoir tout ca, bref, fais moi confiance, la base64 ca marche pourc e que tu veux, c'est sûr éprouvé portable, simple, rien à faire, bref ca marche très bien
    Regarde un lien tout bête avec un exemple où on comprend bien

  16. #16
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    autant pour moi, j'ai zappé l'exemple et donc la partie ou on passe par le binaire et la transformation en groupe de 6 bits

    mais bon entre temps j'ai trouvé une petite solution bricolée à mon problème : avant de convertir en hexa je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int tmp = monByte + 128
    ce qui fait que pour le sens inverse je fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tabByte[i] = (byte) (Integer.parseInt("xx", 16) - 128)
    ça marche mais je n'ai fais que contourner mon problème. le Base64 semble convenir plus si je réfléchi à long terme donc si j'ai le temps je verrai ça.
    merci !

    le code "complet" au cas où, ça peut dépanner quelqu'un (je réutilise le code fourni par wax, désolé pour les droits d'auteur) :
    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
     
    // code quelconque
    byte [] hash = // code quelconque
    StringBuffer hashString = new StringBuffer();
    		for (int i = 0; i < hash.length; ++i)
    		{
                            int tmp = hash[i] + 128 ;
    			String hex = Integer.toHexString(hash[i]);
    			if (hex.length() == 1)
    			{
    				hashString.append("0");
    				hashString.append(hex.charAt(hex.length() - 1));
    			}
    			else
    			{
    				hashString.append(hex.substring(hex.length() - 2));
    			}
    		}
     
    in n = hash.length // le nombre de bytes quoi
     
    byte [] bytes = new byte[n] ;
    String octetChaine ;
    for(int i = 0 ; i < hashString.length() ; i = i + 2) {
          octetChaine = hashString.substring(i, i + 2) ;
          int tmp = Integer.parseInt(octetChaine, 16)  ;
          bytes[i/2] = (byte) (tmp - 128) ;
    }
     
    // verification 
     
           System.out.println("tab1 : " + Arrays.toString(hash));
           System.out.println("tab1 : " + Arrays.toString(bytes));

  17. #17
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    salut,
    George7,
    j'ai finalement téléchargé la bibliothèque commons que tu m'as suggéré. en fait le codage Base64 ne correspond pas à ce que je cherchais, puisqu'il me permet d'obtenir un tableau de bytes à partir d'un tableau de bytes. moi je voulais trouver un moyen d'avoir une chaine a partir d'un tableau de bytes. par contre, la classe Hex de cette bibliothèque fait ça. mais comme ma fonction à moi marche très bien je préfère utiliser mon travail.
    voila

  18. #18
    Invité
    Invité(e)
    Par défaut
    Salut,
    Oui au temps pour moi après petit tour sur la javadoc, cette bibliothèque retourne aussi un tableau d'octets. C'est la première fois que je vois ca... Toutes les méthodes que j'avais vues pour le moment retournaient bien une chaine. Ceci dit le tableau d'octets retourné ne contient que les 64 caractères autorisés, ca doit être de l'ASCII tout bête donc il est possible qu'avaec un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    new String(monTableauRetourné);
    Ca devrait aller

  19. #19
    Nouveau membre du Club
    Inscrit en
    Mars 2009
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 34
    Points : 30
    Points
    30
    Par défaut
    bonjour,

    merci pour ton nième réponse George7. mais j'ai peur de ne plus trop avoir le temps de chercher une autre méthode.
    merci quand même, si un jour ma fonction me pose problème je verrai ce que tu me propose.

    EDIT : quelqu'un aurait une idée pour tester si une chaine passée en paramètre est bien une hexa?

  20. #20
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 778
    Points
    5 778
    Par défaut
    Citation Envoyé par boitaRytm Voir le message
    quelqu'un aurait une idée pour tester si une chaine passée en paramètre est bien une hexa?
    Avec la méthode Integer.parseInt()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    try {
        int value = Integer.parseInt(string, 16);
    } catch(NumberFormatException ex) {
        System.out.println("chaine invalide");
    }

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Calcul du md5 de millions de fichiers
    Par Sennad dans le forum Général Java
    Réponses: 94
    Dernier message: 18/09/2014, 18h15
  2. comment calculer le md5 du contenu d'un fichier
    Par c.plus.plus dans le forum Débuter
    Réponses: 6
    Dernier message: 01/01/2012, 18h54
  3. Hashage SHA - 256
    Par K-Kaï dans le forum Sécurité
    Réponses: 6
    Dernier message: 26/04/2010, 18h38
  4. Calculer le MD5 d'un fichier octet par octet
    Par bouazza92 dans le forum C
    Réponses: 5
    Dernier message: 09/08/2006, 21h39
  5. Réponses: 6
    Dernier message: 08/01/2006, 13h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo