//! RSA demonstration: key generation, PKCS#1 v1.5 sign/verify,
//! and OAEP encrypt/decrypt.
//!
//! ```sh
//! cargo run -p arcana --release --example rsa_demo
//! ```

use arcana::Hasher;
use arcana::hash::sha256::Sha256;
use arcana::rsa::oaep::{oaep_decrypt, oaep_encrypt};
use arcana::rsa::pkcs1::{HashAlg, pkcs1v15_sign, pkcs1v15_verify};
use arcana::rsa::rsa::rsa_keygen;

fn rng_fill(buf: &mut [u8]) {
    // Simple PRNG seeded from a counter — NOT for production use.
    // Real applications must use /dev/urandom or a hardware RNG.
    static mut CTR: u64 = 0xdeadbeef_cafebabe;
    for b in buf.iter_mut() {
        unsafe {
            CTR = CTR.wrapping_mul(6364136223846793005).wrapping_add(1);
            *b = (CTR >> 33) as u8;
        }
    }
}

fn hex(bytes: &[u8]) -> String {
    bytes.iter().map(|b| format!("{:02x}", b)).collect()
}

fn main() {
    // Generate a 2048-bit RSA key pair.
    println!("RSA-2048 key generation...");
    let (pk, sk) = rsa_keygen(2048, &mut rng_fill);
    println!(
        "  modulus ({} bits): {}...",
        pk.n.bit_len(),
        hex(&pk.n.to_be_bytes(pk.n.byte_len())[..16])
    );

    // ---- PKCS#1 v1.5 signature ----
    let message = b"RSA PKCS#1 v1.5 signature test";
    let digest = Sha256::hash(message);

    let sig = pkcs1v15_sign(&sk, &digest, HashAlg::Sha256);
    println!("\nPKCS#1 v1.5 sign (SHA-256):");
    println!("  sig[0..16]: {}", hex(&sig[..16]));

    let ok = pkcs1v15_verify(&pk, &digest, HashAlg::Sha256, &sig);
    assert!(ok, "signature verification must pass");
    println!("  verify: OK");

    // Tamper
    let mut sig_bad = sig.clone();
    sig_bad[0] ^= 0xFF;
    assert!(!pkcs1v15_verify(&pk, &digest, HashAlg::Sha256, &sig_bad));
    println!("  tamper: correctly rejected");

    // ---- OAEP encryption ----
    let plaintext = b"secret payload";
    let ct = oaep_encrypt(&pk, plaintext, &[], &mut rng_fill);
    println!("\nOAEP encrypt:");
    println!("  ct[0..16]: {}", hex(&ct[..16]));

    let pt = oaep_decrypt(&sk, &ct, &[]).expect("OAEP decrypt");
    assert_eq!(pt, plaintext);
    println!("  decrypt: OK");

    println!("\nAll RSA demos passed.");
}
