Wie kann ich ein Passwort in Java hashen?

176

Ich muss Passwörter für die Speicherung in einer Datenbank hashen. Wie kann ich das in Java machen?

Ich hatte gehofft, das Klartext-Passwort zu nehmen, ein zufälliges Salt hinzuzufügen und dann das Salt und das Hash-Passwort in der Datenbank zu speichern.

Wenn sich ein Benutzer anmelden wollte, konnte ich sein übermitteltes Passwort verwenden, das zufällige Salz aus seinen Kontoinformationen hinzufügen, es hashen und prüfen, ob es dem gespeicherten Hash-Passwort mit seinen Kontoinformationen entspricht.

Chris Dutrow
quelle
11
@YGL Dies ist heutzutage eigentlich keine Rekombination, da GPU-Angriffe so billig sind, dass die SHA-Familie selbst mit Salz eine sehr schlechte Wahl für das Hashing von Passwörtern (zu schnell) ist. Verwenden Sie bcrypt, scrypt oder PBKDF2
Eran Medan
11
Warum wurde diese Frage geschlossen? Dies ist eine Frage für ein echtes technisches Problem, und die Antworten sind von unschätzbarem Wert. Das OP fragt nicht nach einer Bibliothek, sondern nach der Lösung des technischen Problems.
stackoverflowuser2010
12
Einfach unglaublich. Diese Frage hat 52 positive Stimmen, und jemand beschließt, sie als "Off-Topic" zu schließen.
stackoverflowuser2010
1
Ja, ich habe auf Meta über diese Ausgabe von Schließungen geschrieben, wurde aber ziemlich schlimm verprügelt.
Chris Dutrow
8
Diese Frage sollte erneut geöffnet werden. Es ist eine Frage, wie man ein Programm schreibt, um das beschriebene Problem (Passwortauthentifizierung) mit einer Shortcode-Lösung zu lösen. Das Auslösen des Auslöseworts "Bibliothek" rechtfertigt nicht das reflexive Schließen einer Frage. Er fragt nicht nach einer Bibliotheksempfehlung, sondern nach dem Hashing von Passwörtern. Edit: Dort behoben.
Erickson

Antworten:

155

Sie können dazu tatsächlich eine in die Java-Laufzeit integrierte Funktion verwenden. Das SunJCE in Java 6 unterstützt PBKDF2, einen guten Algorithmus für das Passwort-Hashing.

byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 128);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = f.generateSecret(spec).getEncoded();
Base64.Encoder enc = Base64.getEncoder();
System.out.printf("salt: %s%n", enc.encodeToString(salt));
System.out.printf("hash: %s%n", enc.encodeToString(hash));

Hier ist eine Dienstprogrammklasse, die Sie für die PBKDF2-Kennwortauthentifizierung verwenden können:

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

/**
 * Hash passwords for storage, and test passwords against password tokens.
 * 
 * Instances of this class can be used concurrently by multiple threads.
 *  
 * @author erickson
 * @see <a href="http://stackoverflow.com/a/2861125/3474">StackOverflow</a>
 */
public final class PasswordAuthentication
{

  /**
   * Each token produced by this class uses this identifier as a prefix.
   */
  public static final String ID = "$31$";

  /**
   * The minimum recommended cost, used by default
   */
  public static final int DEFAULT_COST = 16;

  private static final String ALGORITHM = "PBKDF2WithHmacSHA1";

  private static final int SIZE = 128;

  private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");

  private final SecureRandom random;

  private final int cost;

  public PasswordAuthentication()
  {
    this(DEFAULT_COST);
  }

  /**
   * Create a password manager with a specified cost
   * 
   * @param cost the exponential computational cost of hashing a password, 0 to 30
   */
  public PasswordAuthentication(int cost)
  {
    iterations(cost); /* Validate cost */
    this.cost = cost;
    this.random = new SecureRandom();
  }

  private static int iterations(int cost)
  {
    if ((cost < 0) || (cost > 30))
      throw new IllegalArgumentException("cost: " + cost);
    return 1 << cost;
  }

  /**
   * Hash a password for storage.
   * 
   * @return a secure authentication token to be stored for later authentication 
   */
  public String hash(char[] password)
  {
    byte[] salt = new byte[SIZE / 8];
    random.nextBytes(salt);
    byte[] dk = pbkdf2(password, salt, 1 << cost);
    byte[] hash = new byte[salt.length + dk.length];
    System.arraycopy(salt, 0, hash, 0, salt.length);
    System.arraycopy(dk, 0, hash, salt.length, dk.length);
    Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
    return ID + cost + '$' + enc.encodeToString(hash);
  }

