101 lines
3.2 KiB
Rust
101 lines
3.2 KiB
Rust
use crate::rsa;
|
|
use num_bigint::BigUint;
|
|
use openssl::bn::BigNum;
|
|
use openssl::bn::BigNumContext;
|
|
use openssl::error::ErrorStack;
|
|
use openssl::sha::sha256;
|
|
|
|
pub fn challenge41() -> Option<()> {
|
|
let (public_key, private_key) = rsa::rsa_gen_keys().ok()?;
|
|
|
|
let i = BigNum::from_u32(1337).ok()?;
|
|
let c = rsa::rsa_encrypt_unpadded(&i, &public_key).ok()?;
|
|
let m = rsa::rsa_decrypt_unpadded(&c, &private_key).ok()?;
|
|
assert_eq!(i, m, "rsa is broken");
|
|
|
|
let mut ctx = BigNumContext::new().ok()?;
|
|
// Let S be a random number > 1 mod N. Doesn't matter what.
|
|
let mut s = BigNum::new().ok()?;
|
|
public_key.n.rand_range(&mut s).ok()?;
|
|
// C' = ((S**E mod N) C) mod N
|
|
let mut c2 = BigNum::new().ok()?;
|
|
c2.mod_exp(&s, &public_key.e, &public_key.n, &mut ctx)
|
|
.ok()?;
|
|
let c2 = &(&c2 * &c) % &public_key.n;
|
|
let p2 = rsa::rsa_decrypt_unpadded(&c2, &private_key).ok()?;
|
|
|
|
// P'
|
|
// P = --- mod N
|
|
// S
|
|
let p2 = &(&p2 * &rsa::invmod(&s, &public_key.n).ok()?) % &public_key.n;
|
|
assert_eq!(i, p2, "message recovery oracle failed");
|
|
|
|
println!("[okay] Challenge 41: implement unpadded message recovery oracle");
|
|
Some(())
|
|
}
|
|
|
|
pub fn challenge42() -> Option<()> {
|
|
let (public_key, private_key) = rsa::rsa_gen_keys().ok()?;
|
|
|
|
let i = BigNum::from_u32(1337).ok()?;
|
|
let c = rsa::rsa_encrypt(&i, &public_key).ok()?;
|
|
let m = rsa::rsa_decrypt(&c, &private_key).ok()?;
|
|
assert_eq!(i, m, "rsa is broken");
|
|
|
|
let m = "a message to verify";
|
|
let sig = rsa::rsa_sign(&m, &private_key).ok()?;
|
|
let sig_ok = rsa::rsa_verify(&m, &public_key, &sig).ok()?;
|
|
assert!(sig_ok, "RSA verify does not work");
|
|
assert!(
|
|
rsa::rsa_verify("other message", &public_key, &sig).ok()? == false,
|
|
"RSA verify does not work"
|
|
);
|
|
|
|
let sig_ok = rsa::rsa_verify_insecure(&m, &public_key, &sig).ok()?;
|
|
assert!(sig_ok, "RSA verify does not work");
|
|
assert!(
|
|
rsa::rsa_verify_insecure("other message", &public_key, &sig).ok()? == false,
|
|
"RSA verify does not work"
|
|
);
|
|
|
|
fn cube_root(n: &BigNum) -> Result<BigNum, ErrorStack> {
|
|
let b = BigUint::from_bytes_be(&n.to_vec());
|
|
let b = b.nth_root(3);
|
|
BigNum::from_slice(&b.to_bytes_be())
|
|
}
|
|
|
|
fn _cube(n: &BigNum) -> BigNum {
|
|
n * &(n * n)
|
|
}
|
|
|
|
pub fn rsa_fake_sign(m: &str) -> Result<BigNum, ErrorStack> {
|
|
let hash = sha256(m.as_bytes());
|
|
let mut v = vec![0x0, 0x1, 0xff, 0x0];
|
|
v.append(&mut hash.to_vec());
|
|
while v.len() < 128 {
|
|
v.push(0);
|
|
}
|
|
|
|
// Add one to the cube root to ensure that when the number is
|
|
// cubed again it contains the desired signature.
|
|
let sig_cubed = BigNum::from_slice(&v)?;
|
|
let mut sig = cube_root(&sig_cubed)?;
|
|
sig.add_word(1)?;
|
|
|
|
Ok(sig)
|
|
}
|
|
|
|
let m = "hi mom";
|
|
let sig = rsa_fake_sign(&m).ok()?;
|
|
let sig_ok = rsa::rsa_verify_insecure(&m, &public_key, &sig).ok()?;
|
|
assert!(sig_ok, "RSA fake sign does not work");
|
|
|
|
println!("[okay] Challenge 42: Bleichenbacher's e=3 RSA Attack");
|
|
Some(())
|
|
}
|
|
|
|
pub fn challenge43() -> Option<()> {
|
|
println!("[xxxx] Challenge 43: TBD");
|
|
Some(())
|
|
}
|