qssh 0.0.2-alpha

Experimental quantum-safe SSH using post-quantum crypto. Research project - NOT for production. See LIMITATIONS.md
Documentation
//! Quantum-specific tests for QSSH
//!
//! Tests for vault, ratchet, and Lamport signatures

use qssh::vault::{QuantumVault, KeyType, DoubleRatchet, LamportKeypair};

#[tokio::test]
async fn test_vault_initialization() {
    let mut vault = QuantumVault::new();
    
    // Should fail before initialization
    assert!(vault.get_key("test").await.is_err());
    
    // Initialize with master key
    vault.init(b"test-master-key").await.unwrap();
    
    // Store and retrieve a key
    let test_key = b"my-secret-key";
    vault.store_key("test", test_key, KeyType::SessionKey, 0).await.unwrap();
    
    let retrieved = vault.get_key("test").await.unwrap();
    assert_eq!(test_key.to_vec(), retrieved);
}

#[tokio::test]
async fn test_one_time_keys() {
    let mut vault = QuantumVault::new();
    vault.init(b"test-master-key").await.unwrap();
    
    // Store a one-time key
    let otk = b"one-time-key";
    vault.store_key("otk", otk, KeyType::LamportSeed, 1).await.unwrap();
    
    // First use should succeed
    let first = vault.get_key("otk").await.unwrap();
    assert_eq!(otk.to_vec(), first);
    
    // Second use should fail
    assert!(vault.get_key("otk").await.is_err());
}

#[test]
fn test_double_ratchet() {
    let mut ratchet = DoubleRatchet::new(b"initial-root-key");
    
    // Generate sequence of keys
    let mut keys = Vec::new();
    for _ in 0..10 {
        keys.push(ratchet.next_key());
    }
    
    // All keys should be unique
    let unique_keys: std::collections::HashSet<_> = keys.iter().collect();
    assert_eq!(unique_keys.len(), 10);
}

#[test]
fn test_ratchet_dh_step() {
    let mut alice = DoubleRatchet::new(b"shared-root");
    let mut bob = DoubleRatchet::new(b"shared-root");
    
    // Each ratchet has independent send/recv chains
    let alice_send1 = alice.next_send_key();
    let alice_send2 = alice.next_send_key();
    
    // Keys should evolve
    assert_ne!(alice_send1, alice_send2);
    
    // Get keys before DH ratchet
    let alice_key_before = alice.next_send_key();
    let bob_key_before = bob.next_send_key();
    
    // After DH ratchet, keys should be different
    alice.dh_ratchet(b"new-dh-secret");
    bob.dh_ratchet(b"new-dh-secret");
    
    let alice_key_after = alice.next_send_key();
    let bob_key_after = bob.next_send_key();
    
    // Keys should change after DH ratchet
    assert_ne!(alice_key_before, alice_key_after);
    assert_ne!(bob_key_before, bob_key_after);
}

#[test]
fn test_lamport_signature() {
    let seed = [42u8; 32];
    let mut keypair = LamportKeypair::generate(&seed);
    let public_key = keypair.public_key_bytes();
    
    let message = b"Critical blockchain operation";
    let signature = keypair.sign(message).unwrap();
    
    // Verify signature
    assert!(LamportKeypair::verify(&public_key, message, &signature));
    
    // Wrong message should fail
    assert!(!LamportKeypair::verify(&public_key, b"Different message", &signature));
    
    // Can't sign twice (one-time property)
    assert!(keypair.sign(b"Another message").is_err());
}

#[tokio::test]
async fn test_lamport_chain_in_vault() {
    let mut vault = QuantumVault::new();
    vault.init(b"test-master-key").await.unwrap();
    
    // Initialize Lamport chain
    vault.init_lamport_chain("attestations", b"chain-seed", 5).await.unwrap();
    
    // Should be able to get 5 keypairs
    for i in 0..5 {
        let mut keypair = vault.get_lamport_keypair("attestations").await.unwrap();
        let message = format!("Attestation {}", i);
        let sig = keypair.sign(message.as_bytes()).unwrap();
        // Signature was created successfully
    }
    
    // 6th should fail (chain exhausted)
    assert!(vault.get_lamport_keypair("attestations").await.is_err());
}

#[tokio::test]
async fn test_ratchet_in_vault() {
    let mut vault = QuantumVault::new();
    vault.init(b"test-master-key").await.unwrap();
    
    // Create ratchet session
    vault.create_ratchet("session-1", b"initial-key").await.unwrap();
    
    // Get evolving keys
    let key1 = vault.ratchet_forward("session-1").await.unwrap();
    let key2 = vault.ratchet_forward("session-1").await.unwrap();
    let key3 = vault.ratchet_forward("session-1").await.unwrap();
    
    // All should be different
    assert_ne!(key1, key2);
    assert_ne!(key2, key3);
    assert_ne!(key1, key3);
}