  /**
   * Authenticate with a password and a stored password token.
   * 
   * @return true if the password and token match
   */
  public boolean authenticate(char[] password, String token)
  {
    Matcher m = layout.matcher(token);
    if (!m.matches())
      throw new IllegalArgumentException("Invalid token format");
    int iterations = iterations(Integer.parseInt(m.group(1)));
    byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
    byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
    byte[] check = pbkdf2(password, salt, iterations);
    int zero = 0;
    for (int idx = 0; idx < check.length; ++idx)
      zero |= hash[salt.length + idx] ^ check[idx];
    return zero == 0;
  }

  private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
  {
    KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
    try {
      SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
      return f.generateSecret(spec).getEncoded();
    }
    catch (NoSuchAlgorithmException ex) {
      throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
    }
    catch (InvalidKeySpecException ex) {
      throw new IllegalStateException("Invalid SecretKeyFactory", ex);
    }
  }

  /**
   * Hash a password in an immutable {@code String}. 
   * 
   * <p>Passwords should be stored in a {@code char[]} so that it can be filled 
   * with zeros after use instead of lingering on the heap and elsewhere.
   * 
   * @deprecated Use {@link #hash(char[])} instead
   */
  @Deprecated
  public String hash(String password)
  {
    return hash(password.toCharArray());
  }

  /**
   * Authenticate with a password in an immutable {@code String} and a stored 
   * password token. 
   * 
   * @deprecated Use {@link #authenticate(char[],String)} instead.
   * @see #hash(String)
   */
  @Deprecated
  public boolean authenticate(String password, String token)
  {
    return authenticate(password.toCharArray(), token);
  }

}
erickson
quelle
11
Möglicherweise möchten Sie bei der Konvertierung von Byte in Hex etwas vorsichtig sein, wenn BigInteger: führende Nullen entfernt werden. Das ist für ein schnelles Debuggen in Ordnung, aber ich habe aufgrund dieses Effekts Fehler im Produktionscode gesehen.
Thomas Pornin
24
@ thomas-pornins Highlights, warum wir eine Bibliothek brauchen , keinen Codeblock, der fast da ist. Beängstigend, dass die akzeptierte Antwort die Frage zu einem so wichtigen Thema nicht beantwortet.
Nilzor
9
Verwenden Sie den Algorithmus PBKDF2WithHmacSHA512 ab Java 8. Er ist etwas stärker.
iwan.z
1
Beachten Sie , bestehende ALGs nicht in späteren Versionen gelöscht: java_4: PBEWithMD5AndDES, DESede, DIE java_5 / 6/7: PBKDF2WithHmacSHA1, PBE (nur in Java 5), PBEWithSHA1AndRC2_40, PBEWithSHA1And, PBEWithMD5AndTriple java_8: PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA512AndAES_128, RC4_40, PBKDF2WithHmacSHA256 , PBEWithHmacSHA1AndAES_128, RC4_128, PBKDF2WithHmacSHA224, PBEWithHmacSHA256AndAES_256, RC2_128, PBEWithHmacSHA224AndAES_256, PBEWithHmacSHA384AndAES_256, PBEWithHmacSHA512AndAES_256, PBKDF2WithHmacSHA512, PBEWithHmacSHA256AndAES_128, PBKDF2WithHmacSHA384, PBEWithHmacSHA1AndAES_256
iwan.z
4
@TheTosters Ja, die Ausführungszeit für falsche Passwörter ist länger . Insbesondere benötigen falsche Passwörter dieselbe Zeit wie korrekte Passwörter. Es verhindert Timing-Angriffe, obwohl ich zugeben muss , dass ich mir in diesem Fall keinen praktischen Weg vorstellen kann, eine solche Sicherheitsanfälligkeit auszunutzen. Aber du schneidest keine Ecken. Nur weil ich es nicht sehen kann, heißt das nicht, dass ein verschlagener Verstand es nicht tun wird.
Erickson
97

Hier ist eine vollständige Implementierung mit zwei Methoden, die genau das tun, was Sie wollen:

String getSaltedHash(String password)
boolean checkPassword(String password, String stored)

