Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove primitive traits #300

Merged
merged 6 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ A portable RSA implementation in pure Rust.
## Example

```rust
use rsa::{Pkcs1v15Encrypt, PublicKey, RsaPrivateKey, RsaPublicKey};
use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};

let mut rng = rand::thread_rng();
let bits = 2048;
Expand Down
72 changes: 44 additions & 28 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use num_traits::{One, ToPrimitive};
use rand_core::CryptoRngCore;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;
use zeroize::{Zeroize, Zeroizing};

use crate::algorithms::{generate_multi_prime_key, generate_multi_prime_key_with_exp};
use crate::dummy_rng::DummyRng;
use crate::errors::{Error, Result};
use crate::internals;

use crate::padding::{PaddingScheme, SignatureScheme};
use crate::raw::{DecryptionPrimitive, EncryptionPrimitive};

/// Components of an RSA public key.
pub trait PublicKeyParts {
Expand All @@ -31,8 +31,6 @@ pub trait PublicKeyParts {
}
}

pub trait PrivateKey: DecryptionPrimitive + PublicKeyParts {}

/// Represents the public part of an RSA key.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -161,25 +159,6 @@ impl From<&RsaPrivateKey> for RsaPublicKey {
}
}

/// Generic trait for operations on a public key.
pub trait PublicKey: EncryptionPrimitive + PublicKeyParts {
/// Encrypt the given message.
fn encrypt<R: CryptoRngCore, P: PaddingScheme>(
&self,
rng: &mut R,
padding: P,
msg: &[u8],
) -> Result<Vec<u8>>;

/// Verify a signed message.
///
/// `hashed` must be the result of hashing the input using the hashing function
/// passed in through `hash`.
///
/// If the message is valid `Ok(())` is returned, otherwise an `Err` indicating failure.
fn verify<S: SignatureScheme>(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()>;
}

impl PublicKeyParts for RsaPublicKey {
fn n(&self) -> &BigUint {
&self.n
Expand All @@ -190,8 +169,9 @@ impl PublicKeyParts for RsaPublicKey {
}
}

impl PublicKey for RsaPublicKey {
fn encrypt<R: CryptoRngCore, P: PaddingScheme>(
impl RsaPublicKey {
/// Encrypt the given message.
pub fn encrypt<R: CryptoRngCore, P: PaddingScheme>(
&self,
rng: &mut R,
padding: P,
Expand All @@ -200,7 +180,13 @@ impl PublicKey for RsaPublicKey {
padding.encrypt(rng, self, msg)
}

fn verify<S: SignatureScheme>(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()> {
/// Verify a signed message.
///
/// `hashed` must be the result of hashing the input using the hashing function
/// passed in through `hash`.
///
/// If the message is valid `Ok(())` is returned, otherwise an `Err` indicating failure.
pub fn verify<S: SignatureScheme>(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()> {
scheme.verify(self, hashed, sig)
}
}
Expand Down Expand Up @@ -239,6 +225,16 @@ impl RsaPublicKey {
pub fn new_unchecked(n: BigUint, e: BigUint) -> Self {
Self { n, e }
}

pub(crate) fn raw_int_encryption_primitive(
&self,
plaintext: &BigUint,
pad_size: usize,
) -> Result<Vec<u8>> {
let c = Zeroizing::new(internals::encrypt(self, plaintext));
let c_bytes = Zeroizing::new(c.to_bytes_be());
internals::left_pad(&c_bytes, pad_size)
}
}

impl PublicKeyParts for RsaPrivateKey {
Expand All @@ -251,8 +247,6 @@ impl PublicKeyParts for RsaPrivateKey {
}
}

impl PrivateKey for RsaPrivateKey {}

impl RsaPrivateKey {
/// Generate a new Rsa key pair of the given bit size using the passed in `rng`.
pub fn new<R: CryptoRngCore + ?Sized>(rng: &mut R, bit_size: usize) -> Result<RsaPrivateKey> {
Expand Down Expand Up @@ -461,6 +455,28 @@ impl RsaPrivateKey {
) -> Result<Vec<u8>> {
padding.sign(Some(rng), self, digest_in)
}

/// Do NOT use directly! Only for implementors.
pub(crate) fn raw_decryption_primitive<R: CryptoRngCore + ?Sized>(
&self,
rng: Option<&mut R>,
ciphertext: &[u8],
pad_size: usize,
) -> Result<Vec<u8>> {
let int = Zeroizing::new(BigUint::from_bytes_be(ciphertext));
self.raw_int_decryption_primitive(rng, &int, pad_size)
}

pub(crate) fn raw_int_decryption_primitive<R: CryptoRngCore + ?Sized>(
&self,
rng: Option<&mut R>,
ciphertext: &BigUint,
pad_size: usize,
) -> Result<Vec<u8>> {
let m = Zeroizing::new(internals::decrypt_and_check(rng, self, ciphertext)?);
let m_bytes = Zeroizing::new(m.to_bytes_be());
internals::left_pad(&m_bytes, pad_size)
}
}

/// Check that the public key is well formed and has an exponent within acceptable bounds.
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//!
//! ## PKCS#1 v1.5 encryption
//! ```
//! use rsa::{PublicKey, RsaPrivateKey, RsaPublicKey, Pkcs1v15Encrypt};
//! use rsa::{RsaPrivateKey, RsaPublicKey, Pkcs1v15Encrypt};
//!
//! let mut rng = rand::thread_rng();
//!
Expand All @@ -34,7 +34,7 @@
//!
//! ## OAEP encryption
//! ```
//! use rsa::{PublicKey, RsaPrivateKey, RsaPublicKey, Oaep};
//! use rsa::{RsaPrivateKey, RsaPublicKey, Oaep};
//!
//! let mut rng = rand::thread_rng();
//!
Expand Down Expand Up @@ -233,15 +233,14 @@ mod dummy_rng;
mod encoding;
mod key;
mod padding;
mod raw;

