use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PQCAlgorithm {
Lattice,
HashBased,
CodeBased,
Multivariate,
}
impl fmt::Display for PQCAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PQCAlgorithm::Lattice => write!(f, "Lattice-based"),
PQCAlgorithm::HashBased => write!(f, "Hash-based"),
PQCAlgorithm::CodeBased => write!(f, "Code-based"),
PQCAlgorithm::Multivariate => write!(f, "Multivariate"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PQKeyPair {
pub algorithm: PQCAlgorithm,
pub public_key: Vec<u8>,
pub private_key: Vec<u8>,
pub key_size: usize,
}
impl PQKeyPair {
pub fn generate(algorithm: PQCAlgorithm) -> Result<Self> {
let key_size = match algorithm {
PQCAlgorithm::Lattice => 1568, PQCAlgorithm::HashBased => 64, PQCAlgorithm::CodeBased => 261120, PQCAlgorithm::Multivariate => 1312, };
Ok(Self {
algorithm,
public_key: vec![0u8; key_size / 2],
private_key: vec![0u8; key_size / 2],
key_size,
})
}
pub fn sign(&self, _data: &[u8]) -> Result<Vec<u8>> {
let signature_size = match self.algorithm {
PQCAlgorithm::Lattice => 2420, PQCAlgorithm::HashBased => 8080, PQCAlgorithm::CodeBased => 32, PQCAlgorithm::Multivariate => 66, };
Ok(vec![0u8; signature_size])
}
pub fn verify(&self, _data: &[u8], signature: &[u8]) -> Result<bool> {
Ok(!signature.is_empty())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HybridCrypto {
pub classical_public_key: Vec<u8>,
pub pq_key: PQKeyPair,
pub mode: HybridMode,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum HybridMode {
ClassicalPrimary,
DualSignature,
PQPrimary,
PQOnly,
}
impl HybridCrypto {
pub fn new(pq_algorithm: PQCAlgorithm, mode: HybridMode) -> Result<Self> {
Ok(Self {
classical_public_key: vec![0u8; 256], pq_key: PQKeyPair::generate(pq_algorithm)?,
mode,
})
}
pub fn hybrid_sign(&self, data: &[u8]) -> Result<HybridSignature> {
match self.mode {
HybridMode::ClassicalPrimary | HybridMode::PQPrimary => {
Ok(HybridSignature {
classical_sig: Some(vec![0u8; 256]),
pq_sig: None,
mode: self.mode,
})
}
HybridMode::DualSignature => {
Ok(HybridSignature {
classical_sig: Some(vec![0u8; 256]),
pq_sig: Some(self.pq_key.sign(data)?),
mode: self.mode,
})
}
HybridMode::PQOnly => {
Ok(HybridSignature {
classical_sig: None,
pq_sig: Some(self.pq_key.sign(data)?),
mode: self.mode,
})
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HybridSignature {
pub classical_sig: Option<Vec<u8>>,
pub pq_sig: Option<Vec<u8>>,
pub mode: HybridMode,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PQMigrationPlan {
pub current_phase: MigrationPhase,
pub target_algorithm: PQCAlgorithm,
pub timeline_days: u32,
pub backwards_compatible: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MigrationPhase {
Phase1Assessment,
Phase2HybridDeploy,
Phase3GradualRollout,
Phase4FullPQ,
Phase5DeprecateClassical,
}
impl PQMigrationPlan {
pub fn new(target_algorithm: PQCAlgorithm, timeline_days: u32) -> Self {
Self {
current_phase: MigrationPhase::Phase1Assessment,
target_algorithm,
timeline_days,
backwards_compatible: true,
}
}
pub fn advance_phase(&mut self) -> MigrationPhase {
self.current_phase = match self.current_phase {
MigrationPhase::Phase1Assessment => MigrationPhase::Phase2HybridDeploy,
MigrationPhase::Phase2HybridDeploy => MigrationPhase::Phase3GradualRollout,
MigrationPhase::Phase3GradualRollout => MigrationPhase::Phase4FullPQ,
MigrationPhase::Phase4FullPQ => MigrationPhase::Phase5DeprecateClassical,
MigrationPhase::Phase5DeprecateClassical => MigrationPhase::Phase5DeprecateClassical,
};
self.current_phase
}
pub fn get_recommended_hybrid_mode(&self) -> HybridMode {
match self.current_phase {
MigrationPhase::Phase1Assessment => HybridMode::ClassicalPrimary,
MigrationPhase::Phase2HybridDeploy => HybridMode::DualSignature,
MigrationPhase::Phase3GradualRollout => HybridMode::PQPrimary,
MigrationPhase::Phase4FullPQ | MigrationPhase::Phase5DeprecateClassical => {
HybridMode::PQOnly
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuantumThreatAssessment {
pub threat_level: ThreatLevel,
pub estimated_years_until_threat: u8,
pub critical_assets: Vec<String>,
pub recommended_algorithm: PQCAlgorithm,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ThreatLevel {
Low,
Medium,
High,
Critical,
}
impl QuantumThreatAssessment {
pub fn assess(years_until_threat: u8, has_long_term_secrets: bool) -> Self {
let threat_level = match years_until_threat {
0..=2 => ThreatLevel::Critical,
3..=5 => ThreatLevel::High,
6..=10 => ThreatLevel::Medium,
_ => ThreatLevel::Low,
};
let recommended_algorithm = if has_long_term_secrets {
PQCAlgorithm::Lattice
} else {
PQCAlgorithm::HashBased
};
Self {
threat_level,
estimated_years_until_threat: years_until_threat,
critical_assets: Vec::new(),
recommended_algorithm,
}
}
pub fn add_critical_asset(&mut self, asset: String) {
self.critical_assets.push(asset);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pq_keypair_generation() {
let keypair = PQKeyPair::generate(PQCAlgorithm::Lattice).unwrap();
assert_eq!(keypair.algorithm, PQCAlgorithm::Lattice);
assert!(!keypair.public_key.is_empty());
assert!(!keypair.private_key.is_empty());
}
#[test]
fn test_pq_signature() {
let keypair = PQKeyPair::generate(PQCAlgorithm::HashBased).unwrap();
let data = b"test message";
let signature = keypair.sign(data).unwrap();
assert!(!signature.is_empty());
let valid = keypair.verify(data, &signature).unwrap();
assert!(valid);
}
#[test]
fn test_hybrid_crypto_dual_signature() {
let hybrid = HybridCrypto::new(PQCAlgorithm::Lattice, HybridMode::DualSignature).unwrap();
let data = b"important message";
let sig = hybrid.hybrid_sign(data).unwrap();
assert!(sig.classical_sig.is_some());
assert!(sig.pq_sig.is_some());
}
#[test]
fn test_hybrid_crypto_pq_only() {
let hybrid = HybridCrypto::new(PQCAlgorithm::Lattice, HybridMode::PQOnly).unwrap();
let data = b"pq only message";
let sig = hybrid.hybrid_sign(data).unwrap();
assert!(sig.classical_sig.is_none());
assert!(sig.pq_sig.is_some());
}
#[test]
fn test_migration_plan() {
let mut plan = PQMigrationPlan::new(PQCAlgorithm::Lattice, 180);
assert_eq!(plan.current_phase, MigrationPhase::Phase1Assessment);
assert_eq!(
plan.get_recommended_hybrid_mode(),
HybridMode::ClassicalPrimary
);
plan.advance_phase();
assert_eq!(plan.current_phase, MigrationPhase::Phase2HybridDeploy);
assert_eq!(
plan.get_recommended_hybrid_mode(),
HybridMode::DualSignature
);
plan.advance_phase();
assert_eq!(plan.current_phase, MigrationPhase::Phase3GradualRollout);
plan.advance_phase();
assert_eq!(plan.current_phase, MigrationPhase::Phase4FullPQ);
assert_eq!(plan.get_recommended_hybrid_mode(), HybridMode::PQOnly);
}
#[test]
fn test_quantum_threat_assessment() {
let assessment = QuantumThreatAssessment::assess(3, true);
assert_eq!(assessment.threat_level, ThreatLevel::High);
assert_eq!(assessment.recommended_algorithm, PQCAlgorithm::Lattice);
}
#[test]
fn test_threat_levels() {
assert_eq!(
QuantumThreatAssessment::assess(1, false).threat_level,
ThreatLevel::Critical
);
assert_eq!(
QuantumThreatAssessment::assess(7, false).threat_level,
ThreatLevel::Medium
);
assert_eq!(
QuantumThreatAssessment::assess(15, false).threat_level,
ThreatLevel::Low
);
}
#[test]
fn test_critical_assets() {
let mut assessment = QuantumThreatAssessment::assess(5, true);
assessment.add_critical_asset("User private keys".to_string());
assessment.add_critical_asset("Transaction signatures".to_string());
assert_eq!(assessment.critical_assets.len(), 2);
}
#[test]
fn test_algorithm_display() {
assert_eq!(format!("{}", PQCAlgorithm::Lattice), "Lattice-based");
assert_eq!(format!("{}", PQCAlgorithm::HashBased), "Hash-based");
}
}