Der Punkt ist, dass die Passwörter auch dann sicher sind, wenn ein Angreifer Zugriff auf Ihre Datenbank und den Quellcode erhält.

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import org.apache.commons.codec.binary.Base64;

public class Password {
    // The higher the number of iterations the more 
    // expensive computing the hash is for us and
    // also for an attacker.
    private static final int iterations = 20*1000;
    private static final int saltLen = 32;
    private static final int desiredKeyLen = 256;

    /** Computes a salted PBKDF2 hash of given plaintext password
        suitable for storing in a database. 
        Empty passwords are not supported. */
    public static String getSaltedHash(String password) throws Exception {
        byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
        // store the salt with the password
        return Base64.encodeBase64String(salt) + "$" + hash(password, salt);
    }

    /** Checks whether given plaintext password corresponds 
        to a stored salted hash of the password. */
    public static boolean check(String password, String stored) throws Exception{
        String[] saltAndHash = stored.split("\\$");
        if (saltAndHash.length != 2) {
            throw new IllegalStateException(
                "The stored password must have the form 'salt$hash'");
        }
        String hashOfInput = hash(password, Base64.decodeBase64(saltAndHash[0]));
        return hashOfInput.equals(saltAndHash[1]);
    }

    // using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
    // cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
    private static String hash(String password, byte[] salt) throws Exception {
        if (password == null || password.length() == 0)
            throw new IllegalArgumentException("Empty passwords are not supported.");
        SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        SecretKey key = f.generateSecret(new PBEKeySpec(
            password.toCharArray(), salt, iterations, desiredKeyLen));
        return Base64.encodeBase64String(key.getEncoded());
    }
}

Wir lagern 'salt$iterated_hash(password, salt)'. Das Salt besteht aus 32 zufälligen Bytes. Wenn zwei verschiedene Personen dasselbe Passwort wählen, sehen die gespeicherten Passwörter immer noch unterschiedlich aus.

Die iterated_hash, die im Grunde hash(hash(hash(... hash(password, salt) ...)))macht es sehr teuer für einen potentiellen Angreifer, der Zugriff auf die Datenbank zu erratende Kennwörter hat, Hash sie und schauen Hashes in der Datenbank. Sie müssen dies iterated_hashjedes Mal berechnen, wenn sich ein Benutzer anmeldet, aber es kostet Sie nicht so viel im Vergleich zu dem Angreifer, der fast 100% seiner Zeit damit verbringt, Hashes zu berechnen.

Martin Konicek
quelle
14
Tut mir leid, aber warum sollte ich dies einer vorhandenen Bibliothek vorziehen? Eine Bibliothek hat wahrscheinlich eine höhere Chance, gründlich überprüft zu werden. Ich bezweifle, dass jede der 14 Up-Votes den Code auf Probleme analysiert hat.
Joachim Sauer
2
@JoachimSauer Dies ist im Wesentlichen nur die Verwendung einer Bibliothek (javax.crypto), aber Sie haben Recht - leere Passwörter werden nicht unterstützt. Es wurde eine Ausnahme hinzugefügt, um sie explizit zu machen. Vielen Dank!
Martin Konicek
3
Sie sollten wahrscheinlich die Methodensignaturen in char[] passwordanstelle von ändern String password.
Assylias
2
Obwohl es scheint, dass die Referenz nicht einstimmig angenommen wird. Siehe auch dies: security.stackexchange.com/a/20369/12614
Assylias
3
Sind Sie sicher, dass .equals () in Strings nicht kurzschließt (dh: Stoppen Sie die Schleife, wenn zwei nicht gleiche Bytes gefunden werden)? In diesem Fall besteht die Gefahr, dass bei einem Timing-Angriff Informationen zum Kennwort-Hash verloren gehen.
Bobpoekert
28

BCrypt ist eine sehr gute Bibliothek, und es gibt einen Java-Port davon.

Michael Borgwardt
quelle
2
bcrypt saugt mit seinen zufälligen Salzen
chrisapotek
1
Dies ist sehr einfach zu bedienen
Ankur
7

Sie können Hashes mit berechnen MessageDigest, dies ist jedoch in Bezug auf die Sicherheit falsch. Hashes dürfen nicht zum Speichern von Passwörtern verwendet werden, da sie leicht zerbrechlich sind.

