9 Eylül 2020 Çarşamba

SpringSecurity BCryptPasswordEncoder Sınıfı

Giriş
Şu satırı dahil ederiz.
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
Şifre hiçbir zaman açık metin olaran saklanmamalı. Açıklaması şöyle.
"Never store passwords in plain text" is not a rule. It is a best practice based on common security breaches on naive implementations of password protections.
BCrypt 1999 yılında ortaya çıkmış. 1993 yılında ortaya çıkan Blowfish ile alakalı. Açıklaması şöyle.
BCrypt is a hashing algorithm that was designed by Niels Provos and David Mazières of the OpenBSD Project in 1999. The B stands for...Blowfish!

Blowfish is a symmetric-key block cipher, designed by Bruce Schneier in 1993. Now there's a more modern version called Twofish, but we don't care about that here!
Bu algoritma donanım hızlandıkça daha da yavaşlıyor.  Açıklaması şöyle.
They envisioned an algorithm with computational cost that would increase as hardware improved. Or, as computers get faster and better able to guess passwords, encryption should be slower, or have more "cost."
Neden yavaşladığının açıklaması şöyle.
bcrypt is an older KDF designed from the key schedule of Blowfish, which is slow. It requires 4 KiB of fast memory to compute, which makes it inefficient on GPU-based crackers due to their use of contended memory. This is because GPUs have many cores, but each core has to share access to the main VRAM. Because bcrypt reads and modifies a 4 KiB state as it runs, multiple parallel GPU cores will fight over who gets access to the main memory bus, and the result is that most cores are idling, waiting until they have access to the memory they need to perform bcrypt evaluations during brute force.
constructor
UI'dan gelen şifre uzunluğu için bir üst sınır koymakta fayda var. Üst sınıf bir açıklamaya göre 64 karakter olabilir..
...they recommend a limit of 64 characters for Bcrypt (due to limitations in the algorithm and implementations), and between 64 and 128 characters for other algorithms.
Bir başka açıklama ise şöyle
However, when using bcrypt you should be aware that it limits your maximum password length to 50-72 bytes. The exact length depends on the bcrypt implementation you are using
Örnek
Şöyle yaparız.
@Bean
public PasswordEncoder passwordEncoder() {
  return new BCryptPasswordEncoder(8);
}
encode metodu
Metodun içi şöyle.
public String encode(CharSequence rawPassword) {
  String salt;
  if(this.strength > 0) {
    if(this.random != null) {
      salt = BCrypt.gensalt(this.strength, this.random);
    } else {
      salt = BCrypt.gensalt(this.strength);
    }
  } else {
    salt = BCrypt.gensalt();
  }

  return BCrypt.hashpw(rawPassword.toString(), salt);
}
Döndürülen string 3 kısımdan oluşur. Şöyledir
$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
Açıklaması şöyle.
This is actually three fields, delimited by "$":

- 2a identifies the bcrypt algorithm version that was used.
- 10 is the cost factor; 210 iterations of the key derivation function are used (which is not enough, by the way. I'd recommend a cost of 12 or more.)
- vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa is the salt and the cipher text, concatenated and encoded in a modified Base-64. The first 22 characters decode to a 16-byte value for the salt. The remaining characters are cipher text to be compared for authentication.
Gerçek şifre ile bu string'in eşleştiğini kontrol etmek için matches() metodunu kullanmak gerekir.

Örnek
Şöyle yaparız.
@Autowired
private BCryptPasswordEncoder passwordEncoder;
...
//encode the password
user.setPassword(passwordEncoder.encode(user.getPassword()));
matches metodu
İmzası şöyle.
* @param rawPassword the raw password to encode and match
 * @param encodedPassword the encoded password from storage to compare with
 * @return true if the raw password, after encoding, matches the encoded password from
 * storage
 */
boolean matches(CharSequence rawPassword, String encodedPassword);

Hiç yorum yok:

Yorum Gönder