import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HexFormat;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class SidikDanHmac {

    public static void main(String[] args) throws Exception {
        // ============ Bagian 1: sidik jari SHA-256 ============
        String pesanAsli = "Transfer 100000 ke Budi";
        String pesanUbah = "Transfer 100001 ke Budi";

        System.out.println("=== SHA-256: satu digit beda, sidik total beda ===");
        System.out.println(" " + pesanAsli + " -> " + sha256Hex(pesanAsli));
        System.out.println(" " + pesanUbah + " -> " + sha256Hex(pesanUbah));

        // ============ Bagian 2: HMAC terikat kunci rahasia ============
        // Kunci tetap hanya untuk demo deterministik; produksi memakai
        // kunci dari proses pertukaran yang aman (mis. saat sesi dibuat).
        byte[] kunci = "kunci-hmac-demo".getBytes(StandardCharsets.UTF_8);
        String pesan = "pembayaran: Rp250.000 untuk Siti";

        byte[] tag = hmac(kunci, pesan);
        System.out.println();
        System.out.println("=== HMAC-SHA256 atas pesan tetap ===");
        System.out.println(" tag : " + HexFormat.of().formatHex(tag));

        boolean pesanAsliSah = MessageDigest.isEqual(tag, hmac(kunci, pesan));
        String pesanDitelan = "pembayaran: Rp950.000 untuk Siti";
        boolean pesanUbahSah = MessageDigest.isEqual(tag, hmac(kunci, pesanDitelan));

        System.out.println(" verifikasi pesan asli  : " + (pesanAsliSah ? "SAH" : "TIDAK SAH"));
        System.out.println(" verifikasi pesan ubahan: " + (pesanUbahSah ? "SAH" : "TIDAK SAH"));
    }

    static String sha256Hex(String teks) throws Exception {
        MessageDigest pencerna = MessageDigest.getInstance("SHA-256");
        byte[] sidik = pencerna.digest(teks.getBytes(StandardCharsets.UTF_8));
        return HexFormat.of().formatHex(sidik);
    }

    static byte[] hmac(byte[] kunci, String pesan) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(kunci, "HmacSHA256"));
        return mac.doFinal(pesan.getBytes(StandardCharsets.UTF_8));
    }
}