Sie sollten einen anderen Algorithmus wie bcrypt, PBKDF2 und scrypt verwenden, um Ihre Passwörter zu speichern. Siehe hier .

Bozho
quelle
3
Wie würden Sie das Passwort beim Anmelden hashen, ohne Salt in der Datenbank zu speichern?
ZZ Coder
9
Die Verwendung des Benutzernamens als Salz ist kein schwerwiegender Fehler, aber bei weitem nicht so gut wie die Verwendung eines Salzes aus einem kryptografischen RNG. Und es ist absolut kein Problem, das Salz in der Datenbank zu speichern. Das Salz ist nicht geheim.
erickson
1
Würden der Benutzername und die E-Mail-Adresse nicht auch in der Datenbank gespeichert?
Chris Dutrow
@ZZ Coder, @erickson richtig, ich habe irgendwie angenommen, dass es ein Salz für alle Passwörter sein wird, was zu einer leicht berechenbaren Regenbogentabelle führen würde.
Bozho
13
Ein Problem bei der Verwendung des Benutzernamens (oder einer anderen ID wie E-Mail) als Salt besteht darin, dass Sie die ID nicht ändern können, ohne dass der Benutzer auch ein neues Kennwort festgelegt hat.
Lawrence Dol
6

Sie können die Implementierung der von OWASP beschriebenen Shiro- Bibliothek (ehemals JSecurity ) verwenden .

Es sieht auch so aus, als hätte die JASYPT-Bibliothek ein ähnliches Dienstprogramm .

laz
quelle
Das ist eigentlich was ich benutzt habe. Da wir uns jedoch entschieden haben, Shiro nicht zu verwenden, gab es einige Bedenken hinsichtlich der Ineffizienz, die gesamte Shiro-Bibliothek nur für dieses eine Paket einschließen zu müssen.
Chris Dutrow
Ich kenne keine Bibliothek, die nur aus einem Passwort-Hashing-Dienstprogramm besteht. Sie sind wahrscheinlich besser dran, Ihre eigenen zu rollen, wenn Abhängigkeiten ein Problem darstellen. Die Antwort von erickson sieht für mich ziemlich gut aus. Oder kopieren Sie einfach den Code von dem OWASP-Link, auf den ich verwiesen habe, wenn Sie SHA lieber auf sichere Weise verwenden möchten.
Laz
6

Zusätzlich zu bcrypt und PBKDF2, die in anderen Antworten erwähnt wurden, würde ich empfehlen, sich scrypt anzusehen

MD5 und SHA-1 werden nicht empfohlen, da sie relativ schnell sind. Wenn Sie also verteiltes Computing mit "Miete pro Stunde" (z. B. EC2) oder eine moderne High-End-GPU verwenden, können Sie Passwörter mithilfe von Brute-Force- / Wörterbuchangriffen zu relativ geringen Kosten und zu angemessenen Preisen "knacken" Zeit.

Wenn Sie sie verwenden müssen, wiederholen Sie den Algorithmus mindestens eine vordefinierte signifikante Anzahl von Malen (1000+).

Eran Medan
quelle
6

Stimmen Sie Erickson voll und ganz zu, dass PBKDF2 die Antwort ist.

Wenn Sie diese Option nicht haben oder nur einen Hash verwenden müssen, ist Apache Commons DigestUtils viel einfacher als der richtige JCE-Code: https://commons.apache.org/proper/commons-codec/apidocs/org/apache /commons/codec/digest/DigestUtils.html

Wenn Sie einen Hash verwenden, wählen Sie sha256 oder sha512. Diese Seite enthält gute Empfehlungen zur Behandlung und zum Hashing von Passwörtern (beachten Sie, dass für die Behandlung von Passwörtern kein Hashing empfohlen wird): http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html

David Carboni
quelle
Es ist erwähnenswert, dass SHA512 nicht besser ist als SHA256 (für diesen Zweck), nur weil die Anzahl größer ist.
Azsgy
4

Obwohl die NIST-Empfehlung PBKDF2 bereits erwähnt wurde, möchte ich darauf hinweisen, dass es von 2013 bis 2015 einen öffentlichen Passwort-Hashing-Wettbewerb gab . Am Ende wurde Argon2 als empfohlene Passwort-Hashing-Funktion ausgewählt.

Es gibt eine ziemlich gut angenommene Java-Bindung für die ursprüngliche (native C) Bibliothek, die Sie verwenden können.

