Hashing Kata Sandi di Java

Java Top

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

>> LIHAT KURSUSnya

1. Ikhtisar

Dalam tutorial ini, kita akan membahas pentingnya hashing kata sandi.

Kami akan melihat sekilas apa itu, mengapa itu penting, dan beberapa cara yang aman dan tidak aman untuk melakukannya di Java.

2. Apa itu Hashing?

Hashing adalah proses menghasilkan string, atau hash , dari pesan tertentu menggunakan fungsi matematika yang dikenal sebagai fungsi hash kriptografi .

Meskipun ada beberapa fungsi hash di luar sana, yang disesuaikan dengan kata sandi hashing harus memiliki empat properti utama agar aman:

  1. Ini harus deterministik : pesan yang sama yang diproses dengan fungsi hash yang sama harus selalu menghasilkan hash yang sama
  2. Ini tidak bisa dibalik : tidak praktis untuk menghasilkan pesan dari hash -nya
  3. Ini memiliki entropi tinggi : perubahan kecil pada pesan akan menghasilkan hash yang sangat berbeda
  4. Dan itu menahan benturan : dua pesan berbeda seharusnya tidak menghasilkan hash yang sama

Fungsi hash yang memiliki keempat properti merupakan kandidat kuat untuk hashing kata sandi karena bersama-sama mereka secara dramatis meningkatkan kesulitan dalam rekayasa ulang kata sandi dari hash.

Selain itu, fungsi hashing kata sandi harus lambat . Algoritme cepat akan membantu serangan brute force di mana peretas akan mencoba menebak kata sandi dengan melakukan hashing dan membandingkan miliaran (atau triliunan) kata sandi potensial per detik.

Beberapa fungsi hash hebat yang memenuhi semua kriteria ini adalahPBKDF2, BCrypt, dan SCrypt. Namun pertama-tama, mari kita lihat beberapa algoritme lama dan mengapa algoritme tersebut tidak lagi direkomendasikan

3. Tidak Direkomendasikan: MD5

Fungsi hash pertama kami adalah algoritme intisari pesan MD5, yang dikembangkan sejak tahun 1992.

MessageDigest dari Java membuatnya mudah untuk dihitung dan masih dapat berguna dalam situasi lain.

Namun, selama beberapa tahun terakhir, MD5 ditemukan gagal pada properti hashing kata sandi keempat karena secara komputasi mudah untuk menghasilkan benturan. Terlebih lagi, MD5 adalah algoritma yang cepat dan oleh karena itu tidak berguna melawan serangan brute-force.

Karena itu, MD5 tidak disarankan.

4. Tidak Direkomendasikan: SHA-512

Selanjutnya, kita akan melihat SHA-512, yang merupakan bagian dari keluarga Secure Hash Algorithm, sebuah keluarga yang dimulai dengan SHA-0 pada tahun 1993.

4.1. Mengapa SHA-512?

Saat daya komputer meningkat, dan saat kami menemukan kerentanan baru, peneliti mendapatkan versi baru SHA. Versi yang lebih baru memiliki panjang yang semakin lama, atau terkadang peneliti menerbitkan versi baru dari algoritme yang mendasarinya.

SHA-512 mewakili kunci terpanjang di generasi ketiga algoritme.

Meskipun sekarang ada versi SHA yang lebih aman , SHA-512 adalah yang terkuat yang diterapkan di Java.

4.2. Menerapkan di Java

Sekarang, mari kita lihat penerapan algoritma hashing SHA-512 di Java.

Pertama, kita harus memahami konsep garam . Sederhananya, ini adalah urutan acak yang dibuat untuk setiap hash baru .

Dengan memperkenalkan keacakan ini, kami meningkatkan entropi hash , dan kami melindungi database kami dari daftar hash yang telah dikompilasi sebelumnya yang dikenal sebagai tabel pelangi .

Fungsi hash baru kami kemudian menjadi kira-kira:

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

4.3. Menghasilkan 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, kita akan menggunakan kelas MessageDigest untuk mengonfigurasi fungsi hash SHA-512 dengan salt kita:

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

Dan dengan tambahan itu, kita sekarang dapat menggunakan metode intisari untuk menghasilkan kata sandi hash kita:

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

4.4. Mengapa Tidak Direkomendasikan?

Saat digunakan dengan garam, SHA-512 masih merupakan opsi yang adil, tetapi ada opsi yang lebih kuat dan lebih lambat di luar sana .

Selain itu, opsi lainnya yang akan kami bahas memiliki fitur penting: kekuatan yang dapat dikonfigurasi.

5. PBKDF2, BCrypt, dan SCrypt

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

5.1. Mengapa Itu Direkomendasikan?

Masing-masing lambat, dan masing-masing memiliki fitur brilian yang memiliki 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 bahwa Spring Security dikirimkan dengan kelas enkripsi kata sandinya, yang mengimplementasikan berbagai fungsi hash yang berbeda.

Seperti biasa, kode tersedia di GitHub.

Jawa bawah

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

>> LIHAT KURSUSnya