web-dev-qa-db-fra.com

Java Chaîne vers SHA1

J'essaie de créer un convertisseur simple Chaîne vers SHA1 dans Java et voici ce que j'ai ...

public static String toSHA1(byte[] convertme) {
    MessageDigest md = null;
    try {
        md = MessageDigest.getInstance("SHA-1");
    }
    catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
    } 
    return new String(md.digest(convertme));
}

Quand je le passe toSHA1("password".getBytes()), je reçois [�a�ɹ??�%l�3~��. je sais que c'est probablement un correctif d'encodage simple comme UTF-8, mais quelqu'un pourrait-il me dire ce que je devrais faire pour obtenir ce que je veux, à savoir 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8? Ou est-ce que je fais ça complètement faux?

143
Brian

UPDATE
Vous pouvez utiliser Apache Commons Codec (version 1.7+) pour effectuer ce travail à votre place.

DigestUtils.sha1Hex (stringToConvertToSHexRepresentation)

Merci à @ Jon Onstott pour cette suggestion.


Ancienne réponse
Convertissez votre tableau d'octets en chaîne hexadécimale. Comment savoir comment vous dit comment .

return byteArrayToHexString(md.digest(convertme))

et (copié de Real's How To)

public static String byteArrayToHexString(byte[] b) {
  String result = "";
  for (int i=0; i < b.length; i++) {
    result +=
          Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
  }
  return result;
}

BTW, vous pouvez obtenir une représentation plus compacte en utilisant Base64. Apache Commons Codec API 1.4 , a cet utilitaire de Nice pour enlever toute la douleur. voir ici

173
Nishant

C'est ma solution de conversion de chaîne en sha1. Cela fonctionne bien dans mon application Android:

private static String encryptPassword(String password)
{
    String sha1 = "";
    try
    {
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(password.getBytes("UTF-8"));
        sha1 = byteToHex(crypt.digest());
    }
    catch(NoSuchAlgorithmException e)
    {
        e.printStackTrace();
    }
    catch(UnsupportedEncodingException e)
    {
        e.printStackTrace();
    }
    return sha1;
}

private static String byteToHex(final byte[] hash)
{
    Formatter formatter = new Formatter();
    for (byte b : hash)
    {
        formatter.format("%02x", b);
    }
    String result = formatter.toString();
    formatter.close();
    return result;
}
65
petrnohejl

Utilisation de classe de hachage Guava :

Hashing.sha1().hashString( "password", Charsets.UTF_8 ).toString()
53
Jan Schaefer

SHA-1 (et tous les autres algorithmes de hachage) renvoient des données binaires. Cela signifie que (en Java), ils produisent un byte[]. Ce tableau byte ne ne représente pas de caractères spécifiques, ce qui signifie que vous ne pouvez pas simplement le transformer en String comme vous l'avez fait.

Si vous avez besoin d'un String, vous devez alors formater ce byte[] d'une manière pouvant être représentée sous la forme d'un String (sinon, gardez le byte[] autour de vous).

BASE64 ou de simples chaînes hexadécimales (c’est-à-dire que chaque byte est représenté par deux chiffres hexadécimaux) sont deux méthodes courantes de représentation de byte[] arbitraire en tant que caractères imprimables. On dirait que vous essayez de produire une chaîne hexagonale.

Il y a aussi un autre piège: si vous voulez obtenir le SHA-1 d'un Java String, vous devez d'abord convertir ce String en byte[] (comme l’entrée de SHA-1 est également un byte[]). Si vous utilisez simplement myString.getBytes() comme vous l'avez montré, le système utilisera le codage par défaut de la plate-forme et, en tant que tel, dépendra de l'environnement dans lequel vous l'exécutez (par exemple, il pourrait renvoyer des données différentes en fonction du paramètre language/locale défini par votre OS).

Une meilleure solution consiste à spécifier le codage à utiliser pour la conversion String-à -byte[] de la manière suivante: myString.getBytes("UTF-8"). Choisir le format UTF-8 (ou un autre codage pouvant représenter chaque caractère Unicode) est le choix le plus sûr.

30
Joachim Sauer

Utilisez simplement la bibliothèque de codecs Apache commons. Ils ont une classe d’utilité appelée DigestUtils

Pas besoin d'entrer dans les détails.

26
DaTroop

C'est une solution simple qui peut être utilisée lors de la conversion d'une chaîne au format hexadécimal:

private static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {

    MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    crypt.reset();
    crypt.update(password.getBytes("UTF-8"));

    return new BigInteger(1, crypt.digest()).toString(16);
}
24
Nikita Koksharov

Comme mentionné précédemment, utilisez le codec Apache commons. C'est également recommandé par les gars de Spring (voir DigestUtils dans Spring doc). Par exemple.:

DigestUtils.sha1Hex(b);

Je n'utiliserais certainement pas la réponse la mieux notée ici.

18
kazuar

Il ne s’imprime pas correctement car vous devez utiliser le codage Base64. Avec Java 8, vous pouvez encoder en utilisant la classe de codeur Base64 .

public static String toSHA1(byte[] convertme) {
    md = MessageDigest.getInstance("SHA-1");
    return Base64.getEncoder().encodeToString((md.digest(convertme));
}

Résultat

Cela vous donnera le résultat attendu de 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

5
Eduardo Dennis

Représentation en base 64 de SHA1 Hash:

String hashedVal = Base64.getEncoder().encodeToString(DigestUtils.sha1(stringValue.getBytes(Charset.forName("UTF-8"))));
2
PUG

Message Digest (hash) est l'octet [] dans l'octet [] out

Un résumé de message est défini en tant que fonction qui prend un tableau d'octets bruts et retourne un tableau d'octets bruts (aussi appelé byte[]). Par exemple, SHA-1 (algorithme de hachage sécurisé 1) a une taille de résumé de 160 bits ou 20 octets. Les tableaux d'octets bruts ne peuvent généralement pas être interprétés comme encodage de caractères comme TF-8 , car chaque octet dans chaque ordre n'est pas un encodage légal. Donc les convertir en String avec:

new String(md.digest(subject), StandardCharsets.UTF_8)

peut créer des séquences illégales ou avoir des pointeurs de code sur des mappages non définis nicode :

[�a�ɹ??�%l�3~��.

Encodage binaire en texte

Pour cela binaire-à-texte l'encodage est utilisé. Avec les hachages, celui qui est le plus utilisé est le encodage HEX ou Base16 . Fondamentalement, un octet peut avoir la valeur de 0 à 255 (ou -128 à 127 signé), ce qui est équivalent à la représentation HEX de 0x00-0xFF. Par conséquent, hex double la longueur requise de la sortie, ce qui signifie qu'une sortie de 20 octets créera une chaîne hexagonale de 40 caractères, par exemple:

2fd4e1c67a2d28fced849ee1bb76e7391b93eb12

Notez qu'il n'est pas nécessaire d'utiliser le codage hexadécimal. Vous pouvez également utiliser quelque chose comme base64 . Hex est souvent préféré car il est plus facile à lire par les humains et a une longueur de sortie définie sans besoin de remplissage.

Vous pouvez convertir un tableau d'octets en hexadécimal avec la seule fonctionnalité JDK:

new BigInteger(1, token).toString(16)

Notez cependant que BigInteger interprétera un tableau d'octets donné comme un nombre et non comme une chaîne d'octets. Cela signifie que les zéros de tête ne seront pas sortis et que la chaîne résultante peut être inférieure à 40 caractères.

Utilisation de bibliothèques pour encoder en HEX

Vous pouvez maintenant copier et coller une méthode d'octet à hexagonal non testée à partir de Stack Overflow ou utiliser des dépendances massives comme Guava .

Pour avoir une solution adaptée à la plupart des problèmes liés aux octets, j'ai implémenté un utilitaire permettant de gérer ces cas: bytes-Java (Github)

Pour convertir votre tableau d'octets de résumé de message, vous pouvez simplement le faire

String hex = Bytes.wrap(md.digest(subject)).encodeHex();

ou vous pouvez simplement utiliser la fonction de hachage intégrée

String hex =  Bytes.from(subject).hashSha1().encodeHex();
2
patrickf

Cela ne fonctionne pas parce que, lorsque vous appelez String(md.digest(convertme)), vous dites à Java d'interpréter une séquence d'octets cryptés sous forme de chaîne. Ce que vous voulez, c'est convertir les octets en caractères hexadécimaux.

1
Zarkonnen

Convertit un tableau d'octets en chaîne hexagonale.

public static String toSHA1(byte[] convertme) {
    final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
    MessageDigest md = null;
    try {
        md = MessageDigest.getInstance("SHA-1");
    }
    catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    byte[] buf = md.digest(convertme);
    char[] chars = new char[2 * buf.length];
    for (int i = 0; i < buf.length; ++i) {
        chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
        chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
    }
    return new String(chars);
}
0
abhihere