Im durchschnittlichen Anwendungsfall denke ich, dass es aus Sicherheitsgründen keine Rolle spielt, wenn Sie PBKDF2 anstelle von Argon2 wählen oder umgekehrt. Wenn Sie hohe Sicherheitsanforderungen haben, empfehle ich, Argon2 in Ihrer Bewertung zu berücksichtigen.

Weitere Informationen zur Sicherheit von Passwort-Hashing-Funktionen finden Sie unter security.se .

Qw3ry
quelle
@zaph Ich habe die Antwort bearbeitet, um objektiver zu sein. Bitte beachten Sie, dass die NIST-Empfehlung möglicherweise nicht immer die beste Wahl ist (siehe hier für ein Beispiel) - dies gilt natürlich auch für alles, was auch anderswo empfohlen wird. Daher denke ich, dass diese Antwort einen Wert für diese Frage liefert.
Qw3ry
4

Sie können Spring Security Crypto (hat nur 2 optionale Kompilierungsabhängigkeiten ) verwenden, das die Kennwortverschlüsselung von PBKDF2 , BCrypt , SCrypt und Argon2 unterstützt .

Argon2PasswordEncoder argon2PasswordEncoder = new Argon2PasswordEncoder();
String aCryptedPassword = argon2PasswordEncoder.encode("password");
boolean passwordIsValid = argon2PasswordEncoder.matches("password", aCryptedPassword);
SCryptPasswordEncoder sCryptPasswordEncoder = new SCryptPasswordEncoder();
String sCryptedPassword = sCryptPasswordEncoder.encode("password");
boolean passwordIsValid = sCryptPasswordEncoder.matches("password", sCryptedPassword);
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String bCryptedPassword = bCryptPasswordEncoder.encode("password");
boolean passwordIsValid = bCryptPasswordEncoder.matches("password", bCryptedPassword);
Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder();
String pbkdf2CryptedPassword = pbkdf2PasswordEncoder.encode("password");
boolean passwordIsValid = pbkdf2PasswordEncoder.matches("password", pbkdf2CryptedPassword);
BuZZ-dEE
quelle
2

Hier haben Sie zwei Links für MD5-Hashing und andere Hash-Methoden:

Javadoc-API: http://java.sun.com/j2se/1.4.2/docs/api/java/security/MessageDigest.html

Tutorial: http://www.twmacinta.com/myjava/fast_md5.php

Simon
quelle
3
Denken Sie daran, dass beim Passwort-Hashing langsamer langsamer ist. Sie sollten Tausende von Iterationen der Hash-Funktion als "Schlüsselverstärkungstechnik" verwenden. Auch Salz ist unerlässlich.
erickson
Ich hatte den Eindruck, dass mehrere Iterationen eines Qualitäts-Hashing-Algorithmus ungefähr die gleiche Sicherheit wie eine Iteration erzeugen würden, da die Länge der Bytes immer noch gleich wäre.
Chris Dutrow
@erickson Es wäre besser, Angreifer explizit zu verlangsamen.
Deamon
6
Informationen zur Schlüsselverstärkung: Es gibt Salze, die vorberechnete Hashes unbrauchbar machen. Angreifer müssen jedoch nicht vorberechnen. Angreifer können einfach "on the fly" Saiten + Salz hashen, bis sie die richtige finden. Wenn Sie Ihre Hashes jedoch tausende Male wiederholen, müssen sie dasselbe tun. Ihr Server wird von 10.000 Iterationen nicht stark betroffen sein, da dies nicht so häufig vorkommt. Angreifer benötigen das 10.000-fache der Rechenleistung.
Zockman
2
@Simon Heute gilt MD5 als nutzlos für das Hashing von Passwörtern, da es mit GPU-Brute-Force- / Wörterbuch-Angriffen in Sekundenschnelle geknackt werden kann. Siehe hier: codahale.com/how-to-safely-store-a-password
Eran Medan
1

Unter allen Standard-Hash-Schemata ist LDAP ssha das sicherste.

http://www.openldap.org/faq/data/cache/347.html

Ich würde einfach den dort angegebenen Algorithmen folgen und MessageDigest verwenden, um den Hash auszuführen.

Sie müssen das Salz wie vorgeschlagen in Ihrer Datenbank speichern.

