diff --git a/src/algorithms/pad.rs b/src/algorithms/pad.rs index b89c8c2e..ff0262a3 100644 --- a/src/algorithms/pad.rs +++ b/src/algorithms/pad.rs @@ -8,7 +8,7 @@ use crate::errors::{Error, Result}; /// Returns a new vector of the given length, with 0s left padded. #[inline] -fn left_pad(input: &[u8], padded_len: usize) -> Result> { +pub(crate) fn left_pad(input: &[u8], padded_len: usize) -> Result> { if input.len() > padded_len { return Err(Error::InvalidPadLen); } diff --git a/src/lib.rs b/src/lib.rs index d9fe6b1a..8ff5768f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,11 +228,13 @@ pub mod oaep; pub mod pkcs1v15; pub mod pss; pub mod traits; +pub mod rsa_ext; mod dummy_rng; mod encoding; mod key; + pub use pkcs1; pub use pkcs8; #[cfg(feature = "sha2")] diff --git a/src/rsa_ext.rs b/src/rsa_ext.rs new file mode 100644 index 00000000..d37f0751 --- /dev/null +++ b/src/rsa_ext.rs @@ -0,0 +1,112 @@ +//! RSA-ext trait definitions. + +use alloc::vec::Vec; + +use num_bigint::BigUint; +use rand_core::{CryptoRng, RngCore}; + +use zeroize::{Zeroize, Zeroizing}; + +use crate::algorithms::pad::left_pad; +use crate::algorithms::rsa::rsa_decrypt; +use crate::errors::{Error, Result}; +use crate::key; + +use crate::traits::PublicKeyParts; +use crate::{RsaPrivateKey, RsaPublicKey}; + +/// RsaPrivateKey Ext +pub trait RsaPrivateKeyExt { + /// private_key encrypt + fn encrypt_ext(&self, rng: &mut R, msg: &[u8]) -> Result>; + /// RsaPublicKey decrypt + fn pub_decrypt(&self, data: &[u8]) -> Result>; +} +/// RsaPrivateKey Ext +pub trait RsaPublicKeyExt { + /// RsaPublicKey decrypt + fn decrypt_ext(&self, data: &[u8]) -> Result>; +} +impl RsaPublicKeyExt for RsaPublicKey { + fn decrypt_ext(&self, data: &[u8]) -> Result> { + let e = self.e(); + let n = self.n(); + + let k: usize = self.size(); + let mut ret = vec![]; + for v in data.chunks(k) { + let m = BigUint::from_bytes_be(v); + let m = m.modpow(e, n); + let m = Zeroizing::new(m); + let m = Zeroizing::new(m.to_bytes_be()); + let mut out = vec![0u8; k]; + out[k - m.len()..].copy_from_slice(&m); + + if out[0] != 0 { + break; + } + if out[1] != 0 && out[1] != 1 { + break; + } + let mut i = 2; + while i < out.len() { + if out[i] == 0 { + break; + } + i += 1; + } + + i += 1; + if i == out.len() { + break; + } + ret.extend(&out[i..]); + } + Ok(ret) + } +} + +impl RsaPrivateKeyExt for RsaPrivateKey { + fn encrypt_ext(&self, rng: &mut R, msg: &[u8]) -> Result> { + let pub_key: RsaPublicKey = self.into(); + key::check_public(&pub_key)?; + let k = pub_key.size(); + let max = k - 11; + let chunks = msg.chunks(max); + let mut ret = vec![]; + for sub in chunks { + let msg = sub; + let t_len = msg.len(); + // EM = 0x00 || 0x02 || PS || 0x00 || M + let mut em = Zeroizing::new(vec![0u8; k]); + em[1] = 1; + for i in 2..(k - t_len - 1) { + em[i] = 0xff; + } + // non_zero_random_bytes(rng, &mut em[2..k - msg.len() - 1]); + // em[k - msg.len() - 1] = 0; + em[k - msg.len()..].copy_from_slice(msg); + + let mut m = BigUint::from_bytes_be(&em); + let mut c = rsa_decrypt(Some(rng), self, &m)?; + let mut c_bytes = c.to_bytes_be(); + let ciphertext = left_pad(&c_bytes, k)?; + if k < ciphertext.len() { + return Err(Error::Verification); + } + // clear out tmp values + m.zeroize(); + c.zeroize(); + c_bytes.zeroize(); + + ret.extend(ciphertext); + } + Ok(ret) + } + + /// RsaPublicKey decrypt + fn pub_decrypt(&self, data: &[u8]) -> Result> { + let public_key = self.to_public_key(); + public_key.decrypt_ext(data) + } +}