diff --git a/.github/workflows/linux-tests.yml b/.github/workflows/linux-tests-on-nightly-toolchain.yml similarity index 96% rename from .github/workflows/linux-tests.yml rename to .github/workflows/linux-tests-on-nightly-toolchain.yml index a099db748..97be30df5 100644 --- a/.github/workflows/linux-tests.yml +++ b/.github/workflows/linux-tests-on-nightly-toolchain.yml @@ -1,4 +1,4 @@ -name: Linux Tests +name: Linux Tests On Rust Nightly Toolchain on: [push] jobs: diff --git a/.github/workflows/linux-tests-on-stable-toolchain b/.github/workflows/linux-tests-on-stable-toolchain new file mode 100644 index 000000000..a8873f467 --- /dev/null +++ b/.github/workflows/linux-tests-on-stable-toolchain @@ -0,0 +1,52 @@ +name: Linux Tests On Rust Stable Toolchain +on: [push] + +jobs: + test: + strategy: + matrix: + os: [ubuntu-latest] + runs-on: + - ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - uses: actions-rs/cargo@v1 + with: + command: build + args: --release --all-features + + - name: Install dependencies + run: | + pip install setuptools wheel + + - name: Build cryptatools + run: cargo build --all + + - name: Install cryptatools clis + run: cargo install --path ./cryptatools-cli + + - name: Run tests + run: | + cargo test --all + + - name: Generate documentation + run: | + cargo doc --package cryptatools-core --workspace --no-deps + + - name: Build and install Python Bindings + run: | + python3 ./cryptatools-core/setup.py bdist_wheel --verbose ; + pip3 install ./dist/* --force-reinstall ; + + - name: Test python bindings + run: | + python3 ./cryptatools-core/binding-testing/testing.py ; \ No newline at end of file diff --git a/cryptatools-core/Cargo.toml b/cryptatools-core/Cargo.toml index 95d93aa4c..874d9f20c 100644 --- a/cryptatools-core/Cargo.toml +++ b/cryptatools-core/Cargo.toml @@ -17,10 +17,16 @@ itertools = "*" uniffi_bindgen = "*" time = "*" rand = "*" -num-bigint = "*" num-traits = "*" num = "*" num-bigfloat = "*" +num-bigint = { version = "*", features = [] } #"prime", "rand" +num-bigint-dig = { version = "*", features = ["prime", "rand"], default-features=false } +num-integer = "*" + +indicatif = { version = "0.17", optional = true } +primal = "0.3" +thiserror = "1" [build-dependencies] uniffi = {version = "*", features = [ "build", "cli" ]} @@ -34,4 +40,4 @@ doc = true [[bin]] # This can be whatever name makes sense for your project, but the rest of this tutorial assumes uniffi-bindgen. name = "uniffi-bindgen" -path = "uniffi-bindgen.rs" +path = "uniffi-bindgen.rs" \ No newline at end of file diff --git a/cryptatools-core/src/cryptanalysis/common/rsa/common_modulus_attack.rs b/cryptatools-core/src/cryptanalysis/common/rsa/common_modulus_attack.rs index e69de29bb..3a4872b91 100644 --- a/cryptatools-core/src/cryptanalysis/common/rsa/common_modulus_attack.rs +++ b/cryptatools-core/src/cryptanalysis/common/rsa/common_modulus_attack.rs @@ -0,0 +1,24 @@ +//! Attack on RSA using common modulus attack. +use num_bigint::BigUint; + +struct CommonModulusAttack { + +} + +/// attack a common modulus on a public exponent in public key using Lenstra’s Elliptic Curve Factorization +impl CommonModulusAttack { + pub fn native_factorization(n: BigUint) -> Vec { + /*for i in n { + + }*/ + + vec![] + } + + pub fn attack(n: BigUint) -> Vec { + /*for i in n { + + }*/ + vec![] + } +} \ No newline at end of file diff --git a/cryptatools-core/src/lib.rs b/cryptatools-core/src/lib.rs index b6279530a..ee6482ad3 100644 --- a/cryptatools-core/src/lib.rs +++ b/cryptatools-core/src/lib.rs @@ -1,7 +1,9 @@ pub mod cryptanalysis; pub mod cryptography; pub mod utils; +pub mod maths; +use crate::maths::ECC; use crate::utils::alphabets::{Encoding, Alphabet, split_bytes_by_characters_representation, uniffy_opcode_group}; use crate::cryptography::classical::encryption::monoalphabetic_ciphers::caesar_number::CaesarNumberAlgorithm; use crate::cryptography::classical::encryption::transpositional_ciphers::columnar_transposition::ColumnarTranspositionAlgorithm; diff --git a/cryptatools-core/src/maths/ECC.rs b/cryptatools-core/src/maths/ECC.rs new file mode 100644 index 000000000..1f99fc052 --- /dev/null +++ b/cryptatools-core/src/maths/ECC.rs @@ -0,0 +1,478 @@ +//use num_bigint_dig as num_bigint; +use num_traits; + +use num_bigint_dig::{BigUint, BigInt}; +use num_bigint_dig::ModInverse; +use num_bigint_dig::prime::probably_prime; +use num_bigint_dig::ToBigInt; +use num_bigint_dig::RandBigInt; +use num_traits::Pow; +use num_integer::Integer; + +#[cfg(feature = "progress-bar")] +use indicatif::ProgressBar; +use primal::Primes; +use std::collections::HashMap; + + +struct ECC { + +} + +impl ECC { + +} + +#[derive(Debug, Clone, Default)] +pub struct Point { + /// X coordinate of the Point + pub x_cord: BigInt, + /// Z coordinate of the Point + pub z_cord: BigInt, + /// Parameter of the elliptic curve in Montgomery form + pub a_24: BigInt, + /// modulus + pub modulus: BigInt, +} + +impl Point { + /// Initial parameters for the Point struct. + /// + /// # Parameters + /// + /// - `x_cord`: X coordinate of the Point + /// - `z_cord`: Z coordinate of the Point + /// - `a_24`: Parameter of the elliptic curve in Montgomery form + /// - `mod`: modulus + pub fn new(x_cord: BigInt, z_cord: BigInt, a_24: BigInt, modulus: BigInt) -> Point { + Point { + x_cord, + z_cord, + a_24, + modulus, + } + } + + /// Adds two points `self` and `Q` where `diff = self - Q`. + /// + /// This algorithm requires 6 multiplications. The assumption is that `self.x_cord * Q.x_cord * (self.x_cord - Q.x_cord) != 0`. + /// Using this algorithm speeds up the addition by reducing the number of multiplications required. + /// + /// The `mont_ladder` algorithm is constructed in a way that the difference between intermediate points is always equal to the initial point. + /// So, we always know what the difference between the point is. + /// + /// # Parameters + /// + /// - `Q`: Point on the curve in Montgomery form. + /// - `diff`: `self - Q` + /// + /// ``` + /// use num_bigint::{BigUint, BigInt}; + /// use num_bigint_dig as num_bigint; + /// use num_bigint_dig::ModInverse; + /// use num_traits; + /// use num_traits::cast::FromPrimitive; + /// + /// use cryptatools_core::maths::ECC::*; + /// let p1 = Point::new(BigInt::from_u64(11).unwrap(), BigInt::from_u64(16).unwrap(), BigInt::from_u64(7).unwrap(), BigInt::from_u64(29).unwrap()); + /// let p2 = Point::new(BigInt::from_u64(13).unwrap(), BigInt::from_u64(10).unwrap(), BigInt::from_u64(7).unwrap(), BigInt::from_u64(29).unwrap()); + /// let p3 = p2.add(&p1, &p1); + /// assert_eq!(p3.x_cord, BigInt::from_u64(23).unwrap()); + /// assert_eq!(p3.z_cord, BigInt::from_u64(17).unwrap()); + /// ``` + pub fn add(&self, q: &Point, diff: &Point) -> Point { + let u = BigInt::from(&self.x_cord - &self.z_cord) * BigInt::from(&q.x_cord + &q.z_cord); + let v = BigInt::from(&self.x_cord + &self.z_cord) * BigInt::from(&q.x_cord - &q.z_cord); + let add = BigInt::from(&u + &v); + let subt = u - v; + let x_cord = BigInt::from(&diff.z_cord * &add) * &add % &self.modulus; + let z_cord = BigInt::from(&diff.x_cord * &subt) * &subt % &self.modulus; + + Point::new(x_cord, z_cord, self.a_24.clone(), self.modulus.clone()) + } + + /// Doubles a point in an elliptic curve in Montgomery form. + /// + /// ``` + /// use num_bigint::{BigUint, BigInt}; + /// use num_bigint_dig as num_bigint; + /// use num_bigint_dig::ModInverse; + /// use num_traits; + /// use num_traits::cast::FromPrimitive; + /// use cryptatools_core::maths::ECC::*; + /// + /// let p1 = Point::new(BigInt::from_u64(11).unwrap(), BigInt::from_u64(16).unwrap(), BigInt::from_u64(7).unwrap(), BigInt::from_u64(29).unwrap()); + /// let p2 = p1.double(); + /// assert_eq!(p2.x_cord, BigInt::from(13)); + /// assert_eq!(p2.z_cord, BigInt::from(10)); + /// ``` + /// + /// ``` + /// use num_bigint::{BigUint, BigInt}; + /// use num_bigint_dig as num_bigint; + /// use num_bigint_dig::ModInverse; + /// use num_traits; + /// use num_traits::cast::FromPrimitive; + /// use cryptatools_core::maths::ECC::*; + /// + /// let modulus: BigInt = BigInt::from(101); + /// let a: BigInt = BigInt::from(10); + /// let a_24: BigInt = (a + BigInt::from(2)) * BigInt::from(4).mod_inverse(&modulus).unwrap(); + /// let p1 = Point::new(BigInt::from(10), BigInt::from(17), a_24.clone(), modulus.clone()); + /// let p2 = p1.double(); + /// assert_eq!(p2, Point::new(BigInt::from(68), BigInt::from(56), a_24.clone(), modulus.clone())); + /// ``` + /// + pub fn double(&self) -> Point { + let u = BigInt::from(&self.x_cord + &self.z_cord).pow(2 as u32); + let v = BigInt::from(&self.x_cord - &self.z_cord).pow(2 as u32); + let diff = BigInt::from(u.clone() - v.clone()); + let x_cord = (u * &v) % &self.modulus; + let z_cord = ((v + &self.a_24 * &diff) * diff) % &self.modulus; + + Point::new(x_cord, z_cord, self.a_24.clone(), self.modulus.clone()) + } + + /// Scalar multiplication of a point in Montgomery form + /// using Montgomery Ladder Algorithm. + /// A total of 11 multiplications are required in each step of this + /// algorithm. + /// + /// # Parameters + /// + /// - `k`: The positive integer multiplier + /// + /// ``` + /// use num_bigint::{BigUint, BigInt}; + /// use num_bigint_dig as num_bigint; + /// use num_bigint_dig::ModInverse; + /// use num_traits; + /// use num_traits::cast::FromPrimitive; + /// use cryptatools_core::maths::ECC::*; + /// + /// let p1 = Point::new(BigInt::from(11), BigInt::from(16), BigInt::from(7), BigInt::from(29)); + /// let p3 = p1.mont_ladder(&BigInt::from(3)); + /// assert_eq!(p3.x_cord, BigInt::from(23)); + /// assert_eq!(p3.z_cord, BigInt::from(17)); + /// ``` + pub fn mont_ladder(&self, k: &BigInt) -> Point { + let mut q = self.clone(); + let mut r = self.double(); + + for i in format!("{:b}", k)[1..].chars() { + if i == '1' { + q = r.add(&q, self); + r = r.double(); + } else { + r = q.add(&r, self); + q = q.double(); + } + } + q + } +} + +impl PartialEq for Point { + /// Two points are equal if X/Z of both points are equal. + fn eq(&self, other: &Self) -> bool { + if self.a_24 != other.a_24 || self.modulus != other.modulus { + false + } else { + self.z_cord.clone().mod_inverse(&self.modulus).unwrap() * &self.x_cord % &self.modulus + == other.z_cord.clone().mod_inverse(&self.modulus).unwrap() * &other.x_cord + % &self.modulus + } + } +} + + + + + + + + +/// Error occured during ecm factorization. +#[derive(thiserror::Error, Debug)] +pub enum Error { + /// Bounds should be an even integer. + #[error("Bounds should be an even integer")] + BoundsNotEven, + /// Too small bounds. + #[error("Too small bounds")] + BoundsTooSmall, + /// The factorization failed. + #[error("The factorization failed")] + ECMFailed, + /// The number is prime. + #[error("The number is prime")] + NumberIsPrime, +} + +/// Returns one factor of n using Lenstra's 2 Stage Elliptic curve Factorization +/// with Suyama's Parameterization. Here Montgomery arithmetic is used for fast +/// computation of addition and doubling of points in elliptic curve. +/// +/// This ECM method considers elliptic curves in Montgomery form (E : b*y^2*z = x^3 + a*x^2*z + x*z^2) +/// and involves elliptic curve operations (mod N), where the elements in Z are reduced (mod N). +/// Since N is not a prime, E over FF(N) is not really an elliptic curve but we can still do point additions +/// and doubling as if FF(N) was a field. +/// +/// Stage 1: The basic algorithm involves taking a random point (P) on an elliptic curve in FF(N). +/// The compute k*P using Montgomery ladder algorithm. +/// Let q be an unknown factor of N. Then the order of the curve E, |E(FF(q))|, +/// might be a smooth number that divides k. Then we have k = l * |E(FF(q))| +/// for some l. For any point belonging to the curve E, |E(FF(q))|*P = O, +/// hence k*P = l*|E(FF(q))|*P. Thus kP.z_cord = 0 (mod q), and the unknown factor of N (q) +/// can be recovered by taking gcd(kP.z_cord, N). +/// +/// Stage 2: This is a continuation of Stage 1 if k*P != O. The idea is to utilize +/// the fact that even if kP != 0, the value of k might miss just one large prime divisor +/// of |E(FF(q))|. In this case, we only need to compute the scalar multiplication by p +/// to get p*k*P = O. Here a second bound B2 restricts the size of possible values of p. +/// +/// Parameters: +/// +/// - `n`: Number to be factored. +/// - `B1`: Stage 1 Bound. +/// - `B2`: Stage 2 Bound. +/// - `max_curve`: Maximum number of curves generated. +/// - `rgen`: Random number generator. +pub fn ecm_one_factor( + n: &BigInt, + b1: usize, + b2: usize, + max_curve: usize, + rgen: u32, + #[cfg(feature = "progress-bar")] pb: Option<&ProgressBar>, +) -> Result { + if b1 % 2 != 0 || b2 % 2 != 0 { + return Err(Error::BoundsNotEven); + } + + if probably_prime(&n.to_biguint().unwrap(), 0) == true { + return Err(Error::NumberIsPrime); + } + + #[cfg(feature = "progress-bar")] + if let Some(pb) = pb { + pb.set_length(max_curve as u64); + pb.set_position(0); + } + + let mut curve = 0; + let d = (b2 as f64).sqrt() as usize; + let two_d = 2 * d; + let mut beta: Vec = vec![BigInt::default(); d + 1]; + let mut s: Vec = vec![Point::default(); d + 1]; + let mut k = BigInt::from(1); + + for p in Primes::all().take_while(|&p| p <= b1) { + k *= p.pow(b1.ilog(p)); + } + + while curve <= max_curve { + curve += 1; + + #[cfg(feature = "progress-bar")] + if let Some(pb) = pb { + pb.inc(1); + } + + // Suyama's Parametrization + let sigma = BigInt::from(rand::thread_rng().gen_biguint_below(&BigUint::from(rgen))); //let sigma = (n - BigInt::from(1).to_biguint().unwrap()).to_bigint().unwrap().gen_biguint_below(&BigUint::from(rgen)); + let u = (&sigma * &sigma - BigInt::from(5)) % n; + let v : BigInt = (BigInt::from(4) * sigma) % n; + let diff = v.clone() - u.clone(); + let u_3 : BigInt = u.clone().pow(3 as u32) % n; + + let c = match (BigInt::from(4) * &u_3 * &v).mod_inverse(n) { + Some(c) => { + (diff.modpow(&BigInt::from(3), n) * (BigInt::from(4) * &u + &v) * c + - BigInt::from(2)) + % n + } + _ => return Ok((BigInt::from(4) * u_3 * v).gcd(n)), + }; + + let a24 = (c + 2) * BigInt::from(4).mod_inverse(n).unwrap() % n; + let q = Point::new(u_3, v.pow(3 as u32) % n, a24, n.clone()); + let q = q.mont_ladder(&k); + let g = q.z_cord.clone().gcd(n); + + // Stage 1 factor + if &g != n && g != BigInt::from(1) { + return Ok(g); + } + + // Stage 1 failure. Q.z = 0, Try another curve + if &g == n { + continue; + } + + // Stage 2 - Improved Standard Continuation + s[1] = q.double(); + s[2] = s[1].double(); + beta[1] = BigInt::from(&s[1].x_cord * &s[1].z_cord) % n; + beta[2] = BigInt::from(&s[2].x_cord * &s[2].z_cord) % n; + + for d in 3..=(d) { + s[d] = s[d - 1].add(&s[1], &s[d - 2]); + beta[d] = BigInt::from(&s[d].x_cord * &s[d].z_cord) % n; + } + + let mut g = BigInt::from(1); + let b = b1 - 1; + let mut t = q.mont_ladder(&BigInt::from(b - two_d)); + let mut r = q.mont_ladder(&BigInt::from(b)); + + let mut primes = Primes::all().skip_while(|&q| q < b); + for rr in (b..b2).step_by(two_d) { + let alpha = BigInt::from(&r.x_cord * &r.z_cord) % n; + for q in primes.by_ref().take_while(|&q| q <= rr + two_d) { + let delta = (q - rr) / 2; + let f = BigInt::from(&r.x_cord - &s[d].x_cord) + * BigInt::from(&r.z_cord + &s[d].z_cord) + - &alpha + + &beta[delta]; + g = (g * f) % n; + } + // Swap + std::mem::swap(&mut t, &mut r); + r = r.add(&s[d], &t); + } + g = g.gcd(n); + + // Stage 2 Factor found + if &g != n && g != BigInt::from(1) { + return Ok(g); + } + } + + // ECM failed, Increase the bounds + Err(Error::ECMFailed) +} + +fn optimal_b1(digits: usize) -> usize { + match digits { + 1..=15 => 2000, + 16..=20 => 11000, + 21..=25 => 50000, + 26..=30 => 250000, + 31..=35 => 1000000, + 36..=40 => 3000000, + 41..=45 => 11000000, + 46..=50 => 44000000, + 51..=55 => 110000000, + 56..=60 => 260000000, + 61..=65 => 850000000, + 66..=70 => 2900000000, + _ => 2900000000, + } +} + +/// Performs factorization using Lenstra's Elliptic curve method. +/// +/// This function repeatedly calls `ecm_one_factor` to compute the factors +/// of n. First all the small factors are taken out using trial division. +/// Then `ecm_one_factor` is used to compute one factor at a time. +/// +/// # Parameters +/// +/// - `n`: Number to be factored. +/// +/// +/// ``` +/// use num_bigint::{BigUint, BigInt}; +/// use num_bigint_dig as num_bigint; +/// use num_bigint_dig::ModInverse; +/// use num_traits; +/// use num_traits::cast::FromPrimitive; +/// +/// use std::collections::HashMap; +/// use std::str::FromStr; +/// +/// use cryptatools_core::maths::ECC::*; +/// +/// // assert_eq!(BigInt::from_str("398883434337287"), ); +/// +/// assert_eq!( +/// ecm(&BigInt::from_str("398883434337287").unwrap()).unwrap(), +/// HashMap::from([ +/// (BigInt::from_str("99476569").unwrap(), 1), +/// (BigInt::from_str("4009823").unwrap(), 1), +/// ]) +/// ); +/// ``` +pub fn ecm( + n: &BigInt, + #[cfg(feature = "progress-bar")] pb: Option<&ProgressBar>, +) -> Result, Error> { + ecm_with_params( + n, + optimal_b1(n.to_string().len()), + 100000, + 200, + 1234, + #[cfg(feature = "progress-bar")] + pb, + ) +} + +/// Performs factorization using Lenstra's Elliptic curve method. +/// +/// This function repeatedly calls `ecm_one_factor` to compute the factors +/// of n. First all the small factors are taken out using trial division. +/// Then `ecm_one_factor` is used to compute one factor at a time. +/// +/// # Parameters +/// +/// - `n`: Number to be factored. +/// - `B1`: Stage 1 Bound. +/// - `B2`: Stage 2 Bound. +/// - `max_curve`: Maximum number of curves generated. +/// - `seed`: Initialize pseudorandom generator. +pub fn ecm_with_params( + n: &BigInt, + b1: usize, + b2: usize, + max_curve: usize, + seed: usize, + #[cfg(feature = "progress-bar")] pb: Option<&ProgressBar>, +) -> Result, Error> { + let mut factors = HashMap::new(); + + let mut n: BigInt = n.clone(); + for prime in Primes::all().take(100_000) { + if n.is_multiple_of(&BigInt::from(prime)) { + let prime = BigInt::from(prime.clone()); + while n.is_multiple_of(&prime) { + n /= prime.clone(); + *factors.entry(prime.clone()).or_insert(0) += 1; + } + } + } + + //let mut rand_state = RandState::new(); + //rand_state.seed(&seed.into()); + + while n.to_bigint().unwrap() != BigInt::from(1) { + let factor = ecm_one_factor( + &n.to_bigint().unwrap(), + b1, + b2, + max_curve, + 16,// 16 is an hardcoded random generated number + #[cfg(feature = "progress-bar")] + pb, + ) + .unwrap_or(n.to_bigint().unwrap().clone()); + + while n.is_multiple_of(&factor) { + n /= &factor; + *factors.entry(factor.clone()).or_insert(0) += 1; + } + } + + Ok(factors) +} \ No newline at end of file diff --git a/cryptatools-core/src/maths/factoring.rs b/cryptatools-core/src/maths/factoring.rs new file mode 100644 index 000000000..c9303af0d --- /dev/null +++ b/cryptatools-core/src/maths/factoring.rs @@ -0,0 +1,25 @@ +//! Any Factorization method will be supplied here. +use num_bigint::BigUint; + +struct Factorization { + +} + +impl Factorization { + pub fn native_factorization(n: BigUint) -> Vec { + /*for i in n { + + }*/ + vec![] + } + + /// Lenstra’s Elliptic Curve Factorization using BigUint input + /// + /// + pub fn elnstra_elliptic_curve_factorization_method(n: BigUint) -> Vec { + /*for i in n { + + }*/ + vec![] + } +} \ No newline at end of file diff --git a/cryptatools-core/src/maths/is_prime.rs b/cryptatools-core/src/maths/is_prime.rs new file mode 100644 index 000000000..6c1bbc390 --- /dev/null +++ b/cryptatools-core/src/maths/is_prime.rs @@ -0,0 +1,18 @@ +//! Check if is prime + +use num_bigint::BigUint; + +pub fn is_prime(n: BigUint) -> bool { + /*if n <= 1 { + return false; + } + for a in 2..n { + if n % a == 0 { + return false; + } + } + true + */ + + false +} \ No newline at end of file diff --git a/cryptatools-core/src/maths/mod.rs b/cryptatools-core/src/maths/mod.rs new file mode 100644 index 000000000..fe5406c40 --- /dev/null +++ b/cryptatools-core/src/maths/mod.rs @@ -0,0 +1,3 @@ +pub mod factoring; +pub mod is_prime; +pub mod ECC; \ No newline at end of file diff --git a/cryptatools-core/src/utils/alphabets.rs b/cryptatools-core/src/utils/alphabets.rs index 04b15fd90..610f60fa0 100644 --- a/cryptatools-core/src/utils/alphabets.rs +++ b/cryptatools-core/src/utils/alphabets.rs @@ -1,6 +1,5 @@ use itertools::Itertools; use bimap::btree::BiBTreeMap; -//use std::assert_matches::assert_matches; ///``` /// use cryptatools_core::utils::{convert::Encode, alphabets::split_bytes_by_characters_representation, alphabets::Alphabet}; @@ -873,9 +872,6 @@ impl Alphabet { /// Returns: a converted human readable set of character text in the same order as the original unconverted text. /// /// ``` - /// #![feature(assert_matches)] - /// - /// use std::assert_matches::assert_matches; /// use cryptatools_core::utils::{convert::Encode, alphabets::split_bytes_by_characters_representation, alphabets::Alphabet}; /// use cryptatools_core::utils::alphabets::Encoding; /// diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index d15f576fe..09b25ec17 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -11,6 +11,7 @@ - [Contribute](./chapter_1/3-contribute.md) - [Global Usages](./chapter_1/4-usage.md) - [Node Connection](./chapter_1/usages/1-Interacting-with-blockchain-with-nodejs.md) +- [public exponent common modulus attack](./chapter_1/usages/2-breaking-rsa.md) # II - How To diff --git a/docs/src/chapter_1/usages/2-breaking-rsa.md b/docs/src/chapter_1/usages/2-breaking-rsa.md new file mode 100644 index 000000000..fdefa53c7 --- /dev/null +++ b/docs/src/chapter_1/usages/2-breaking-rsa.md @@ -0,0 +1,18 @@ +Let's create a python script in order to generate a public key with a wrong exponent: + + +```shell +pip install rsa +``` + + +```python +import rsa + +(pubkey, privkey) = rsa.newkeys(4096, accurate=True, exponent=1) + +with open('private.pem', mode='rb') as privatefile: + keydata = privatefile.read() +privkey = rsa.PrivateKey.load_pkcs1(keydata) +``` +