//! KDF example — HKDF, PBKDF2, and scrypt key derivation.
//!
//! Run with: cargo run --example kdf -p native-ossl

use native_ossl::digest::DigestAlg;
use native_ossl::kdf::{HkdfBuilder, Pbkdf2Builder, ScryptBuilder, ScryptParams};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let sha256 = DigestAlg::fetch(c"SHA2-256", None)?;

    // ── HKDF (RFC 5869) ───────────────────────────────────────────────────────

    let ikm = b"input key material";
    let salt = b"random salt value";
    let info = b"context / application info";

    let mut okm = [0u8; 32];
    HkdfBuilder::new(&sha256)
        .key(ikm)
        .salt(salt)
        .info(info)
        .derive(&mut okm)?;
    println!("HKDF-SHA-256 OKM: {}", native_ossl::util::hex_encode(okm));

    // HKDF-Expand only (skip extract — caller supplies PRK directly).
    let prk = okm; // reuse as PRK for demonstration
    let mut expanded = [0u8; 32];
    HkdfBuilder::new(&sha256)
        .key(&prk)
        .info(b"expand-only context")
        .mode(native_ossl::kdf::HkdfMode::ExpandOnly)
        .derive(&mut expanded)?;
    println!(
        "HKDF-Expand OKM:  {}",
        native_ossl::util::hex_encode(expanded)
    );

    // ── PBKDF2-HMAC-SHA-256 (RFC 8018) ───────────────────────────────────────

    let password = b"correct horse battery staple";
    let pbkdf2_salt = b"nacl";

    let mut dk = [0u8; 32];
    Pbkdf2Builder::new(&sha256, password, pbkdf2_salt)
        .iterations(600_000)
        .derive(&mut dk)?;
    println!("PBKDF2 derived key: {}", native_ossl::util::hex_encode(dk));

    // ── scrypt (RFC 7914) ─────────────────────────────────────────────────────

    let scrypt_salt = b"NaCl";
    let params = ScryptParams::default(); // N=16384, r=8, p=1 (interactive default)

    let mut scrypt_key = [0u8; 32];
    ScryptBuilder::new(password, scrypt_salt)
        .params(params)
        .derive(&mut scrypt_key)?;
    println!(
        "scrypt derived key: {}",
        native_ossl::util::hex_encode(scrypt_key)
    );

    Ok(())
}