ZZ Coder
quelle
1
Da SSHA die Hash-Funktion nicht iteriert, ist sie zu schnell. Dadurch können Angreifer Kennwörter schneller ausprobieren. Bessere Algorithmen wie Bcrypt, PBBKDF1 und PBKDF2 verwenden "Schlüsselverstärkungstechniken", um Angreifer bis zu dem Punkt zu verlangsamen, an dem ein Kennwort ablaufen sollte, bevor sie selbst einen 8-Buchstaben-Kennwortbereich brutal erzwingen können.
Erickson
Das Problem bei all diesen Mechanismen ist, dass Sie keinen Client-Support erhalten. Das Problem mit dem Hash-Passwort besteht darin, dass Sie das Passwort-Hash mit anderen Algorithmen nicht unterstützen können. Mit ssha unterstützen es zumindest alle LDAP-Clients.
ZZ Coder
Es ist nicht "am sichersten", sondern nur "ziemlich kompatibel". bcrypt / scrypt sind viel ressourcenintensiver.
eckes
1

Ab 2020 ist der glaubwürdigste und flexibelste verwendete Algorithmus

derjenige, der seine Stärke bei jeder Hardware am wahrscheinlichsten optimiert,

ist Argon2id oder Argon2i .

Es bietet das erforderliche Kalibrierungswerkzeug, um optimierte Festigkeitsparameter unter Berücksichtigung einer Ziel-Hashing-Zeit und der verwendeten Hardware zu finden.

  • Argon2i ist auf speichergieriges Hashing spezialisiert
  • Argon2d ist auf CPU-gieriges Hashing spezialisiert
  • Argon2id verwendet beide Methoden.

Speichergieriges Hashing würde gegen die Verwendung von GPUs zum Knacken helfen.

Die Implementierung von Spring Security / Bouncy Castle ist nicht optimiert und relativ wochenlang, wenn man bedenkt, was der Angreifer verwenden könnte. Vgl.: Federdokumentation

Die aktuelle Implementierung verwendet Bouncy Castle, das Parallelität / Optimierungen, die Passwort-Cracker bewirken, nicht ausnutzt, sodass eine unnötige Asymmetrie zwischen Angreifer und Verteidiger besteht.

Die glaubwürdigste Implementierung, die für Java verwendet wird, ist die von mkammerer .

ein Wrapper-Glas / eine Bibliothek der offiziellen nativen Implementierung, die in Rust geschrieben wurde.

Es ist gut geschrieben und einfach zu bedienen.

Die eingebettete Version bietet native Builds für Linux, Windows und OSX.

Als Beispiel wird es von jpmorganchase in seinem Tessera- Sicherheitsprojekt verwendet, das zur Sicherung von Quorum , seiner Cryptocurency-Implementierung von Ethereum, verwendet wird.

Hier ist der Beispielcode von tessera.

Die Kalibrierung kann mit de.mkammerer.argon2.Argon2Helper # findIterations durchgeführt werden

Der SCRYPT- und Pbkdf2-Algorithmus kann auch durch Schreiben eines einfachen Benchmarks kalibriert werden. Aktuelle minimale sichere Iterationswerte erfordern jedoch höhere Hashing-Zeiten.

user1767316
quelle
0

Ich habe das aus einem Video auf udemy abgeleitet und bearbeitet, um ein stärkeres zufälliges Passwort zu erhalten

}

private String pass() {
        String passswet="1234567890zxcvbbnmasdfghjklop[iuytrtewq@#$%^&*" ;

        char icon1;
        char[] t=new char[20];

         int rand1=(int)(Math.random()*6)+38;//to make a random within the range of special characters

            icon1=passswet.charAt(rand1);//will produce char with a special character

        int i=0;
        while( i <11) {

             int rand=(int)(Math.random()*passswet.length());
             //notice (int) as the original value of Math>random() is double

             t[i] =passswet.charAt(rand);

             i++;
                t[10]=icon1;
//to replace the specified item with icon1
         }
        return new String(t);
}






}
سحنون المالكى
quelle
Ich bin offen für Korrekturen, aber ich denke, Sie sollten beim Hashing keine Zufallszahlen verwenden. Dies ist so, dass Ihre Hash-Funktion deterministisch bleibt; Das heißt, wenn Sie eine Zeichenfolge mehrmals hashen, erhalten Sie immer denselben Hashwert für diese Zeichenfolge zurück.
Duldi