Mencantumkan Kata Laluan di Java

Java Teratas

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan membincangkan kepentingan hash kata laluan.

Kami akan melihat dengan cepat apa itu, mengapa itu penting, dan beberapa cara yang selamat dan tidak selamat untuk melakukannya di Java.

2. Apa Hashing?

Hashing adalah proses menghasilkan rentetan, atau hash , dari mesej yang diberikan menggunakan fungsi matematik yang dikenali sebagai fungsi hash kriptografi .

Walaupun terdapat beberapa fungsi hash di luar sana, kata kunci yang disesuaikan dengan hashing password harus mempunyai empat sifat utama agar selamat:

  1. Ia harus bersifat deterministik : mesej yang sama yang diproses oleh fungsi hash yang sama harus selalu menghasilkan hash yang sama
  2. Ia tidak boleh dibalikkan : tidak praktikal untuk menghasilkan mesej dari hashnya
  3. Ini mempunyai entropi tinggi : perubahan kecil pada mesej harus menghasilkan hash yang sangat berbeza
  4. Dan ia menentang perlanggaran : dua mesej yang berbeza tidak boleh menghasilkan hash yang sama

Fungsi hash yang mempunyai keempat-empat sifat adalah calon kuat untuk mencirikan kata laluan kerana bersama-sama mereka secara dramatik meningkatkan kesukaran dalam membalikkan kata laluan dari hash.

Walaupun begitu, fungsi hashing kata laluan harus perlahan . Algoritma pantas akan membantu serangan kekerasan di mana penggodam akan cuba meneka kata laluan dengan mencirikan dan membandingkan berbilion (atau trilion) potensi kata laluan per saat.

Beberapa fungsi hash hebat yang memenuhi semua kriteria ini adalahPBKDF2, BCrypt, dan SCrypt. Tetapi pertama, mari kita lihat beberapa algoritma lama dan mengapa ia tidak lagi digalakkan

3. Tidak Disyorkan: MD5

Fungsi hash pertama kami adalah algoritma pencernaan mesej MD5, yang dikembangkan pada tahun 1992.

Java's MessageDigest menjadikannya mudah dikira dan masih boleh berguna dalam keadaan lain.

Walau bagaimanapun, sejak beberapa tahun kebelakangan ini, MD5 didapati gagal memiliki harta pencirian kata laluan keempat kerana mudah untuk membuat perlanggaran. Untuk mengatasinya, MD5 adalah algoritma pantas dan oleh itu tidak berguna untuk menyerang serangan brute-force.

Oleh kerana itu, MD5 tidak digalakkan.

4. Tidak digalakkan: SHA-512

Seterusnya, kita akan melihat SHA-512, yang merupakan sebahagian daripada keluarga Secure Hash Algorithm, sebuah keluarga yang bermula dengan SHA-0 pada tahun 1993.

4.1. Mengapa SHA-512?

Apabila komputer meningkat dalam daya, dan ketika kita menemui kelemahan baru, maka penyelidik memperoleh versi baru SHA. Versi yang lebih baru mempunyai panjang yang semakin panjang, atau kadang kala penyelidik menerbitkan versi baru dari algoritma yang mendasari.

SHA-512 mewakili kunci terpanjang dalam generasi ketiga algoritma.

Walaupun sekarang terdapat versi SHA yang lebih selamat , SHA-512 adalah versi terkuat yang dilaksanakan di Java.

4.2. Melaksanakan di Jawa

Sekarang, mari kita lihat pelaksanaan algoritma hash SHA-512 di Java.

Pertama, kita harus memahami konsep garam . Ringkasnya, ini adalah urutan rawak yang dihasilkan untuk setiap hash baru .

Dengan memperkenalkan rawak ini, kami meningkatkan entropi hash , dan kami melindungi pangkalan data kami daripada senarai hash yang telah disusun sebelumnya yang dikenali sebagai jadual pelangi .

Fungsi hash baru kami kemudian menjadi kira-kira:

salt <- generate-salt; hash <- salt + ':' + sha512(salt + password)

4.3. Menjana Garam

Untuk memperkenalkan garam, kami akan menggunakan kelas SecureRandom dari java.security :

SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.nextBytes(salt);

Kemudian, kami akan menggunakan kelas MessageDigest untuk mengkonfigurasi fungsi hash SHA-512 dengan garam kami:

MessageDigest md = MessageDigest.getInstance("SHA-512"); md.update(salt);

Dan dengan menambahkannya, kita sekarang boleh menggunakan kaedah mencerna untuk menghasilkan kata laluan hash kita:

byte[] hashedPassword = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));

4.4. Mengapa Tidak Digalakkan?

Apabila digunakan dengan garam, SHA-512 masih merupakan pilihan yang tepat, tetapi ada pilihan yang lebih kuat dan lebih perlahan di luar sana .

Selain itu, pilihan lain yang akan kita bahas mempunyai ciri penting: kekuatan yang boleh dikonfigurasi.

5. PBKDF2, BCrypt, dan SCrypt

PBKDF2, BCrypt, dan SCrypt adalah tiga algoritma yang disyorkan.

5.1. Mengapa Mereka Disyorkan?

Masing-masing lambat, dan masing-masing mempunyai ciri cemerlang mempunyai kekuatan yang dapat dikonfigurasi.

This means that as computers increase in strength, we can slow down the algorithm by changing the inputs.

5.2. Implementing PBKDF2 in Java

Now, salts are a fundamental principle of password hashing, and so we need one for PBKDF2, too:

SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.nextBytes(salt);

Next, we'll create a PBEKeySpec and a SecretKeyFactory which we'll instantiate using the PBKDF2WithHmacSHA1 algorithm:

KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

The third parameter (65536) is effectively the strength parameter. It indicates how many iterations that this algorithm run for, increasing the time it takes to produce the hash.

Finally, we can use our SecretKeyFactory to generate the hash:

byte[] hash = factory.generateSecret(spec).getEncoded();

5.3. Implementing BCrypt and SCrypt in Java

So, it turns out that BCrypt and SCrypt support don't yet ship with Java, though some Java libraries support them.

One of those libraries is Spring Security.

6. Password Hashing With Spring Security

Although Java natively supports both the PBKDF2 and SHA hashing algorithms, it doesn't support BCrypt and SCrypt algorithms.

Luckily for us, Spring Security ships with support for all these recommended algorithms via the PasswordEncoder interface:

  • MessageDigestPasswordEncoder gives us MD5 and SHA-512
  • Pbkdf2PasswordEncoder gives us PBKDF2
  • BCryptPasswordEncoder gives us BCrypt, and
  • SCryptPasswordEncoder gives us SCrypt

The password encoders for PBKDF2, BCrypt, and SCrypt all come with support for configuring the desired strength of the password hash.

We can use these encoders directly, even without having a Spring Security-based application. Or, if we are protecting our site with Spring Security, then we can configure our desired password encoder through its DSL or via dependency injection.

And, unlike our examples above, these encryption algorithms will generate the salt for us internally. The algorithm stores the salt within the output hash for later use in validating a password.

7. Conclusion

So, we've taken a deep dive into password hashing; exploring the concept and its uses.

And we've taken a look at some historical hash functions as well as some currently implemented ones before coding them in Java.

Akhirnya, kami melihat bahawa Spring Security menghantar kelas enkripsi kata laluannya, melaksanakan pelbagai fungsi hash yang berbeza.

Seperti biasa, kodnya terdapat di GitHub.

Bahagian bawah Java

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS