Java calcule la représentation hexadécimale d’un résumé SHA-1 d’une chaîne

Je stocke le mot de passe utilisateur sur la firebase database en tant que hachage sha1.

Malheureusement, je reçois des réponses étranges.

Je stocke la chaîne comme ceci:

MessageDigest cript = MessageDigest.getInstance("SHA-1"); cript.reset(); cript.update(userPass.getBytes("utf8")); this.password = new Ssortingng(cript.digest()); 

Je voulais quelque chose comme ça ->

aff -> “0c05aa56405c447e6678b7f3127febde5c3a9238”

plutôt que

aff -> V @ \ D ~ fx : 8

Cela se produit car cript.digest () renvoie un tableau d’octets que vous essayez d’imprimer en tant que chaîne de caractères. Vous voulez le convertir en chaîne Hex imprimable.

Solution facile: utilisez la bibliothèque de codecs commun Apache:

 Ssortingng password = new Ssortingng(Hex.encodeHex(cript.digest()), CharSet.forName("UTF-8")); 

Utilisation de la bibliothèque de codecs communs apache:

 DigestUtils.sha1Hex("aff") 

Le résultat est 0c05aa56405c447e6678b7f3127febde5c3a9238

C’est tout 🙂

Une itération d’un algorithme de hachage n’est pas sécurisée. C’est trop rapide. Vous devez effectuer le renforcement des touches en répétant le hachage plusieurs fois.

De plus, vous ne saluez pas le mot de passe. Cela crée une vulnérabilité aux dictionnaires pré-calculés, comme les “tables arc-en-ciel”.

Au lieu d’essayer de déployer votre propre code (ou d’utiliser certains logiciels tiers) pour le faire correctement, vous pouvez utiliser le code intégré à l’environnement d’exécution Java. Voir cette réponse pour plus de détails.

Une fois le mot de passe haché correctement, vous aurez un byte[] . Un moyen simple de convertir cette Ssortingng hexadécimale est d’ BigInteger classe BigInteger :

 Ssortingng passwordHash = new BigInteger(1, cript.digest()).toSsortingng(16); 

Si vous voulez vous assurer que votre chaîne a toujours 40 caractères, vous devrez peut-être faire un remplissage avec des zéros à gauche (vous pouvez le faire avec Ssortingng.format() .)

Si vous ne souhaitez pas append de dépendances supplémentaires à votre projet, vous pouvez également utiliser

 MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(message.getBytes("utf8")); byte[] digestBytes = digest.digest(); Ssortingng digestStr = javax.xml.bind.DatatypeConverter.printHexBinary(digestBytes); 

La méthode crypt.digest () renvoie un octet []. Ce tableau d’octets est la sum SHA-1 correcte, mais les hachages cryptographiques sont généralement affichés aux humains sous forme hexadécimale. Chaque octet de votre hachage produira deux chiffres hexadécimaux.

Pour convertir en toute sécurité un octet en hexadécimal, utilisez ceci:

 // %1$ == arg 1 // 02 == pad with 0's // x == convert to hex Ssortingng hex = Ssortingng.format("%1$02x", byteValue); 

Cet extrait de code peut être utilisé pour convertir un caractère en hexadécimal :

 /* * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. * * Redissortingbution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redissortingbutions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redissortingbutions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the dissortingbution. * * - Neither the name of Oracle or the names of its * consortingbutors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.*; public class UnicodeFormatter { static public Ssortingng byteToHex(byte b) { // Returns hex Ssortingng representation of byte b char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] }; return new Ssortingng(array); } static public Ssortingng charToHex(char c) { // Returns hex Ssortingng representation of char c byte hi = (byte) (c >>> 8); byte lo = (byte) (c & 0xff); return byteToHex(hi) + byteToHex(lo); } } 

Notez que travailler avec des octets en Java est très sujet aux erreurs. Je vérifierais tout et testerais aussi des cas étranges.

Aussi, vous devriez envisager d’utiliser quelque chose de plus fort que SHA-1. http://csrc.nist.gov/groups/ST/hash/statement.html

Si vous utilisez Spring, c’est assez simple:

 MessageDigestPasswordEncoder encoder = new MessageDigestPasswordEncoder("SHA-1"); Ssortingng hash = encoder.encodePassword(password, "salt goes here"); 

Il n’y a pas que de simples algorithmes de hachage standard impliqués dans le stockage des mots de passe irréversibles.

  1. Effectuez plusieurs rounds pour ralentir les attaques en force
  2. Utiliser un “sel” par enregistrement comme entrée dans l’algorithme de hachage en plus du mot de passe pour rendre les attaques par dictionnaire moins réalisables et éviter les collisions de sortie.
  3. Utilisez “pepper”, un paramètre de configuration d’application en entrée de l’algorithme de hachage pour rendre une firebase database volée avec un “piment” inconnu.
  4. Tapez l’entrée pour éviter les faiblesses dans certains algorithmes de hachage, par exemple lorsque vous pouvez append un caractère au mot de passe sans connaître le mot de passe, en modifiant le hachage.

Pour plus d’informations, voir par exemple

Vous pouvez également utiliser une méthode http://en.wikipedia.org/wiki/Password-authenticated_key_agreement pour éviter de transmettre le mot de passe en texte clair au serveur.

digest () renvoie un tableau d’octets que vous convertissez en une chaîne à l’aide du codage par défaut. Ce que vous voulez faire, c’est encoder en base64.

Pour utiliser UTF-8, procédez comme suit:

 userPass.getBytes("UTF-8"); 

Et pour obtenir une chaîne Base64 du condensé, vous pouvez faire quelque chose comme ceci:

 this.password = new BASE64Encoder().encode(cript.digest()); 

Puisque MessageDigest.digest() renvoie un tableau d’octets, vous pouvez le convertir en Ssortingng à l’aide de Hex Encoding (plus simple) d’Apache.

Par exemple

 this.password = Hex.encodeHexSsortingng(cript.digest()); 

Que diriez-vous de convertir un octet [] en base64?

  byte[] chkSumBytArr = digest.digest(); BASE64Encoder encoder = new BASE64Encoder(); Ssortingng base64CheckSum = encoder.encode(chkSumBytArr); 

vous pouvez aussi utiliser ce code (depuis crackstation.net):

private static Ssortingng toHex(byte[] array) { BigInteger bi = new BigInteger(1, array); Ssortingng hex = bi.toSsortingng(16); int paddingLength = (array.length * 2) - hex.length(); if(paddingLength > 0) return Ssortingng.format("%0" + paddingLength + "d", 0) + hex; else return hex; }

Vous pouvez utiliser Google Guava :

Maven:

  guava com.google.guava 14.0.1  

Échantillon:

 HashFunction hashFunction = Hashing.sha1(); HashCode hashCode = hashFunction.newHasher() .putSsortingng(password,Charsets.UTF_8) .hash(); Ssortingng hash = BaseEncoding.base16().lowerCase().encode(hashCode.asBytes()); 
  MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); messageDigest.reset(); messageDigest.update(password.getBytes("UTF-8")); Ssortingng sha1Ssortingng = new BigInteger(1, messageDigest.digest()).toSsortingng(16); 

Vous devez d’abord encoder le résultat en hexadécimal. MessageDigest renvoie un hachage “brut” plutôt qu’un hachage lisible par l’homme.

Modifier:

@thejh a fourni un lien vers le code qui devrait fonctionner. Personnellement, je suggère d’utiliser soit Bouncycastle ou Apache Commons Codec pour faire le travail. Bouncycastle serait bien si vous voulez faire d’autres opérations liées à la cryptographie.