Finish implementation of Bleichenbacher's e=3 RSA Attack finally
This commit is contained in:
35
src/rsa.rs
35
src/rsa.rs
@@ -210,46 +210,45 @@ pub fn rsa_decrypt_str(c: &BigNum, p: &RsaPrivateKey) -> Result<String, ErrorSta
|
||||
Ok(String::from(std::str::from_utf8(&m.to_vec()).unwrap()))
|
||||
}
|
||||
|
||||
pub fn rsa_sign(m: &str, p: &RsaPublicKey) -> Result<BigNum, ErrorStack> {
|
||||
pub fn rsa_sign(m: &str, p: &RsaPrivateKey) -> Result<BigNum, ErrorStack> {
|
||||
let hash = sha256(m.as_bytes());
|
||||
let m = BigNum::from_slice(&hash)?;
|
||||
rsa_encrypt(&m, p)
|
||||
let m = rsa_padding_add_pkcs1(&m, p.n.num_bytes())?;
|
||||
rsa_decrypt_unpadded(&m, p)
|
||||
}
|
||||
|
||||
pub fn rsa_verify(m: &str, p: &RsaPrivateKey, signature: &BigNum) -> Result<bool, ErrorStack> {
|
||||
pub fn rsa_verify(m: &str, p: &RsaPublicKey, signature: &BigNum) -> Result<bool, ErrorStack> {
|
||||
let hash = BigNum::from_slice(&sha256(m.as_bytes()))?;
|
||||
let m = rsa_decrypt(signature, p)?;
|
||||
let m = rsa_encrypt_unpadded(signature, p)?;
|
||||
let m = rsa_padding_remove_pkcs1(&m, p.n.num_bytes())?;
|
||||
Ok(m == hash)
|
||||
}
|
||||
|
||||
pub fn rsa_verify_insecure(
|
||||
m: &str,
|
||||
p: &RsaPrivateKey,
|
||||
p: &RsaPublicKey,
|
||||
signature: &BigNum,
|
||||
) -> Result<bool, ErrorStack> {
|
||||
let hash = BigNum::from_slice(&sha256(m.as_bytes()))?;
|
||||
const SHA256_HASH_LEN: usize = 32;
|
||||
let pad_to = p.n.num_bytes();
|
||||
let m = rsa_decrypt_unpadded(signature, p)?;
|
||||
println!("{:?}", m.to_vec());
|
||||
let m = rsa_encrypt_unpadded(signature, p)?;
|
||||
assert!(m.num_bytes() + 1 == pad_to, "Padding length incorrect");
|
||||
|
||||
// There was, 7 years ago, a common implementation flaw with RSA verifiers: they'd verify
|
||||
// signatures by "decrypting" them (cubing them modulo the public exponent) and then "parsing"
|
||||
// them by looking for 00h 01h ... ffh 00h ASN.1 HASH.
|
||||
let v = m.to_vec_padded(pad_to)?;
|
||||
println!("{:?}", v);
|
||||
let pad_to: usize = pad_to.try_into().unwrap();
|
||||
assert!(v[0] == 0, "PKCS1 padding incorrect");
|
||||
assert!(v[1] == 1, "PKCS1 padding incorrect");
|
||||
assert!(
|
||||
v[pad_to - SHA256_HASH_LEN - 2] == 0xff,
|
||||
"PKCS1 padding incorrect"
|
||||
);
|
||||
assert!(
|
||||
v[pad_to - SHA256_HASH_LEN - 1] == 0,
|
||||
"PKCS1 padding incorrect"
|
||||
);
|
||||
let sig = BigNum::from_slice(&v[pad_to - SHA256_HASH_LEN..])?;
|
||||
let mut i = 2;
|
||||
while i < v.len() - 1 {
|
||||
if v[i] == 0xff && v[i + 1] == 0x0 {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
i += 2;
|
||||
let sig = BigNum::from_slice(&v[i..i + SHA256_HASH_LEN])?;
|
||||
Ok(sig == hash)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user