2022-10-31 14:15:52 -06:00
|
|
|
//! PKCS#1 v1.5 support as described in [RFC8017 § 8.2].
|
|
|
|
//!
|
2022-11-12 18:43:30 -07:00
|
|
|
//! # Usage
|
|
|
|
//!
|
|
|
|
//! See [code example in the toplevel rustdoc](../index.html#pkcs1-v15-signatures).
|
|
|
|
//!
|
2022-10-31 14:15:52 -06:00
|
|
|
//! [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2
|
|
|
|
|
2023-04-18 12:17:07 -06:00
|
|
|
use alloc::{boxed::Box, string::ToString, vec::Vec};
|
2022-08-19 20:46:40 +03:00
|
|
|
use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex};
|
2022-09-07 20:47:03 +03:00
|
|
|
use core::marker::PhantomData;
|
|
|
|
use digest::Digest;
|
2023-04-18 12:17:07 -06:00
|
|
|
use num_bigint::BigUint;
|
2023-04-05 05:12:08 +03:00
|
|
|
use pkcs8::{
|
|
|
|
spki::{
|
|
|
|
der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier,
|
|
|
|
SignatureAlgorithmIdentifier,
|
|
|
|
},
|
|
|
|
AssociatedOid, Document, EncodePrivateKey, EncodePublicKey, SecretDocument,
|
|
|
|
};
|
2022-12-05 05:03:38 +03:00
|
|
|
use rand_core::CryptoRngCore;
|
2022-09-07 20:47:03 +03:00
|
|
|
use signature::{
|
2022-12-05 05:03:38 +03:00
|
|
|
hazmat::{PrehashSigner, PrehashVerifier},
|
|
|
|
DigestSigner, DigestVerifier, Keypair, RandomizedDigestSigner, RandomizedSigner,
|
|
|
|
SignatureEncoding, Signer, Verifier,
|
2022-09-07 20:47:03 +03:00
|
|
|
};
|
2022-03-15 16:20:20 -05:00
|
|
|
use zeroize::Zeroizing;
|
2018-07-24 01:01:44 +02:00
|
|
|
|
2023-04-24 01:53:21 +03:00
|
|
|
use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad};
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
use crate::algorithms::pkcs1v15::*;
|
2023-04-24 01:53:21 +03:00
|
|
|
use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
|
2022-08-19 20:46:40 +03:00
|
|
|
use crate::dummy_rng::DummyRng;
|
2019-03-18 09:29:05 -07:00
|
|
|
use crate::errors::{Error, Result};
|
2023-04-24 01:53:21 +03:00
|
|
|
use crate::key;
|
|
|
|
use crate::keytraits::PublicKeyParts;
|
2023-01-10 13:59:31 -07:00
|
|
|
use crate::padding::{PaddingScheme, SignatureScheme};
|
2023-02-13 18:35:20 +03:00
|
|
|
use crate::traits::{Decryptor, EncryptingKeypair, RandomizedDecryptor, RandomizedEncryptor};
|
2022-08-19 20:46:40 +03:00
|
|
|
use crate::{RsaPrivateKey, RsaPublicKey};
|
|
|
|
|
2023-01-10 13:59:31 -07:00
|
|
|
/// Encryption using PKCS#1 v1.5 padding.
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
|
|
|
pub struct Pkcs1v15Encrypt;
|
|
|
|
|
|
|
|
impl PaddingScheme for Pkcs1v15Encrypt {
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn decrypt<Rng: CryptoRngCore>(
|
2023-01-10 13:59:31 -07:00
|
|
|
self,
|
|
|
|
rng: Option<&mut Rng>,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
priv_key: &RsaPrivateKey,
|
2023-01-10 13:59:31 -07:00
|
|
|
ciphertext: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
|
|
|
decrypt(rng, priv_key, ciphertext)
|
|
|
|
}
|
|
|
|
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn encrypt<Rng: CryptoRngCore>(
|
2023-01-10 13:59:31 -07:00
|
|
|
self,
|
|
|
|
rng: &mut Rng,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
pub_key: &RsaPublicKey,
|
2023-01-10 13:59:31 -07:00
|
|
|
msg: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
|
|
|
encrypt(rng, pub_key, msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Digital signatures using PKCS#1 v1.5 padding.
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
pub struct Pkcs1v15Sign {
|
|
|
|
/// Length of hash to use.
|
|
|
|
pub hash_len: Option<usize>,
|
|
|
|
|
|
|
|
/// Prefix.
|
|
|
|
pub prefix: Box<[u8]>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Pkcs1v15Sign {
|
|
|
|
/// Create new PKCS#1 v1.5 padding for the given digest.
|
|
|
|
///
|
|
|
|
/// The digest must have an [`AssociatedOid`]. Make sure to enable the `oid`
|
|
|
|
/// feature of the relevant digest crate.
|
|
|
|
pub fn new<D>() -> Self
|
|
|
|
where
|
|
|
|
D: Digest + AssociatedOid,
|
|
|
|
{
|
|
|
|
Self {
|
|
|
|
hash_len: Some(<D as Digest>::output_size()),
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
prefix: pkcs1v15_generate_prefix::<D>().into_boxed_slice(),
|
2023-01-10 13:59:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-17 06:40:24 -06:00
|
|
|
/// Create new PKCS#1 v1.5 padding for computing an unprefixed signature.
|
2023-01-10 13:59:31 -07:00
|
|
|
///
|
|
|
|
/// This sets `hash_len` to `None` and uses an empty `prefix`.
|
2023-04-17 06:40:24 -06:00
|
|
|
pub fn new_unprefixed() -> Self {
|
2023-01-10 13:59:31 -07:00
|
|
|
Self {
|
|
|
|
hash_len: None,
|
|
|
|
prefix: Box::new([]),
|
|
|
|
}
|
|
|
|
}
|
2023-04-17 06:40:24 -06:00
|
|
|
|
|
|
|
/// Create new PKCS#1 v1.5 padding for computing an unprefixed signature.
|
|
|
|
///
|
|
|
|
/// This sets `hash_len` to `None` and uses an empty `prefix`.
|
|
|
|
#[deprecated(since = "0.9.0", note = "use Pkcs1v15Sign::new_unprefixed instead")]
|
|
|
|
pub fn new_raw() -> Self {
|
|
|
|
Self::new_unprefixed()
|
|
|
|
}
|
2023-01-10 13:59:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SignatureScheme for Pkcs1v15Sign {
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn sign<Rng: CryptoRngCore>(
|
2023-01-10 13:59:31 -07:00
|
|
|
self,
|
|
|
|
rng: Option<&mut Rng>,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
priv_key: &RsaPrivateKey,
|
2023-01-10 13:59:31 -07:00
|
|
|
hashed: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
|
|
|
if let Some(hash_len) = self.hash_len {
|
|
|
|
if hashed.len() != hash_len {
|
|
|
|
return Err(Error::InputNotHashed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sign(rng, priv_key, &self.prefix, hashed)
|
|
|
|
}
|
|
|
|
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn verify(self, pub_key: &RsaPublicKey, hashed: &[u8], sig: &[u8]) -> Result<()> {
|
2023-01-10 13:59:31 -07:00
|
|
|
if let Some(hash_len) = self.hash_len {
|
|
|
|
if hashed.len() != hash_len {
|
|
|
|
return Err(Error::InputNotHashed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-18 12:17:07 -06:00
|
|
|
verify(
|
|
|
|
pub_key,
|
|
|
|
self.prefix.as_ref(),
|
|
|
|
hashed,
|
|
|
|
&BigUint::from_bytes_be(sig),
|
|
|
|
)
|
2023-01-10 13:59:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-31 14:15:52 -06:00
|
|
|
/// PKCS#1 v1.5 signatures as described in [RFC8017 § 8.2].
|
|
|
|
///
|
|
|
|
/// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2
|
2022-12-05 05:03:38 +03:00
|
|
|
#[derive(Clone, PartialEq, Eq)]
|
2022-08-19 20:46:40 +03:00
|
|
|
pub struct Signature {
|
2023-04-18 12:17:07 -06:00
|
|
|
inner: BigUint,
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
|
2022-12-05 05:03:38 +03:00
|
|
|
impl SignatureEncoding for Signature {
|
|
|
|
type Repr = Box<[u8]>;
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
|
2023-01-10 13:59:31 -07:00
|
|
|
impl TryFrom<&[u8]> for Signature {
|
2022-12-05 05:03:38 +03:00
|
|
|
type Error = signature::Error;
|
2022-09-12 19:43:13 +03:00
|
|
|
|
2023-01-10 13:59:31 -07:00
|
|
|
fn try_from(bytes: &[u8]) -> signature::Result<Self> {
|
2022-12-05 05:03:38 +03:00
|
|
|
Ok(Self {
|
2023-04-18 12:17:07 -06:00
|
|
|
inner: BigUint::from_bytes_be(bytes),
|
2022-12-05 05:03:38 +03:00
|
|
|
})
|
2022-09-12 19:43:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-05 05:03:38 +03:00
|
|
|
impl From<Signature> for Box<[u8]> {
|
|
|
|
fn from(signature: Signature) -> Box<[u8]> {
|
2023-04-18 12:17:07 -06:00
|
|
|
signature.inner.to_bytes_be().into_boxed_slice()
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-05 05:03:38 +03:00
|
|
|
impl Debug for Signature {
|
|
|
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
|
2023-04-18 12:17:07 -06:00
|
|
|
fmt.debug_tuple("Signature")
|
|
|
|
.field(&self.to_string())
|
|
|
|
.finish()
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LowerHex for Signature {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
2023-04-18 12:17:07 -06:00
|
|
|
write!(f, "{:x}", &self.inner)
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UpperHex for Signature {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
2023-04-18 12:17:07 -06:00
|
|
|
write!(f, "{:X}", &self.inner)
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Signature {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
|
|
|
write!(f, "{:X}", self)
|
|
|
|
}
|
|
|
|
}
|
2018-07-24 01:01:44 +02:00
|
|
|
|
2022-10-31 14:15:52 -06:00
|
|
|
/// Encrypts the given message with RSA and the padding
|
|
|
|
/// scheme from PKCS#1 v1.5. The message must be no longer than the
|
|
|
|
/// length of the public modulus minus 11 bytes.
|
2018-07-24 14:31:06 +02:00
|
|
|
#[inline]
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn encrypt<R: CryptoRngCore + ?Sized>(
|
2022-03-13 19:50:05 +00:00
|
|
|
rng: &mut R,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
pub_key: &RsaPublicKey,
|
2022-03-13 19:50:05 +00:00
|
|
|
msg: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
2018-07-24 01:01:44 +02:00
|
|
|
key::check_public(pub_key)?;
|
|
|
|
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
let em = pkcs1v15_encrypt_pad(rng, msg, pub_key.size())?;
|
|
|
|
let int = Zeroizing::new(BigUint::from_bytes_be(&em));
|
2023-04-24 01:53:21 +03:00
|
|
|
uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size())
|
2018-07-24 01:01:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
|
2022-10-31 14:15:52 -06:00
|
|
|
///
|
|
|
|
/// If an `rng` is passed, it uses RSA blinding to avoid timing side-channel attacks.
|
|
|
|
///
|
|
|
|
/// Note that whether this function returns an error or not discloses secret
|
|
|
|
/// information. If an attacker can cause this function to run repeatedly and
|
|
|
|
/// learn whether each instance returned an error then they can decrypt and
|
|
|
|
/// forge signatures as if they had the private key. See
|
|
|
|
/// `decrypt_session_key` for a way of solving this problem.
|
2018-07-24 14:31:06 +02:00
|
|
|
#[inline]
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn decrypt<R: CryptoRngCore + ?Sized>(
|
2018-07-24 01:01:44 +02:00
|
|
|
rng: Option<&mut R>,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
priv_key: &RsaPrivateKey,
|
2018-07-24 01:01:44 +02:00
|
|
|
ciphertext: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
|
|
|
key::check_public(priv_key)?;
|
|
|
|
|
2023-04-24 01:53:21 +03:00
|
|
|
let em = rsa_decrypt_and_check(priv_key, rng, &BigUint::from_bytes_be(ciphertext))?;
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
let em = uint_to_zeroizing_be_pad(em, priv_key.size())?;
|
2018-07-24 01:01:44 +02:00
|
|
|
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
pkcs1v15_encrypt_unpad(em, priv_key.size())
|
2018-07-24 01:01:44 +02:00
|
|
|
}
|
|
|
|
|
2022-10-31 14:15:52 -06:00
|
|
|
/// Calculates the signature of hashed using
|
|
|
|
/// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. Note that `hashed` must
|
|
|
|
/// be the result of hashing the input message using the given hash
|
|
|
|
/// function. If hash is `None`, hashed is signed directly. This isn't
|
|
|
|
/// advisable except for interoperability.
|
|
|
|
///
|
|
|
|
/// If `rng` is not `None` then RSA blinding will be used to avoid timing
|
|
|
|
/// side-channel attacks.
|
|
|
|
///
|
|
|
|
/// This function is deterministic. Thus, if the set of possible
|
|
|
|
/// messages is small, an attacker may be able to build a map from
|
|
|
|
/// messages to signatures and identify the signed messages. As ever,
|
|
|
|
/// signatures provide authenticity, not confidentiality.
|
2018-07-24 14:31:06 +02:00
|
|
|
#[inline]
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn sign<R: CryptoRngCore + ?Sized>(
|
2018-07-24 14:31:06 +02:00
|
|
|
rng: Option<&mut R>,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
priv_key: &RsaPrivateKey,
|
2022-09-16 20:25:05 +03:00
|
|
|
prefix: &[u8],
|
2018-07-24 14:31:06 +02:00
|
|
|
hashed: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
let em = pkcs1v15_sign_pad(prefix, hashed, priv_key.size())?;
|
2018-07-24 14:31:06 +02:00
|
|
|
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
uint_to_zeroizing_be_pad(
|
2023-04-24 01:53:21 +03:00
|
|
|
rsa_decrypt_and_check(priv_key, rng, &BigUint::from_bytes_be(&em))?,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
priv_key.size(),
|
|
|
|
)
|
2018-07-24 14:31:06 +02:00
|
|
|
}
|
|
|
|
|
2018-07-24 22:04:41 +02:00
|
|
|
/// Verifies an RSA PKCS#1 v1.5 signature.
|
|
|
|
#[inline]
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
fn verify(pub_key: &RsaPublicKey, prefix: &[u8], hashed: &[u8], sig: &BigUint) -> Result<()> {
|
2023-04-24 01:53:21 +03:00
|
|
|
let em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?;
|
2018-07-24 01:01:44 +02:00
|
|
|
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
pkcs1v15_sign_unpad(prefix, hashed, &em, pub_key.size())
|
2018-07-24 01:01:44 +02:00
|
|
|
}
|
|
|
|
|
2022-10-31 14:15:52 -06:00
|
|
|
/// Signing key for PKCS#1 v1.5 signatures as described in [RFC8017 § 8.2].
|
|
|
|
///
|
|
|
|
/// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2
|
2022-09-19 23:17:56 +08:00
|
|
|
#[derive(Debug, Clone)]
|
2022-09-07 20:47:03 +03:00
|
|
|
pub struct SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2022-08-19 20:46:40 +03:00
|
|
|
inner: RsaPrivateKey,
|
2022-09-16 20:25:05 +03:00
|
|
|
prefix: Vec<u8>,
|
2022-09-07 20:47:03 +03:00
|
|
|
phantom: PhantomData<D>,
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2023-01-20 16:46:27 -07:00
|
|
|
/// Create a new signing key from the give RSA private key with an empty prefix.
|
|
|
|
///
|
|
|
|
/// ## Note: unprefixed signatures are uncommon
|
|
|
|
///
|
2023-04-11 06:37:34 -06:00
|
|
|
/// In most cases you'll want to use [`SigningKey::new`].
|
|
|
|
pub fn new_unprefixed(key: RsaPrivateKey) -> Self {
|
2022-08-19 20:46:40 +03:00
|
|
|
Self {
|
|
|
|
inner: key,
|
2022-09-16 20:25:05 +03:00
|
|
|
prefix: Vec::new(),
|
2022-09-07 20:47:03 +03:00
|
|
|
phantom: Default::default(),
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
2022-10-31 14:15:52 -06:00
|
|
|
|
2023-04-11 06:37:34 -06:00
|
|
|
/// Generate a new signing key with an empty prefix.
|
|
|
|
pub fn random_unprefixed<R: CryptoRngCore + ?Sized>(
|
|
|
|
rng: &mut R,
|
|
|
|
bit_size: usize,
|
|
|
|
) -> Result<Self> {
|
2022-12-05 05:03:38 +03:00
|
|
|
Ok(Self {
|
|
|
|
inner: RsaPrivateKey::new(rng, bit_size)?,
|
|
|
|
prefix: Vec::new(),
|
|
|
|
phantom: Default::default(),
|
|
|
|
})
|
2022-10-31 14:15:52 -06:00
|
|
|
}
|
2022-09-07 20:47:03 +03:00
|
|
|
}
|
2022-08-19 20:46:40 +03:00
|
|
|
|
2023-04-05 05:12:08 +03:00
|
|
|
impl<D> AssociatedAlgorithmIdentifier for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
type Params = AnyRef<'static>;
|
|
|
|
|
|
|
|
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<D> SignatureAlgorithmIdentifier for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest + oid::RsaSignatureAssociatedOid,
|
|
|
|
{
|
|
|
|
type Params = AnyRef<'static>;
|
|
|
|
|
|
|
|
const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> =
|
|
|
|
AlgorithmIdentifierRef {
|
|
|
|
oid: D::OID,
|
|
|
|
parameters: Some(AnyRef::NULL),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-09-21 18:43:04 -04:00
|
|
|
impl<D> From<RsaPrivateKey> for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn from(key: RsaPrivateKey) -> Self {
|
2023-04-11 06:37:34 -06:00
|
|
|
Self::new_unprefixed(key)
|
2022-09-21 18:43:04 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 17:42:36 -04:00
|
|
|
impl<D> From<SigningKey<D>> for RsaPrivateKey
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn from(key: SigningKey<D>) -> Self {
|
|
|
|
key.inner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> SigningKey<D>
|
|
|
|
where
|
2022-09-16 20:25:05 +03:00
|
|
|
D: Digest + AssociatedOid,
|
2022-09-07 20:47:03 +03:00
|
|
|
{
|
2022-12-05 05:03:38 +03:00
|
|
|
/// Create a new signing key with a prefix for the digest `D`.
|
2023-04-11 06:37:34 -06:00
|
|
|
pub fn new(key: RsaPrivateKey) -> Self {
|
2022-08-19 20:46:40 +03:00
|
|
|
Self {
|
|
|
|
inner: key,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
prefix: pkcs1v15_generate_prefix::<D>(),
|
2022-09-07 20:47:03 +03:00
|
|
|
phantom: Default::default(),
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
2022-12-05 05:03:38 +03:00
|
|
|
|
|
|
|
/// Generate a new signing key with a prefix for the digest `D`.
|
2023-04-11 06:37:34 -06:00
|
|
|
pub fn random<R: CryptoRngCore + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
|
2022-12-05 05:03:38 +03:00
|
|
|
Ok(Self {
|
|
|
|
inner: RsaPrivateKey::new(rng, bit_size)?,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
prefix: pkcs1v15_generate_prefix::<D>(),
|
2022-12-05 05:03:38 +03:00
|
|
|
phantom: Default::default(),
|
|
|
|
})
|
|
|
|
}
|
2023-04-11 06:37:34 -06:00
|
|
|
|
|
|
|
/// Create a new signing key with a prefix for the digest `D`.
|
|
|
|
#[deprecated(since = "0.9.0", note = "use SigningKey::new instead")]
|
|
|
|
pub fn new_with_prefix(key: RsaPrivateKey) -> Self {
|
|
|
|
Self::new(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Generate a new signing key with a prefix for the digest `D`.
|
|
|
|
#[deprecated(since = "0.9.0", note = "use SigningKey::random instead")]
|
|
|
|
pub fn random_with_prefix<R: CryptoRngCore + ?Sized>(
|
|
|
|
rng: &mut R,
|
|
|
|
bit_size: usize,
|
|
|
|
) -> Result<Self> {
|
|
|
|
Self::random(rng, bit_size)
|
|
|
|
}
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
|
2022-09-21 18:42:29 -04:00
|
|
|
impl<D> AsRef<RsaPrivateKey> for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn as_ref(&self) -> &RsaPrivateKey {
|
|
|
|
&self.inner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-08 23:38:43 +03:00
|
|
|
impl<D> EncodePrivateKey for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
|
|
|
|
self.inner.to_pkcs8_der()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> Signer<Signature> for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn try_sign(&self, msg: &[u8]) -> signature::Result<Signature> {
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
sign::<DummyRng>(None, &self.inner, &self.prefix, &D::digest(msg))?
|
2023-04-18 12:17:07 -06:00
|
|
|
.as_slice()
|
|
|
|
.try_into()
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> RandomizedSigner<Signature> for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2023-01-07 21:26:52 -07:00
|
|
|
fn try_sign_with_rng(
|
2022-08-19 20:46:40 +03:00
|
|
|
&self,
|
2023-01-07 21:26:52 -07:00
|
|
|
rng: &mut impl CryptoRngCore,
|
2022-09-07 20:47:03 +03:00
|
|
|
msg: &[u8],
|
2022-08-19 20:46:40 +03:00
|
|
|
) -> signature::Result<Signature> {
|
2023-04-18 12:17:07 -06:00
|
|
|
sign(Some(rng), &self.inner, &self.prefix, &D::digest(msg))?
|
|
|
|
.as_slice()
|
|
|
|
.try_into()
|
2022-09-07 20:47:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<D> DigestSigner<D, Signature> for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn try_sign_digest(&self, digest: D) -> signature::Result<Signature> {
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
sign::<DummyRng>(None, &self.inner, &self.prefix, &digest.finalize())?
|
2023-04-18 12:17:07 -06:00
|
|
|
.as_slice()
|
|
|
|
.try_into()
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> RandomizedDigestSigner<D, Signature> for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2023-01-07 21:26:52 -07:00
|
|
|
fn try_sign_digest_with_rng(
|
2022-09-07 20:47:03 +03:00
|
|
|
&self,
|
2023-01-07 21:26:52 -07:00
|
|
|
rng: &mut impl CryptoRngCore,
|
2022-09-07 20:47:03 +03:00
|
|
|
digest: D,
|
|
|
|
) -> signature::Result<Signature> {
|
2023-04-18 12:17:07 -06:00
|
|
|
sign(Some(rng), &self.inner, &self.prefix, &digest.finalize())?
|
|
|
|
.as_slice()
|
|
|
|
.try_into()
|
2022-09-07 20:47:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-22 19:03:46 +03:00
|
|
|
impl<D> PrehashSigner<Signature> for SigningKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn sign_prehash(&self, prehash: &[u8]) -> signature::Result<Signature> {
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
sign::<DummyRng>(None, &self.inner, &self.prefix, prehash)?
|
2023-04-18 12:17:07 -06:00
|
|
|
.as_slice()
|
|
|
|
.try_into()
|
2022-09-22 19:03:46 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-31 14:15:52 -06:00
|
|
|
/// Verifying key for PKCS#1 v1.5 signatures as described in [RFC8017 § 8.2].
|
|
|
|
///
|
|
|
|
/// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2
|
2022-12-05 05:03:38 +03:00
|
|
|
#[derive(Debug)]
|
2022-09-07 20:47:03 +03:00
|
|
|
pub struct VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2022-08-19 20:46:40 +03:00
|
|
|
inner: RsaPublicKey,
|
2022-09-16 20:25:05 +03:00
|
|
|
prefix: Vec<u8>,
|
2022-09-07 20:47:03 +03:00
|
|
|
phantom: PhantomData<D>,
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
|
2022-12-05 05:03:38 +03:00
|
|
|
/* Implemented manually so we don't have to bind D with Clone */
|
|
|
|
impl<D> Clone for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
|
|
|
inner: self.inner.clone(),
|
|
|
|
prefix: self.prefix.clone(),
|
|
|
|
phantom: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2023-01-20 16:46:27 -07:00
|
|
|
/// Create a new verifying key from an RSA public key with an empty prefix.
|
|
|
|
///
|
|
|
|
/// ## Note: unprefixed signatures are uncommon
|
|
|
|
///
|
2023-04-11 06:37:34 -06:00
|
|
|
/// In most cases you'll want to use [`VerifyingKey::new`] instead.
|
|
|
|
pub fn new_unprefixed(key: RsaPublicKey) -> Self {
|
2022-08-19 20:46:40 +03:00
|
|
|
Self {
|
|
|
|
inner: key,
|
2022-09-16 20:25:05 +03:00
|
|
|
prefix: Vec::new(),
|
2022-09-07 20:47:03 +03:00
|
|
|
phantom: Default::default(),
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
2022-09-07 20:47:03 +03:00
|
|
|
}
|
2022-08-19 20:46:40 +03:00
|
|
|
|
2023-04-05 05:12:08 +03:00
|
|
|
impl<D> AssociatedAlgorithmIdentifier for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
type Params = AnyRef<'static>;
|
|
|
|
|
|
|
|
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<D> SignatureAlgorithmIdentifier for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest + oid::RsaSignatureAssociatedOid,
|
|
|
|
{
|
|
|
|
type Params = AnyRef<'static>;
|
|
|
|
|
|
|
|
const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> =
|
|
|
|
AlgorithmIdentifierRef {
|
|
|
|
oid: D::OID,
|
|
|
|
parameters: Some(AnyRef::NULL),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-09-21 18:43:04 -04:00
|
|
|
impl<D> From<RsaPublicKey> for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn from(key: RsaPublicKey) -> Self {
|
2023-04-11 06:37:34 -06:00
|
|
|
Self::new_unprefixed(key)
|
2022-09-21 18:43:04 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 17:42:36 -04:00
|
|
|
impl<D> From<VerifyingKey<D>> for RsaPublicKey
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn from(key: VerifyingKey<D>) -> Self {
|
|
|
|
key.inner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> VerifyingKey<D>
|
|
|
|
where
|
2022-09-16 20:25:05 +03:00
|
|
|
D: Digest + AssociatedOid,
|
2022-09-07 20:47:03 +03:00
|
|
|
{
|
2022-10-31 14:15:52 -06:00
|
|
|
/// Create a new verifying key with a prefix for the digest `D`.
|
2023-04-11 06:37:34 -06:00
|
|
|
pub fn new(key: RsaPublicKey) -> Self {
|
2022-08-19 20:46:40 +03:00
|
|
|
Self {
|
|
|
|
inner: key,
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
prefix: pkcs1v15_generate_prefix::<D>(),
|
2022-09-07 20:47:03 +03:00
|
|
|
phantom: Default::default(),
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
2023-04-11 06:37:34 -06:00
|
|
|
|
|
|
|
/// Create a new verifying key with a prefix for the digest `D`.
|
|
|
|
#[deprecated(since = "0.9.0", note = "use VerifyingKey::new instead")]
|
|
|
|
pub fn new_with_prefix(key: RsaPublicKey) -> Self {
|
|
|
|
Self::new(key)
|
|
|
|
}
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
|
2022-09-21 18:42:29 -04:00
|
|
|
impl<D> AsRef<RsaPublicKey> for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn as_ref(&self) -> &RsaPublicKey {
|
|
|
|
&self.inner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-05 05:03:38 +03:00
|
|
|
impl<D> Keypair for SigningKey<D>
|
2022-09-07 20:47:03 +03:00
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2022-12-05 05:03:38 +03:00
|
|
|
type VerifyingKey = VerifyingKey<D>;
|
|
|
|
fn verifying_key(&self) -> Self::VerifyingKey {
|
|
|
|
VerifyingKey {
|
|
|
|
inner: self.inner.to_public_key(),
|
|
|
|
prefix: self.prefix.clone(),
|
2022-09-07 20:47:03 +03:00
|
|
|
phantom: Default::default(),
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
impl<D> Verifier<Signature> for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
2022-08-19 20:46:40 +03:00
|
|
|
fn verify(&self, msg: &[u8], signature: &Signature) -> signature::Result<()> {
|
2022-09-07 20:47:03 +03:00
|
|
|
verify(
|
|
|
|
&self.inner,
|
2022-12-05 05:03:38 +03:00
|
|
|
&self.prefix.clone(),
|
2022-09-07 20:47:03 +03:00
|
|
|
&D::digest(msg),
|
2023-04-18 12:17:07 -06:00
|
|
|
&signature.inner,
|
2022-09-07 20:47:03 +03:00
|
|
|
)
|
|
|
|
.map_err(|e| e.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<D> DigestVerifier<D, Signature> for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn verify_digest(&self, digest: D, signature: &Signature) -> signature::Result<()> {
|
|
|
|
verify(
|
|
|
|
&self.inner,
|
2022-09-16 20:25:05 +03:00
|
|
|
&self.prefix,
|
2022-09-07 20:47:03 +03:00
|
|
|
&digest.finalize(),
|
2023-04-18 12:17:07 -06:00
|
|
|
&signature.inner,
|
2022-09-07 20:47:03 +03:00
|
|
|
)
|
|
|
|
.map_err(|e| e.into())
|
2022-08-19 20:46:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-22 19:03:46 +03:00
|
|
|
impl<D> PrehashVerifier<Signature> for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> {
|
2023-04-18 12:17:07 -06:00
|
|
|
verify(&self.inner, &self.prefix, prehash, &signature.inner).map_err(|e| e.into())
|
2022-09-22 19:03:46 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-08 22:01:19 +03:00
|
|
|
impl<D> EncodePublicKey for VerifyingKey<D>
|
|
|
|
where
|
|
|
|
D: Digest,
|
|
|
|
{
|
|
|
|
fn to_public_key_der(&self) -> pkcs8::spki::Result<Document> {
|
|
|
|
self.inner.to_public_key_der()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-13 18:35:20 +03:00
|
|
|
/// Encryption key for PKCS#1 v1.5 encryption as described in [RFC8017 § 7.2].
|
|
|
|
///
|
|
|
|
/// [RFC8017 § 7.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.2
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct EncryptingKey {
|
|
|
|
inner: RsaPublicKey,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EncryptingKey {
|
|
|
|
/// Create a new verifying key from an RSA public key.
|
|
|
|
pub fn new(key: RsaPublicKey) -> Self {
|
|
|
|
Self { inner: key }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RandomizedEncryptor for EncryptingKey {
|
|
|
|
fn encrypt_with_rng<R: CryptoRngCore + ?Sized>(
|
|
|
|
&self,
|
|
|
|
rng: &mut R,
|
|
|
|
msg: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
|
|
|
encrypt(rng, &self.inner, msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Decryption key for PKCS#1 v1.5 decryption as described in [RFC8017 § 7.2].
|
|
|
|
///
|
|
|
|
/// [RFC8017 § 7.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.2
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct DecryptingKey {
|
|
|
|
inner: RsaPrivateKey,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DecryptingKey {
|
|
|
|
/// Create a new verifying key from an RSA public key.
|
|
|
|
pub fn new(key: RsaPrivateKey) -> Self {
|
|
|
|
Self { inner: key }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decryptor for DecryptingKey {
|
|
|
|
fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
decrypt::<DummyRng>(None, &self.inner, ciphertext)
|
2023-02-13 18:35:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RandomizedDecryptor for DecryptingKey {
|
|
|
|
fn decrypt_with_rng<R: CryptoRngCore + ?Sized>(
|
|
|
|
&self,
|
|
|
|
rng: &mut R,
|
|
|
|
ciphertext: &[u8],
|
|
|
|
) -> Result<Vec<u8>> {
|
|
|
|
decrypt(Some(rng), &self.inner, ciphertext)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EncryptingKeypair for DecryptingKey {
|
|
|
|
type EncryptingKey = EncryptingKey;
|
|
|
|
fn encrypting_key(&self) -> EncryptingKey {
|
|
|
|
EncryptingKey {
|
|
|
|
inner: self.inner.clone().into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-05 05:12:08 +03:00
|
|
|
mod oid {
|
|
|
|
use const_oid::ObjectIdentifier;
|
|
|
|
|
|
|
|
/// A trait which associates an RSA-specific OID with a type.
|
|
|
|
pub(crate) trait RsaSignatureAssociatedOid {
|
|
|
|
/// The OID associated with this type.
|
|
|
|
const OID: ObjectIdentifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "sha1")]
|
|
|
|
impl RsaSignatureAssociatedOid for sha1::Sha1 {
|
|
|
|
const OID: ObjectIdentifier =
|
|
|
|
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "sha2")]
|
|
|
|
impl RsaSignatureAssociatedOid for sha2::Sha224 {
|
|
|
|
const OID: ObjectIdentifier =
|
|
|
|
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.14");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "sha2")]
|
|
|
|
impl RsaSignatureAssociatedOid for sha2::Sha256 {
|
|
|
|
const OID: ObjectIdentifier =
|
|
|
|
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "sha2")]
|
|
|
|
impl RsaSignatureAssociatedOid for sha2::Sha384 {
|
|
|
|
const OID: ObjectIdentifier =
|
|
|
|
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "sha2")]
|
|
|
|
impl RsaSignatureAssociatedOid for sha2::Sha512 {
|
|
|
|
const OID: ObjectIdentifier =
|
|
|
|
const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 01:01:44 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2022-03-13 19:50:05 +00:00
|
|
|
use base64ct::{Base64, Encoding};
|
|
|
|
use hex_literal::hex;
|
2020-01-02 21:51:43 -05:00
|
|
|
use num_bigint::BigUint;
|
2018-11-08 18:17:59 +01:00
|
|
|
use num_traits::FromPrimitive;
|
2018-07-24 01:01:44 +02:00
|
|
|
use num_traits::Num;
|
2022-12-05 05:03:38 +03:00
|
|
|
use rand_chacha::{
|
|
|
|
rand_core::{RngCore, SeedableRng},
|
|
|
|
ChaCha8Rng,
|
|
|
|
};
|
2018-07-24 14:31:06 +02:00
|
|
|
use sha1::{Digest, Sha1};
|
2022-09-07 20:47:03 +03:00
|
|
|
use sha2::Sha256;
|
2022-09-16 20:25:05 +03:00
|
|
|
use sha3::Sha3_256;
|
2022-12-05 05:03:38 +03:00
|
|
|
use signature::{RandomizedSigner, Signer, Verifier};
|
2018-07-24 14:31:06 +02:00
|
|
|
|
Remove primitive traits (#300)
The crate contains several exported traits targeting
hardware-accelerated implementations (PublicKey, PrivateKey,
EncryptionPrimitive, DecriptionPrimitive). However these traits
overcomplicate internal structure of the crate. It is not clear, which
level of API can be implemented by the hardware accelerators.
The crate is already quite complicated, implementing both
PaddingScheme-based API and Signer/Verifier/Encryptor/Decryptor API.
Remove the complication for now. The proper level of indirection can be
introduced once support for actual hardware accelerators is implemented.
Inline and drop the RsaPrivateKey::raw_decryption_primitive() function.
There is no need to zeroize argument, it is ciphertext, so it can be
assumed to be safe.
Change raw_int_decryption_primitive() and raw_int_decryption_primitive()
to output Result<BigUint> instead of Result<Vec<u8>>, because they also
take BigUint rather than Vec<u8> or &[u8].
In order to simplify adding support for RSA hardware accelerators, move
all formatting and padding functions to a separate modules, making it
theoretically possible to use that for implementing support for
low-level RSA hardware accelerators.
Also follows the pkcs1v15 change and use BigUint as a Signature's
internal implementation.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
2023-04-19 17:51:06 +03:00
|
|
|
use crate::{PublicKeyParts, RsaPrivateKey, RsaPublicKey};
|
2018-07-24 01:01:44 +02:00
|
|
|
|
2021-07-26 23:25:13 +02:00
|
|
|
fn get_private_key() -> RsaPrivateKey {
|
2018-07-24 01:01:44 +02:00
|
|
|
// In order to generate new test vectors you'll need the PEM form of this key:
|
|
|
|
// -----BEGIN RSA PRIVATE KEY-----
|
|
|
|
// MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
|
|
|
|
// fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
|
|
|
|
// /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
|
|
|
|
// RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
|
|
|
|
// EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
|
|
|
|
// IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
|
|
|
|
// tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
|
|
|
|
// -----END RSA PRIVATE KEY-----
|
|
|
|
|
2021-07-26 23:25:13 +02:00
|
|
|
RsaPrivateKey::from_components(
|
2018-07-24 01:01:44 +02:00
|
|
|
BigUint::from_str_radix("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077", 10).unwrap(),
|
2018-11-08 18:17:59 +01:00
|
|
|
BigUint::from_u64(65537).unwrap(),
|
2018-07-24 01:01:44 +02:00
|
|
|
BigUint::from_str_radix("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861", 10).unwrap(),
|
|
|
|
vec![
|
|
|
|
BigUint::from_str_radix("98920366548084643601728869055592650835572950932266967461790948584315647051443",10).unwrap(),
|
|
|
|
BigUint::from_str_radix("94560208308847015747498523884063394671606671904944666360068158221458669711639", 10).unwrap()
|
|
|
|
],
|
2022-07-25 06:35:47 -06:00
|
|
|
).unwrap()
|
2018-07-24 01:01:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_decrypt_pkcs1v15() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
|
|
|
let tests = [[
|
|
|
|
"gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==",
|
|
|
|
"x",
|
|
|
|
], [
|
|
|
|
"Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==",
|
|
|
|
"testing.",
|
|
|
|
], [
|
|
|
|
"arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==",
|
|
|
|
"testing.\n",
|
|
|
|
], [
|
|
|
|
"WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==",
|
|
|
|
"01234567890123456789012345678901234567890123456789012",
|
|
|
|
]];
|
|
|
|
|
|
|
|
for test in &tests {
|
|
|
|
let out = priv_key
|
2023-01-10 13:59:31 -07:00
|
|
|
.decrypt(Pkcs1v15Encrypt, &Base64::decode_vec(test[0]).unwrap())
|
2018-07-24 01:01:44 +02:00
|
|
|
.unwrap();
|
|
|
|
assert_eq!(out, test[1].as_bytes());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_encrypt_decrypt_pkcs1v15() {
|
2022-03-14 14:22:48 +00:00
|
|
|
let mut rng = ChaCha8Rng::from_seed([42; 32]);
|
2018-07-24 01:01:44 +02:00
|
|
|
let priv_key = get_private_key();
|
|
|
|
let k = priv_key.size();
|
|
|
|
|
|
|
|
for i in 1..100 {
|
2022-03-13 19:50:05 +00:00
|
|
|
let mut input = vec![0u8; i * 8];
|
|
|
|
rng.fill_bytes(&mut input);
|
2018-07-24 01:01:44 +02:00
|
|
|
if input.len() > k - 11 {
|
|
|
|
input = input[0..k - 11].to_vec();
|
|
|
|
}
|
|
|
|
|
2021-07-26 23:25:13 +02:00
|
|
|
let pub_key: RsaPublicKey = priv_key.clone().into();
|
2018-07-24 01:01:44 +02:00
|
|
|
let ciphertext = encrypt(&mut rng, &pub_key, &input).unwrap();
|
|
|
|
assert_ne!(input, ciphertext);
|
2022-03-13 19:50:05 +00:00
|
|
|
|
|
|
|
let blind: bool = rng.next_u32() < (1u32 << 31);
|
2018-07-24 01:01:44 +02:00
|
|
|
let blinder = if blind { Some(&mut rng) } else { None };
|
|
|
|
let plaintext = decrypt(blinder, &priv_key, &ciphertext).unwrap();
|
|
|
|
assert_eq!(input, plaintext);
|
|
|
|
}
|
|
|
|
}
|
2018-07-24 14:31:06 +02:00
|
|
|
|
2023-02-13 18:35:20 +03:00
|
|
|
#[test]
|
|
|
|
fn test_decrypt_pkcs1v15_traits() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
let decrypting_key = DecryptingKey::new(priv_key);
|
|
|
|
|
|
|
|
let tests = [[
|
|
|
|
"gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==",
|
|
|
|
"x",
|
|
|
|
], [
|
|
|
|
"Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==",
|
|
|
|
"testing.",
|
|
|
|
], [
|
|
|
|
"arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==",
|
|
|
|
"testing.\n",
|
|
|
|
], [
|
|
|
|
"WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==",
|
|
|
|
"01234567890123456789012345678901234567890123456789012",
|
|
|
|
]];
|
|
|
|
|
|
|
|
for test in &tests {
|
|
|
|
let out = decrypting_key
|
|
|
|
.decrypt(&Base64::decode_vec(test[0]).unwrap())
|
|
|
|
.unwrap();
|
|
|
|
assert_eq!(out, test[1].as_bytes());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_encrypt_decrypt_pkcs1v15_traits() {
|
|
|
|
let mut rng = ChaCha8Rng::from_seed([42; 32]);
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
let k = priv_key.size();
|
|
|
|
let decrypting_key = DecryptingKey::new(priv_key);
|
|
|
|
|
|
|
|
for i in 1..100 {
|
|
|
|
let mut input = vec![0u8; i * 8];
|
|
|
|
rng.fill_bytes(&mut input);
|
|
|
|
if input.len() > k - 11 {
|
|
|
|
input = input[0..k - 11].to_vec();
|
|
|
|
}
|
|
|
|
|
|
|
|
let encrypting_key = decrypting_key.encrypting_key();
|
|
|
|
let ciphertext = encrypting_key.encrypt_with_rng(&mut rng, &input).unwrap();
|
|
|
|
assert_ne!(input, ciphertext);
|
|
|
|
|
|
|
|
let blind: bool = rng.next_u32() < (1u32 << 31);
|
|
|
|
let plaintext = if blind {
|
|
|
|
decrypting_key
|
|
|
|
.decrypt_with_rng(&mut rng, &ciphertext)
|
|
|
|
.unwrap()
|
|
|
|
} else {
|
|
|
|
decrypting_key.decrypt(&ciphertext).unwrap()
|
|
|
|
};
|
|
|
|
assert_eq!(input, plaintext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 14:31:06 +02:00
|
|
|
#[test]
|
|
|
|
fn test_sign_pkcs1v15() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
2022-03-13 19:50:05 +00:00
|
|
|
let tests = [(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
|
|
|
|
),
|
|
|
|
)];
|
2018-07-24 14:31:06 +02:00
|
|
|
|
2022-03-13 19:50:05 +00:00
|
|
|
for (text, expected) in &tests {
|
|
|
|
let digest = Sha1::digest(text.as_bytes()).to_vec();
|
2018-07-24 14:31:06 +02:00
|
|
|
|
2023-01-10 13:59:31 -07:00
|
|
|
let out = priv_key.sign(Pkcs1v15Sign::new::<Sha1>(), &digest).unwrap();
|
2018-07-24 14:31:06 +02:00
|
|
|
assert_ne!(out, digest);
|
|
|
|
assert_eq!(out, expected);
|
|
|
|
|
2022-03-14 14:22:48 +00:00
|
|
|
let mut rng = ChaCha8Rng::from_seed([42; 32]);
|
2018-07-24 14:31:06 +02:00
|
|
|
let out2 = priv_key
|
2023-01-10 13:59:31 -07:00
|
|
|
.sign_with_rng(&mut rng, Pkcs1v15Sign::new::<Sha1>(), &digest)
|
2018-07-24 14:31:06 +02:00
|
|
|
.unwrap();
|
|
|
|
assert_eq!(out2, expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 22:04:41 +02:00
|
|
|
#[test]
|
2022-08-19 20:46:40 +03:00
|
|
|
fn test_sign_pkcs1v15_signer() {
|
2018-07-24 22:04:41 +02:00
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
2022-09-16 20:25:05 +03:00
|
|
|
let tests = [(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
|
|
|
|
),
|
|
|
|
)];
|
|
|
|
|
2023-04-11 06:37:34 -06:00
|
|
|
let signing_key = SigningKey::<Sha1>::new(priv_key);
|
2022-09-16 20:25:05 +03:00
|
|
|
|
|
|
|
for (text, expected) in &tests {
|
2023-04-18 12:17:07 -06:00
|
|
|
let out = signing_key.sign(text.as_bytes()).to_bytes();
|
2022-09-16 20:25:05 +03:00
|
|
|
assert_ne!(out.as_ref(), text.as_bytes());
|
|
|
|
assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec());
|
|
|
|
assert_eq!(out.as_ref(), expected);
|
|
|
|
|
|
|
|
let mut rng = ChaCha8Rng::from_seed([42; 32]);
|
2023-04-18 12:17:07 -06:00
|
|
|
let out2 = signing_key
|
|
|
|
.sign_with_rng(&mut rng, text.as_bytes())
|
|
|
|
.to_bytes();
|
2022-09-16 20:25:05 +03:00
|
|
|
assert_eq!(out2.as_ref(), expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_sign_pkcs1v15_signer_sha2_256() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
2022-03-13 19:50:05 +00:00
|
|
|
let tests = [(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
2022-09-07 20:47:03 +03:00
|
|
|
"2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea"
|
|
|
|
"02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451b"
|
2022-03-13 19:50:05 +00:00
|
|
|
),
|
|
|
|
)];
|
2022-08-19 20:46:40 +03:00
|
|
|
|
2023-04-11 06:37:34 -06:00
|
|
|
let signing_key = SigningKey::<Sha256>::new(priv_key);
|
2022-08-19 20:46:40 +03:00
|
|
|
|
|
|
|
for (text, expected) in &tests {
|
2023-04-18 12:17:07 -06:00
|
|
|
let out = signing_key.sign(text.as_bytes()).to_bytes();
|
2022-09-07 20:47:03 +03:00
|
|
|
assert_ne!(out.as_ref(), text.as_bytes());
|
|
|
|
assert_eq!(out.as_ref(), expected);
|
2022-08-19 20:46:40 +03:00
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
let mut rng = ChaCha8Rng::from_seed([42; 32]);
|
2023-04-18 12:17:07 -06:00
|
|
|
let out2 = signing_key
|
|
|
|
.sign_with_rng(&mut rng, text.as_bytes())
|
|
|
|
.to_bytes();
|
2022-09-07 20:47:03 +03:00
|
|
|
assert_eq!(out2.as_ref(), expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-16 20:25:05 +03:00
|
|
|
#[test]
|
|
|
|
fn test_sign_pkcs1v15_signer_sha3_256() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
|
|
|
let tests = [(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
|
|
|
"55e9fba3354dfb51d2c8111794ea552c86afc2cab154652c03324df8c2c51ba7"
|
|
|
|
"2ff7c14de59a6f9ba50d90c13a7537cc3011948369f1f0ec4a49d21eb7e723f9"
|
|
|
|
),
|
|
|
|
)];
|
|
|
|
|
2023-04-11 06:37:34 -06:00
|
|
|
let signing_key = SigningKey::<Sha3_256>::new(priv_key);
|
2022-09-16 20:25:05 +03:00
|
|
|
|
|
|
|
for (text, expected) in &tests {
|
2023-04-18 12:17:07 -06:00
|
|
|
let out = signing_key.sign(text.as_bytes()).to_bytes();
|
2022-09-16 20:25:05 +03:00
|
|
|
assert_ne!(out.as_ref(), text.as_bytes());
|
|
|
|
assert_eq!(out.as_ref(), expected);
|
|
|
|
|
|
|
|
let mut rng = ChaCha8Rng::from_seed([42; 32]);
|
2023-04-18 12:17:07 -06:00
|
|
|
let out2 = signing_key
|
|
|
|
.sign_with_rng(&mut rng, text.as_bytes())
|
|
|
|
.to_bytes();
|
2022-09-16 20:25:05 +03:00
|
|
|
assert_eq!(out2.as_ref(), expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
#[test]
|
|
|
|
fn test_sign_pkcs1v15_digest_signer() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
|
|
|
let tests = [(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
2022-09-16 20:25:05 +03:00
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
|
2022-09-07 20:47:03 +03:00
|
|
|
),
|
|
|
|
)];
|
|
|
|
|
2023-04-11 06:37:34 -06:00
|
|
|
let signing_key = SigningKey::new(priv_key);
|
2022-09-07 20:47:03 +03:00
|
|
|
|
|
|
|
for (text, expected) in &tests {
|
2022-09-16 20:25:05 +03:00
|
|
|
let mut digest = Sha1::new();
|
2022-09-07 20:47:03 +03:00
|
|
|
digest.update(text.as_bytes());
|
2023-04-18 12:17:07 -06:00
|
|
|
let out = signing_key.sign_digest(digest).to_bytes();
|
2022-09-07 20:47:03 +03:00
|
|
|
assert_ne!(out.as_ref(), text.as_bytes());
|
|
|
|
assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec());
|
2022-08-19 20:46:40 +03:00
|
|
|
assert_eq!(out.as_ref(), expected);
|
|
|
|
|
|
|
|
let mut rng = ChaCha8Rng::from_seed([42; 32]);
|
2022-09-16 20:25:05 +03:00
|
|
|
let mut digest = Sha1::new();
|
2022-09-07 20:47:03 +03:00
|
|
|
digest.update(text.as_bytes());
|
2023-04-18 12:17:07 -06:00
|
|
|
let out2 = signing_key
|
|
|
|
.sign_digest_with_rng(&mut rng, digest)
|
|
|
|
.to_bytes();
|
2022-08-19 20:46:40 +03:00
|
|
|
assert_eq!(out2.as_ref(), expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_verify_pkcs1v15() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
|
|
|
let tests = [
|
|
|
|
(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
|
|
|
|
),
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
|
|
|
|
),
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
];
|
2021-07-26 23:25:13 +02:00
|
|
|
let pub_key: RsaPublicKey = priv_key.into();
|
2018-07-24 22:04:41 +02:00
|
|
|
|
2022-08-19 20:46:40 +03:00
|
|
|
for (text, sig, expected) in &tests {
|
2022-03-13 19:50:05 +00:00
|
|
|
let digest = Sha1::digest(text.as_bytes()).to_vec();
|
2018-07-24 22:04:41 +02:00
|
|
|
|
2023-01-10 13:59:31 -07:00
|
|
|
let result = pub_key.verify(Pkcs1v15Sign::new::<Sha1>(), &digest, sig);
|
2022-08-19 20:46:40 +03:00
|
|
|
match expected {
|
|
|
|
true => result.expect("failed to verify"),
|
|
|
|
false => {
|
|
|
|
result.expect_err("expected verifying error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_verify_pkcs1v15_signer() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
|
|
|
let tests = [
|
|
|
|
(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
2022-09-16 20:25:05 +03:00
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
|
2022-08-19 20:46:40 +03:00
|
|
|
),
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
2022-09-16 20:25:05 +03:00
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
|
2022-08-19 20:46:40 +03:00
|
|
|
),
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
];
|
|
|
|
let pub_key: RsaPublicKey = priv_key.into();
|
2023-04-11 06:37:34 -06:00
|
|
|
let verifying_key = VerifyingKey::<Sha1>::new(pub_key);
|
2022-08-19 20:46:40 +03:00
|
|
|
|
|
|
|
for (text, sig, expected) in &tests {
|
2022-12-05 05:03:38 +03:00
|
|
|
let result = verifying_key.verify(
|
|
|
|
text.as_bytes(),
|
|
|
|
&Signature::try_from(sig.as_slice()).unwrap(),
|
|
|
|
);
|
2022-08-19 20:46:40 +03:00
|
|
|
match expected {
|
|
|
|
true => result.expect("failed to verify"),
|
|
|
|
false => {
|
|
|
|
result.expect_err("expected verifying error");
|
|
|
|
}
|
|
|
|
}
|
2018-07-24 22:04:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:47:03 +03:00
|
|
|
#[test]
|
|
|
|
fn test_verify_pkcs1v15_digest_signer() {
|
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
|
|
|
let tests = [
|
|
|
|
(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
2022-09-16 20:25:05 +03:00
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
|
2022-09-07 20:47:03 +03:00
|
|
|
),
|
|
|
|
true,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"Test.\n",
|
|
|
|
hex!(
|
2022-09-16 20:25:05 +03:00
|
|
|
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
|
|
|
|
"6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
|
2022-09-07 20:47:03 +03:00
|
|
|
),
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
];
|
|
|
|
let pub_key: RsaPublicKey = priv_key.into();
|
2023-04-11 06:37:34 -06:00
|
|
|
let verifying_key = VerifyingKey::new(pub_key);
|
2022-09-07 20:47:03 +03:00
|
|
|
|
|
|
|
for (text, sig, expected) in &tests {
|
2022-09-16 20:25:05 +03:00
|
|
|
let mut digest = Sha1::new();
|
2022-09-07 20:47:03 +03:00
|
|
|
digest.update(text.as_bytes());
|
2022-12-05 05:03:38 +03:00
|
|
|
let result =
|
|
|
|
verifying_key.verify_digest(digest, &Signature::try_from(sig.as_slice()).unwrap());
|
2022-09-07 20:47:03 +03:00
|
|
|
match expected {
|
|
|
|
true => result.expect("failed to verify"),
|
|
|
|
false => {
|
|
|
|
result.expect_err("expected verifying error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-11 06:37:34 -06:00
|
|
|
|
2018-07-24 14:31:06 +02:00
|
|
|
#[test]
|
|
|
|
fn test_unpadded_signature() {
|
|
|
|
let msg = b"Thu Dec 19 18:06:16 EST 2013\n";
|
2022-03-13 19:50:05 +00:00
|
|
|
let expected_sig = Base64::decode_vec("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==").unwrap();
|
2018-07-24 14:31:06 +02:00
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
2023-04-17 06:40:24 -06:00
|
|
|
let sig = priv_key.sign(Pkcs1v15Sign::new_unprefixed(), msg).unwrap();
|
2018-07-24 14:31:06 +02:00
|
|
|
assert_eq!(expected_sig, sig);
|
|
|
|
|
2021-07-26 23:25:13 +02:00
|
|
|
let pub_key: RsaPublicKey = priv_key.into();
|
2018-07-24 22:04:41 +02:00
|
|
|
pub_key
|
2023-04-17 06:40:24 -06:00
|
|
|
.verify(Pkcs1v15Sign::new_unprefixed(), msg, &sig)
|
2018-07-24 22:04:41 +02:00
|
|
|
.expect("failed to verify");
|
2018-07-24 14:31:06 +02:00
|
|
|
}
|
2022-08-19 20:46:40 +03:00
|
|
|
|
|
|
|
#[test]
|
2022-09-22 19:03:46 +03:00
|
|
|
fn test_unpadded_signature_hazmat() {
|
2022-08-19 20:46:40 +03:00
|
|
|
let msg = b"Thu Dec 19 18:06:16 EST 2013\n";
|
2022-09-22 19:03:46 +03:00
|
|
|
let expected_sig = Base64::decode_vec("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==").unwrap();
|
2022-08-19 20:46:40 +03:00
|
|
|
let priv_key = get_private_key();
|
|
|
|
|
2023-04-11 06:37:34 -06:00
|
|
|
let signing_key = SigningKey::<Sha1>::new_unprefixed(priv_key);
|
2023-04-18 12:17:07 -06:00
|
|
|
let sig = signing_key
|
|
|
|
.sign_prehash(msg)
|
|
|
|
.expect("Failure during sign")
|
|
|
|
.to_bytes();
|
2022-08-19 20:46:40 +03:00
|
|
|
assert_eq!(sig.as_ref(), expected_sig);
|
|
|
|
|
2022-12-05 05:03:38 +03:00
|
|
|
let verifying_key = signing_key.verifying_key();
|
2022-08-19 20:46:40 +03:00
|
|
|
verifying_key
|
2023-04-18 12:17:07 -06:00
|
|
|
.verify_prehash(msg, &Signature::try_from(expected_sig.as_slice()).unwrap())
|
2022-08-19 20:46:40 +03:00
|
|
|
.expect("failed to verify");
|
|
|
|
}
|
2020-03-06 23:10:55 +01:00
|
|
|
}
|