import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HexFormat;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class KataSandiPbkdf2 {

    public static void main(String[] args) throws Exception {
        // Salt tetap HANYA untuk demo deterministik.
        // Produksi: salt acak 16 byte dari SecureRandom per pengguna.
        byte[] saltBudi = "garam-budi-2026".getBytes(StandardCharsets.UTF_8);
        byte[] saltSiti = "garam-siti-2026".getBytes(StandardCharsets.UTF_8);
        String sandiSama = "rahasiaKuat123";

        byte[] hashBudi = hashPbkdf2(sandiSama, saltBudi);
        byte[] hashSiti = hashPbkdf2(sandiSama, saltSiti);

        System.out.println("=== Registrasi: kata sandi sama, salt berbeda ===");
        System.out.println("Budi : " + HexFormat.of().formatHex(hashBudi));
        System.out.println("Siti : " + HexFormat.of().formatHex(hashSiti));
        System.out.println("Hash berbeda meski kata sandi sama: salt unik per pengguna.");

        System.out.println();
        System.out.println("=== Verifikasi dengan MessageDigest.isEqual ===");
        verifikasi(sandiSama, saltBudi, hashBudi);
        verifikasi("tebakanSalah", saltBudi, hashBudi);
        verifikasi(sandiSama, saltSiti, hashSiti);
    }

    static void verifikasi(String sandiMasukan, byte[] salt, byte[] hashTersimpan)
            throws Exception {
        byte[] hashBaru = hashPbkdf2(sandiMasukan, salt);
        boolean cocok = MessageDigest.isEqual(hashBaru, hashTersimpan);
        System.out.println("sandi [" + sandiMasukan + "] -> "
                + (cocok ? "COCOK" : "TIDAK COCOK"));
    }

    // PBKDF2: hash lambat yang sengaja diulang ribuan kali.
    // Iterasi 1000 dipilih agar demo cepat; produksi memakai ratusan ribu.
    static byte[] hashPbkdf2(String sandi, byte[] salt) throws Exception {
        PBEKeySpec spesifikasi = new PBEKeySpec(
                sandi.toCharArray(), salt, 1000, 256);
        SecretKeyFactory pabrik = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        return pabrik.generateSecret(spesifikasi).getEncoded();
    }
}
