//! pqc-py — Post-quantum cryptography for Python via Rust
//!
//! This crate provides memory-safe, high-performance cryptographic operations:
//! - HKDF-SHA256/SHA512 key derivation
//! - HMAC-SHA256 message authentication
//! - AES-256-GCM authenticated encryption
//! - SHA-256 hash chains for audit logging
//! - Post-quantum cryptography (ML-KEM, ML-DSA, SLH-DSA)
//!
//! All secret key material is automatically zeroed on drop.

#![deny(unsafe_code)]
#![warn(missing_docs)]
#![warn(clippy::all)]

pub mod error;
pub mod hash;
pub mod keys;
pub mod symmetric;
pub mod pqc;

#[cfg(feature = "python")]
pub mod ffi;

// Re-export primary types for convenience
pub use error::CryptoError;
pub use keys::hkdf::{derive_key, derive_key_sha512};
pub use keys::hmac::{hmac_sha256, verify_hmac};
pub use symmetric::aes_gcm::{decrypt_aes_gcm, encrypt_aes_gcm};
pub use hash::chain::{HashChain, HashChainEntry};

// Re-export PQC types
pub use pqc::kyber::{KyberKeyPair, kyber_keygen, kyber_encapsulate, kyber_decapsulate};
pub use pqc::dilithium::{DilithiumKeyPair, dilithium_keygen, dilithium_sign, dilithium_verify};
pub use pqc::sphincs::{SphincsKeyPair, SphincsVariant, sphincs_keygen, sphincs_sign, sphincs_verify};
pub use pqc::SecurityLevel;

/// Library version
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// Generate cryptographically secure random bytes
pub fn random_bytes(length: usize) -> Vec<u8> {
    use rand::RngCore;
    let mut rng = rand::thread_rng();
    let mut bytes = vec![0u8; length];
    rng.fill_bytes(&mut bytes);
    bytes
}

/// Generate a random 32-byte key
pub fn random_key() -> [u8; 32] {
    use rand::RngCore;
    let mut rng = rand::thread_rng();
    let mut key = [0u8; 32];
    rng.fill_bytes(&mut key);
    key
}

/// Generate a random 12-byte nonce for AES-GCM
pub fn random_nonce() -> [u8; 12] {
    use rand::RngCore;
    let mut rng = rand::thread_rng();
    let mut nonce = [0u8; 12];
    rng.fill_bytes(&mut nonce);
    nonce
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_random_bytes() {
        let bytes1 = random_bytes(32);
        let bytes2 = random_bytes(32);
        assert_eq!(bytes1.len(), 32);
        assert_eq!(bytes2.len(), 32);
        assert_ne!(bytes1, bytes2);
    }

    #[test]
    fn test_random_key() {
        let key1 = random_key();
        let key2 = random_key();
        assert_ne!(key1, key2);
    }

    #[test]
    fn test_random_nonce() {
        let nonce1 = random_nonce();
        let nonce2 = random_nonce();
        assert_ne!(nonce1, nonce2);
    }
}
