3 Eylül 2019 Salı

PBEKeySpec Sınıfı - Şifreden Hash Üretir

Giriş
Şu satırı dahil ederiz.
import java.security.spec.KeySpec;
import javax.crypto.spec.PBEKeySpec;
PBKDF2 (Password-Based Key Derivation Function 2) algoritmasını gerçekleştirir.
Açıklaması şöyle.
PBKDF2 is one of the oldest KDFs, and is likely the most common. It is not memory hard, which means an attacker can perform massively parallel attacks against it without running into memory issues. PBKDF2 works by taking any keyed hash, typically HMAC, and running it multiple times such that each hash evaluation depends on all the previous hash evaluations. Unfortunately, typical hashes used in HMAC require next to no memory to compute, so an attacker can massively parallelize brute force searches on GPUs and ASICs without running into the issues that a memory-hard KDF would cause.
Açıklaması şöyle
Password-based key-derivation algorithm found in PKCS #5 2.0 using the specified pseudo-random function (<prf>). Example: PBKDF2WithHmacSHA256.
Ne İşe Yarar ?
SecretKeyFactory ile birlikte kullanılarak verilen şifreyi byte[] hash haline getirir.

Örnek
Şöyle yaparız Burada byte[] hash Base64 haline getiriliyor.
String password = "password123";
String salt = "somesalt";
int iterations = 10_000;
int keyLength = 256;

SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec spec = new PBEKeySpec(password.toCharArray(), 
  salt.getBytes(), iterations, keyLength);
SecretKey key = skf.generateSecret(spec);
byte[] hash = key.getEncoded();

System.out.println(Base64.getEncoder().encodeToString(hash));
Örnek
Şöyle yaparız. Burada byte[] hash Base64 haline getiriliyor.
public class PasswordUtils {

  public static final int ITERATIONS = 1000;
  public static final int KEY_LENGTH = 512;
  private static final String ALGORITHM = "PBKDF2WithHmacSHA512";
  private static final SecureRandom RAND = new SecureRandom();

  public static Optional<String> generateSalt(final int length) {
    byte[] salt = new byte[length];
    RAND.nextBytes(salt);

    return Optional.of(Base64.getEncoder().encodeToString(salt));
  }

  public static Optional<String> hashThePlainTextPassword(
    String plainTextPassword,
    String salt) {
    
    char[] chars = plainTextPassword.toCharArray();
    byte[] bytes = salt.getBytes();

    PBEKeySpec spec = new PBEKeySpec(chars, bytes, ITERATIONS, KEY_LENGTH);
    Arrays.fill(chars, Character.MIN_VALUE);
    
    try {
      SecretKeyFactory fac = SecretKeyFactory.getInstance(ALGORITHM);
      byte[] securePassword = fac.generateSecret(spec).getEncoded();
      return Optional.of(Base64.getEncoder().encodeToString(securePassword));

    } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
      //Handle the exception
      return Optional.empty();
    } finally {
      spec.clearPassword();
    }
  }
}
constructor - password + salt + iterationCount
Şöyle yaparız.
byte[] salt = { ... };
String passPhrase = ...;
int iterationCount = 2;
KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
constructor - password + salt + iterationCount + keyLength
AES için şöyle yaparız.
PBEKeySpec spec = new PBEKeySpec("password", "salt".getBytes(),1000  , 128);

Hiç yorum yok:

Yorum Gönder