pub use pkcs1;
pub use pkcs8;
#[cfg(feature = "sha2")]
pub use sha2;

pub use crate::{
key::{PublicKey, PublicKeyParts, RsaPrivateKey, RsaPublicKey},
key::{PublicKeyParts, RsaPrivateKey, RsaPublicKey},
oaep::Oaep,
padding::{PaddingScheme, SignatureScheme},
pkcs1v15::{Pkcs1v15Encrypt, Pkcs1v15Sign},
Expand Down
60 changes: 26 additions & 34 deletions src/oaep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ use core::marker::PhantomData;
use rand_core::CryptoRngCore;

use digest::{Digest, DynDigest, FixedOutputReset};
use num_bigint::BigUint;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use zeroize::Zeroizing;

use crate::algorithms::{mgf1_xor, mgf1_xor_digest};
use crate::dummy_rng::DummyRng;
use crate::errors::{Error, Result};
use crate::key::{self, PrivateKey, PublicKey, RsaPrivateKey, RsaPublicKey};
use crate::key::{self, PublicKeyParts, RsaPrivateKey, RsaPublicKey};
use crate::padding::PaddingScheme;
use crate::traits::{Decryptor, RandomizedDecryptor, RandomizedEncryptor};

Expand Down Expand Up @@ -55,7 +56,7 @@ impl Oaep {
/// ```
/// use sha1::Sha1;
/// use sha2::Sha256;
/// use rsa::{BigUint, RsaPublicKey, Oaep, PublicKey};
/// use rsa::{BigUint, RsaPublicKey, Oaep, };
/// use base64ct::{Base64, Encoding};
///
/// let n = Base64::decode_vec("ALHgDoZmBQIx+jTmgeeHW6KsPOrj11f6CvWsiRleJlQpW77AwSZhd21ZDmlTKfaIHBSUxRUsuYNh7E2SHx8rkFVCQA2/gXkZ5GK2IUbzSTio9qXA25MWHvVxjMfKSL8ZAxZyKbrG94FLLszFAFOaiLLY8ECs7g+dXOriYtBwLUJK+lppbd+El+8ZA/zH0bk7vbqph5pIoiWggxwdq3mEz4LnrUln7r6dagSQzYErKewY8GADVpXcq5mfHC1xF2DFBub7bFjMVM5fHq7RK+pG5xjNDiYITbhLYrbVv3X0z75OvN0dY49ITWjM7xyvMWJXVJS7sJlgmCCL6RwWgP8PhcE=").unwrap();
Expand Down Expand Up @@ -92,7 +93,7 @@ impl Oaep {
/// ```
/// use sha1::Sha1;
/// use sha2::Sha256;
/// use rsa::{BigUint, RsaPublicKey, Oaep, PublicKey};
/// use rsa::{BigUint, RsaPublicKey, Oaep, };
/// use base64ct::{Base64, Encoding};
///
/// let n = Base64::decode_vec("ALHgDoZmBQIx+jTmgeeHW6KsPOrj11f6CvWsiRleJlQpW77AwSZhd21ZDmlTKfaIHBSUxRUsuYNh7E2SHx8rkFVCQA2/gXkZ5GK2IUbzSTio9qXA25MWHvVxjMfKSL8ZAxZyKbrG94FLLszFAFOaiLLY8ECs7g+dXOriYtBwLUJK+lppbd+El+8ZA/zH0bk7vbqph5pIoiWggxwdq3mEz4LnrUln7r6dagSQzYErKewY8GADVpXcq5mfHC1xF2DFBub7bFjMVM5fHq7RK+pG5xjNDiYITbhLYrbVv3X0z75OvN0dY49ITWjM7xyvMWJXVJS7sJlgmCCL6RwWgP8PhcE=").unwrap();
Expand Down Expand Up @@ -131,10 +132,10 @@ impl Oaep {
}

impl PaddingScheme for Oaep {
fn decrypt<Rng: CryptoRngCore, Priv: PrivateKey>(
fn decrypt<Rng: CryptoRngCore>(
mut self,
rng: Option<&mut Rng>,
priv_key: &Priv,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
) -> Result<Vec<u8>> {
decrypt(
Expand All @@ -147,10 +148,10 @@ impl PaddingScheme for Oaep {
)
}

fn encrypt<Rng: CryptoRngCore, Pub: PublicKey>(
fn encrypt<Rng: CryptoRngCore>(
mut self,
rng: &mut Rng,
pub_key: &Pub,
pub_key: &RsaPublicKey,
msg: &[u8],
) -> Result<Vec<u8>> {
encrypt(
Expand All @@ -175,9 +176,9 @@ impl fmt::Debug for Oaep {
}

#[inline]
fn encrypt_internal<R: CryptoRngCore + ?Sized, K: PublicKey, MGF: FnMut(&mut [u8], &mut [u8])>(
fn encrypt_internal<R: CryptoRngCore + ?Sized, MGF: FnMut(&mut [u8], &mut [u8])>(
rng: &mut R,
pub_key: &K,
pub_key: &RsaPublicKey,
msg: &[u8],
p_hash: &[u8],
h_size: usize,
Expand Down Expand Up @@ -206,7 +207,8 @@ fn encrypt_internal<R: CryptoRngCore + ?Sized, K: PublicKey, MGF: FnMut(&mut [u8

mgf(seed, db);

pub_key.raw_encryption_primitive(&em, pub_key.size())
let int = Zeroizing::new(BigUint::from_bytes_be(&em));
pub_key.raw_int_encryption_primitive(&int, pub_key.size())
}

/// Encrypts the given message with RSA and the padding scheme from
Expand All @@ -217,9 +219,9 @@ fn encrypt_internal<R: CryptoRngCore + ?Sized, K: PublicKey, MGF: FnMut(&mut [u8
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
fn encrypt<R: CryptoRngCore + ?Sized, K: PublicKey>(
fn encrypt<R: CryptoRngCore + ?Sized>(
rng: &mut R,
pub_key: &K,
pub_key: &RsaPublicKey,
msg: &[u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
Expand Down Expand Up @@ -249,14 +251,9 @@ fn encrypt<R: CryptoRngCore + ?Sized, K: PublicKey>(
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
fn encrypt_digest<
R: CryptoRngCore + ?Sized,
K: PublicKey,
D: Digest,
MGD: Digest + FixedOutputReset,
>(
fn encrypt_digest<R: CryptoRngCore + ?Sized, D: Digest, MGD: Digest + FixedOutputReset>(
rng: &mut R,
pub_key: &K,
pub_key: &RsaPublicKey,
msg: &[u8],
label: Option<String>,
) -> Result<Vec<u8>> {
Expand Down Expand Up @@ -289,9 +286,9 @@ fn encrypt_digest<
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
fn decrypt<R: CryptoRngCore + ?Sized, SK: PrivateKey>(
fn decrypt<R: CryptoRngCore + ?Sized>(
rng: Option<&mut R>,
priv_key: &SK,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
Expand Down Expand Up @@ -343,14 +340,9 @@ fn decrypt<R: CryptoRngCore + ?Sized, SK: PrivateKey>(
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
fn decrypt_digest<
R: CryptoRngCore + ?Sized,
SK: PrivateKey,
D: Digest,
MGD: Digest + FixedOutputReset,
>(
fn decrypt_digest<R: CryptoRngCore + ?Sized, D: Digest, MGD: Digest + FixedOutputReset>(
rng: Option<&mut R>,
priv_key: &SK,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
label: Option<String>,
) -> Result<Vec<u8>> {
Expand Down Expand Up @@ -390,9 +382,9 @@ fn decrypt_digest<
/// `rng` is given. It returns one or zero in valid that indicates whether the
/// plaintext was correctly structured.
#[inline]
fn decrypt_inner<R: CryptoRngCore + ?Sized, SK: PrivateKey, MGF: FnMut(&mut [u8], &mut [u8])>(
fn decrypt_inner<R: CryptoRngCore + ?Sized, MGF: FnMut(&mut [u8], &mut [u8])>(
rng: Option<&mut R>,
priv_key: &SK,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
h_size: usize,
expected_p_hash: &[u8],
Expand Down Expand Up @@ -491,7 +483,7 @@ where
rng: &mut R,
msg: &[u8],
) -> Result<Vec<u8>> {
encrypt_digest::<_, _, D, MGD>(rng, &self.inner, msg, self.label.as_ref().cloned())
encrypt_digest::<_, D, MGD>(rng, &self.inner, msg, self.label.as_ref().cloned())
}
}

Expand Down Expand Up @@ -542,7 +534,7 @@ where
MGD: Digest + FixedOutputReset,
{
fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
decrypt_digest::<DummyRng, _, D, MGD>(
decrypt_digest::<DummyRng, D, MGD>(
None,
&self.inner,
ciphertext,
Expand All @@ -561,7 +553,7 @@ where
rng: &mut R,
ciphertext: &[u8],
) -> Result<Vec<u8>> {
decrypt_digest::<_, _, D, MGD>(
decrypt_digest::<_, D, MGD>(
Some(rng),
&self.inner,
ciphertext,
Expand All @@ -572,7 +564,7 @@ where

#[cfg(test)]
mod tests {
use crate::key::{PublicKey, PublicKeyParts, RsaPrivateKey, RsaPublicKey};
use crate::key::{PublicKeyParts, RsaPrivateKey, RsaPublicKey};
use crate::oaep::{DecryptingKey, EncryptingKey, Oaep};
use crate::traits::{Decryptor, RandomizedDecryptor, RandomizedEncryptor};

Expand Down
Loading