use indicatif::ProgressBar;
use lazy_static::lazy_static;
use std::sync::Arc;
mod cipolla;
mod comfact_cn;
mod cube_root;
mod factorization;
mod gaa;
mod known_d;
mod known_phi;
mod leaked_crt_coefficient;
mod leaked_crt_exponent;
mod leaked_crt_exponents;
mod leaked_pq;
mod multi_key;
mod non_coprime_exp;
mod partial_d;
mod partial_prime;
mod prime_modulus;
mod small_e;
mod sum_pq;
mod wiener;
use crate::Factors;
use crate::{Parameters, Solution};
pub use cipolla::CipollaAttack;
pub use comfact_cn::ComfactCnAttack;
pub use cube_root::CubeRootAttack;
pub use factorization::*;
pub use gaa::GaaAttack;
pub use known_d::KnownDAttack;
pub use known_phi::KnownPhiAttack;
pub use leaked_crt_coefficient::LeakedCrtCoefficientAttack;
pub use leaked_crt_exponent::LeakedCrtExponentAttack;
pub use leaked_crt_exponents::LeakedCrtExponentsAttack;
pub use leaked_pq::LeakedPQAttack;
pub use multi_key::*;
pub use non_coprime_exp::NonCoprimeExpAttack;
pub use partial_d::PartialDAttack;
pub use partial_prime::PartialPrimeAttack;
pub use prime_modulus::PrimeModulusAttack;
pub use small_e::SmallEAttack;
pub use sum_pq::DiffPQAttack;
pub use sum_pq::SumPQAttack;
pub use wiener::WienerAttack;
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
pub enum Error {
#[error("Missing parameters")]
MissingParameters,
#[error("Unsuccessful attack")]
NotFound,
#[error(transparent)]
Key(crate::key::KeyError),
#[error("Partial factorization: {0:?}")]
PartialFactorization(Factors),
}
impl From<crate::key::KeyError> for Error {
fn from(e: crate::key::KeyError) -> Self {
match e {
crate::key::KeyError::FactorsAreNotPrimeNumbers(factors) => {
Error::PartialFactorization(factors)
}
_ => Error::Key(e),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AttackSpeed {
Fast,
Medium,
Slow,
}
impl PartialOrd for AttackSpeed {
fn partial_cmp(&self, other: &AttackSpeed) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for AttackSpeed {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
use crate::AttackSpeed::{Fast, Medium, Slow};
use std::cmp::Ordering::*;
match (self, other) {
(Fast, Fast) | (Medium, Medium) | (Slow, Slow) => Equal,
(Fast, _) => Less,
(_, Fast) => Greater,
(Medium, _) => Less,
(_, Medium) => Greater,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AttackKind {
Factorization,
KnownExtraInformation,
MultiKey,
}
impl PartialOrd for AttackKind {
fn partial_cmp(&self, other: &AttackKind) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for AttackKind {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
use crate::AttackKind::{Factorization, KnownExtraInformation, MultiKey};
use std::cmp::Ordering::*;
match (self, other) {
(Factorization, Factorization)
| (KnownExtraInformation, KnownExtraInformation)
| (MultiKey, MultiKey) => Equal,
(Factorization, _) => Less,
(_, Factorization) => Greater,
(KnownExtraInformation, MultiKey) => Less,
(MultiKey, KnownExtraInformation) => Greater,
}
}
}
pub trait Attack: std::fmt::Debug {
fn name(&self) -> &'static str;
fn speed(&self) -> AttackSpeed {
AttackSpeed::Medium
}
fn kind(&self) -> AttackKind {
AttackKind::Factorization
}
fn run(&self, params: &Parameters, pb: Option<&ProgressBar>) -> Result<Solution, Error>;
}
lazy_static! {
static ref _ATTACKS: Vec<Arc<dyn Attack + Sync + Send>> = vec![
Arc::new(CipollaAttack),
Arc::new(ComfactCnAttack),
Arc::new(CubeRootAttack),
Arc::new(DiffPQAttack),
Arc::new(GaaAttack),
Arc::new(KnownDAttack),
Arc::new(KnownPhiAttack),
Arc::new(LeakedCrtCoefficientAttack),
Arc::new(LeakedCrtExponentAttack),
Arc::new(LeakedCrtExponentsAttack),
Arc::new(LeakedPQAttack),
Arc::new(NonCoprimeExpAttack),
Arc::new(PartialDAttack),
Arc::new(PartialPrimeAttack),
Arc::new(PrimeModulusAttack),
Arc::new(SmallEAttack),
Arc::new(SumPQAttack),
Arc::new(WienerAttack),
];
pub static ref ATTACKS: Vec<Arc<dyn Attack + Sync + Send>> = {
let mut attacks = _ATTACKS.to_vec();
attacks.extend_from_slice(&FACTORIZATION_ATTACKS);
attacks.extend_from_slice(&MULTI_KEY_ATTACKS);
attacks
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unique_attacks() {
let mut attacks = ATTACKS.to_vec();
attacks.sort_by(|a, b| a.name().cmp(b.name()));
for (i, attack) in attacks.iter().enumerate() {
if i > 0 {
assert!(
attack.name() != attacks[i - 1].name(),
"Duplicated attack: {}",
attack.name()
);
}
}
}
}