Files
zooqueen afe5434dc4 give the crate a workspace root, and the pqc callers the api that exists
cargo could not read the manifest at all:

  error inheriting `aes-gcm` from workspace root manifest's
  workspace.dependencies.aes-gcm: failed to find a workspace root

All 25 dependencies are declared `workspace = true`, which resolves only
against a [workspace.dependencies] table, and the crate was extracted from a
monorepo without one. The versions here are the ones Cargo.lock had already
resolved, so this records what the crate was building against and chooses
nothing new — `cargo build --locked` leaves Cargo.lock untouched.

That got the manifest parsed and the library building, which exposed three
callers written against an ml-kem/ml-dsa that predates the pinned versions:

  Encapsulate and Decapsulate are private at ml_kem's root and public at
    ml_kem::kem, and MlKem768::generate needs KemCore in scope.

  ml-dsa has no Ml_Dsa65, no VerificationKey and no SigningKey::generate.
    Key generation is the KeyGen trait (MlDsa65::key_gen), the pair hands out
    signing_key()/verifying_key(), and signing goes through signature::Signer
    and Verifier.

  ml-dsa is on rand_core 0.9 while ml-kem is on 0.6, so one thread_rng cannot
    serve both. The ml-dsa side takes OsRng from ml-dsa's own re-export, via
    unwrap_err, because OsRng is fallible in 0.9 and key_gen wants an
    infallible CryptoRng. No new dependency.

  integration_test's message list mixed [u8; 9], [u8; 27], [u8; 0] and
    [u8; 1000] in one untyped array, which has no single element type. Typed
    as [&[u8]; 4].

Both examples RUN, not merely compile: ML-KEM encapsulation round-trips,
ML-DSA signatures verify, HQC round-trips. 12 tests pass.

Worth knowing separately: src/ml_kem.rs, src/ml_dsa.rs, src/hqc.rs, src/pqc/
and src/hybrid/ are in no build target — lib.rs declares only symmetric, hash,
error and prelude. Those wrappers are dead files and would not compile as they
stand (src/ml_dsa.rs imports the same Ml_Dsa65 and VerificationKey that do not
exist). Post-quantum is reachable today only as the re-exported upstream
crates, without this crate's SecurityLevel/zeroizing layer over it.
2026-08-10 21:15:45 -07:00

97 lines
3.3 KiB
Rust

//! Test all crypto functionality on ARM Mac
fn main() {
println!("🔐 Hanzo Crypto - ARM Mac (M1/M2/M3) Test\n");
// Test ML-KEM (Pure Rust - no AVX2 issues!)
println!("✓ ML-KEM-768 (FIPS 203):");
{
use ml_kem::kem::{Decapsulate, Encapsulate};
use ml_kem::{KemCore, MlKem768};
use rand::thread_rng;
let mut rng = thread_rng();
let (dk, ek) = MlKem768::generate(&mut rng);
let (ct, ss1) = ek.encapsulate(&mut rng).unwrap();
let ss2 = dk.decapsulate(&ct).unwrap();
assert_eq!(ss1, ss2);
println!(" ✅ Key encapsulation works!");
}
// Test ML-DSA (Pure Rust)
println!("\n✓ ML-DSA-65 (FIPS 204):");
{
// ml-dsa is on rand_core 0.9 while ml-kem above is on 0.6, so the two
// blocks cannot share one RNG. Take ml-dsa's own re-export rather than
// add a second rand to the manifest.
use ml_dsa::signature::rand_core::{OsRng, TryRngCore};
use ml_dsa::signature::{Signer, Verifier};
use ml_dsa::{KeyGen, MlDsa65};
// OsRng is fallible in rand_core 0.9; unwrap_err gives the infallible
// CryptoRng that key_gen asks for.
let mut rng = OsRng.unwrap_err();
let keypair = MlDsa65::key_gen(&mut rng);
let message = b"Quantum-resistant on ARM!";
let signature = keypair.signing_key().sign(&message[..]);
keypair.verifying_key().verify(&message[..], &signature).unwrap();
println!(" ✅ Digital signatures work!");
}
// Test HQC
println!("\n✓ HQC-192:");
{
use pqcrypto_hqc::hqc192::*;
use pqcrypto_traits::kem::SharedSecret;
let (pk, sk) = keypair();
let (ss1, ct) = encapsulate(&pk);
let ss2 = decapsulate(&ct, &sk);
assert_eq!(ss1.as_bytes(), ss2.as_bytes());
println!(" ✅ Code-based crypto works!");
}
// Test BLAKE3
println!("\n✓ BLAKE3:");
{
let hash = blake3::hash(b"Fast hashing!");
println!(" ✅ Hash: {}", hash.to_hex()[..16].to_string());
}
// Test ChaCha20-Poly1305
println!("\n✓ ChaCha20-Poly1305:");
{
use chacha20poly1305::{
aead::{Aead, AeadCore, KeyInit, OsRng},
ChaCha20Poly1305,
};
let key = ChaCha20Poly1305::generate_key(&mut OsRng);
let nonce = ChaCha20Poly1305::generate_nonce(&mut OsRng);
let cipher = ChaCha20Poly1305::new(&key);
let ct = cipher.encrypt(&nonce, b"Secret".as_ref()).unwrap();
let pt = cipher.decrypt(&nonce, ct.as_ref()).unwrap();
assert_eq!(pt, b"Secret");
println!(" ✅ Stream cipher works!");
}
// Test AES-256-GCM
println!("\n✓ AES-256-GCM:");
{
use aes_gcm::{
aead::{Aead, AeadCore, KeyInit, OsRng},
Aes256Gcm,
};
let key = Aes256Gcm::generate_key(&mut OsRng);
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
let cipher = Aes256Gcm::new(&key);
let ct = cipher.encrypt(&nonce, b"Top Secret".as_ref()).unwrap();
let pt = cipher.decrypt(&nonce, ct.as_ref()).unwrap();
assert_eq!(pt, b"Top Secret");
println!(" ✅ Block cipher works!");
}
println!("\n🎉 All crypto algorithms work perfectly on ARM Mac!");
println!(" No AVX2 issues - Pure Rust FTW!");
}