|
@@ -10,7 +10,7 @@ use openssl::{
|
|
|
pkey::{PKey, HasPublic, HasPrivate},
|
|
|
symm::{Cipher, encrypt as openssl_encrypt, decrypt as openssl_decrypt},
|
|
|
rand::rand_bytes,
|
|
|
- rsa::{Rsa, Padding as OpensslPadding},
|
|
|
+ rsa::{Rsa as OsslRsa, Padding as OpensslPadding},
|
|
|
hash::{hash, MessageDigest},
|
|
|
sign::{Signer as OsslSigner, Verifier as OsslVerifier}
|
|
|
};
|
|
@@ -193,33 +193,31 @@ impl Display for Hash {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub(crate) const RSA_KEY_BYTES: usize = 384;
|
|
|
-
|
|
|
/// A cryptographic signature.
|
|
|
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
|
|
|
-#[strum_discriminants(name(SignatureKind))]
|
|
|
-pub(crate) enum Signature {
|
|
|
- #[serde(with = "BigArray")]
|
|
|
- Rsa([u8; RSA_KEY_BYTES]),
|
|
|
+#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
|
+pub struct Signature {
|
|
|
+ kind: Sign,
|
|
|
+ data: Vec<u8>,
|
|
|
}
|
|
|
|
|
|
impl Signature {
|
|
|
- fn new(id: SignatureKind) -> Signature {
|
|
|
- match id {
|
|
|
- SignatureKind::Rsa => Signature::Rsa([0; RSA_KEY_BYTES])
|
|
|
- }
|
|
|
+ pub fn empty(kind: Sign) -> Signature {
|
|
|
+ let data = vec![0; kind.key_len() as usize];
|
|
|
+ Signature { kind, data }
|
|
|
}
|
|
|
|
|
|
- fn as_slice(&self) -> &[u8] {
|
|
|
- match self {
|
|
|
- Signature::Rsa(buf) => buf.as_slice()
|
|
|
- }
|
|
|
+ pub fn copy_from(kind: Sign, from: &[u8]) -> Signature {
|
|
|
+ let mut data = vec![0; kind.key_len() as usize];
|
|
|
+ data.as_mut_slice().copy_from_slice(from);
|
|
|
+ Signature { kind, data }
|
|
|
}
|
|
|
|
|
|
- fn as_mut_slice(&mut self) -> &mut [u8] {
|
|
|
- match self {
|
|
|
- Signature::Rsa(buf) => buf.as_mut_slice()
|
|
|
- }
|
|
|
+ pub fn as_slice(&self) -> &[u8] {
|
|
|
+ self.data.as_slice()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
|
|
+ self.data.as_mut_slice()
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -235,12 +233,6 @@ impl AsMut<[u8]> for Signature {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl Default for Signature {
|
|
|
- fn default() -> Self {
|
|
|
- Signature::Rsa([0; RSA_KEY_BYTES])
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
|
|
|
#[strum_discriminants(name(SymKeyKind))]
|
|
|
pub(crate) enum SymKey {
|
|
@@ -306,6 +298,22 @@ impl Decrypter for SymKey {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#[repr(u32)]
|
|
|
+#[derive(Debug, Display, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
|
|
+pub enum KeyLen {
|
|
|
+ Bits256 = 32,
|
|
|
+ Bits512 = 64,
|
|
|
+ Bits2048 = 256,
|
|
|
+ Bits3072 = 384,
|
|
|
+ Bits4096 = 512,
|
|
|
+}
|
|
|
+
|
|
|
+impl KeyLen {
|
|
|
+ const fn bits(self) -> u32 {
|
|
|
+ 8 * self as u32
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
pub trait Scheme: for<'de> Deserialize<'de> + Serialize
|
|
|
+ Copy + std::fmt::Debug + PartialEq + Into<Self::Kind>
|
|
|
{
|
|
@@ -316,6 +324,7 @@ pub trait Scheme: for<'de> Deserialize<'de> + Serialize
|
|
|
fn public_from_der(self, der: &[u8]) -> Result<PKey<Public>>;
|
|
|
fn private_from_der(self, der: &[u8]) -> Result<PKey<Private>>;
|
|
|
fn generate(self) -> Result<AsymKeyPair<Self::Kind>>;
|
|
|
+ fn key_len(self) -> KeyLen;
|
|
|
}
|
|
|
|
|
|
pub enum SchemeKind {
|
|
@@ -364,11 +373,22 @@ impl Scheme for Encrypt {
|
|
|
Encrypt::RsaEsOaep(inner) => inner.generate(),
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ fn key_len(self) -> KeyLen {
|
|
|
+ match self {
|
|
|
+ Encrypt::RsaEsOaep(inner) => inner.key_len(),
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
impl Encrypt {
|
|
|
+ pub const RSA_OAEP_2048_SHA_256: Encrypt = Encrypt::RsaEsOaep(RsaEsOaep {
|
|
|
+ key_len: KeyLen::Bits2048,
|
|
|
+ hash_kind: HashKind::Sha2_256,
|
|
|
+ });
|
|
|
+
|
|
|
pub const RSA_OAEP_3072_SHA_256: Encrypt = Encrypt::RsaEsOaep(RsaEsOaep {
|
|
|
- key_bytes: 384,
|
|
|
+ key_len: KeyLen::Bits3072,
|
|
|
hash_kind: HashKind::Sha2_256,
|
|
|
});
|
|
|
}
|
|
@@ -414,38 +434,53 @@ impl Scheme for Sign {
|
|
|
Sign::RsaSsaPss(inner) => inner.generate(),
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ fn key_len(self) -> KeyLen {
|
|
|
+ self.key_len_const()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
impl Sign {
|
|
|
+ pub const RSA_PSS_2048_SHA_256: Sign = Sign::RsaSsaPss(RsaSsaPss {
|
|
|
+ key_bits: KeyLen::Bits2048,
|
|
|
+ hash_kind: HashKind::Sha2_256,
|
|
|
+ });
|
|
|
+
|
|
|
pub const RSA_PSS_3072_SHA_256: Sign = Sign::RsaSsaPss(RsaSsaPss {
|
|
|
- key_bytes: 384,
|
|
|
+ key_bits: KeyLen::Bits3072,
|
|
|
hash_kind: HashKind::Sha2_256,
|
|
|
});
|
|
|
|
|
|
- fn sig_buf(&self) -> Signature {
|
|
|
+ const fn key_len_const(self) -> KeyLen {
|
|
|
match self {
|
|
|
- Sign::RsaSsaPss(_) => Signature::Rsa([0u8; RSA_KEY_BYTES]),
|
|
|
+ Sign::RsaSsaPss(inner) => inner.key_bits,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+enum Rsa {}
|
|
|
+
|
|
|
+impl Rsa {
|
|
|
+ /// The default public exponent to use for generated RSA keys.
|
|
|
+ const EXP: u32 = 65537; // 2**16 + 1
|
|
|
+
|
|
|
+ fn generate<S: Scheme>(scheme: S) -> Result<AsymKeyPair<S>> {
|
|
|
+ let key = OsslRsa::generate(scheme.key_len().bits())?;
|
|
|
+ // TODO: Separating the keys this way seems inefficient. Investigate alternatives.
|
|
|
+ let public_der = key.public_key_to_der()?;
|
|
|
+ let private_der = key.private_key_to_der()?;
|
|
|
+ let public = AsymKey::<Public, S>::new(scheme, &public_der)?;
|
|
|
+ let private = AsymKey::<Private, S>::new(scheme, &private_der)?;
|
|
|
+ Ok(AsymKeyPair { public, private })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
|
|
|
pub struct RsaEsOaep {
|
|
|
- key_bytes: usize,
|
|
|
+ key_len: KeyLen,
|
|
|
hash_kind: HashKind,
|
|
|
}
|
|
|
|
|
|
-fn generate_rsa<S: Scheme>(scheme: S) -> Result<AsymKeyPair<S>> {
|
|
|
- let key_bits = 8 * u32::try_from(RSA_KEY_BYTES)?;
|
|
|
- let key = Rsa::generate(key_bits)?;
|
|
|
- // TODO: Separating the keys this way seems inefficient. Investigate alternatives.
|
|
|
- let public_der = key.public_key_to_der()?;
|
|
|
- let private_der = key.private_key_to_der()?;
|
|
|
- let public = AsymKey::<Public, S>::new(scheme, &public_der)?;
|
|
|
- let private = AsymKey::<Private, S>::new(scheme, &private_der)?;
|
|
|
- Ok(AsymKeyPair { public, private })
|
|
|
-}
|
|
|
-
|
|
|
impl Scheme for RsaEsOaep {
|
|
|
type Kind = Encrypt;
|
|
|
|
|
@@ -470,7 +505,11 @@ impl Scheme for RsaEsOaep {
|
|
|
}
|
|
|
|
|
|
fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
|
|
|
- generate_rsa(self.into())
|
|
|
+ Rsa::generate(self.into())
|
|
|
+ }
|
|
|
+
|
|
|
+ fn key_len(self) -> KeyLen {
|
|
|
+ self.key_len
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -482,7 +521,7 @@ impl From<RsaEsOaep> for Encrypt {
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
|
|
|
pub struct RsaSsaPss {
|
|
|
- key_bytes: usize,
|
|
|
+ key_bits: KeyLen,
|
|
|
hash_kind: HashKind,
|
|
|
}
|
|
|
|
|
@@ -510,7 +549,11 @@ impl Scheme for RsaSsaPss {
|
|
|
}
|
|
|
|
|
|
fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
|
|
|
- generate_rsa(self.into())
|
|
|
+ Rsa::generate(self.into())
|
|
|
+ }
|
|
|
+
|
|
|
+ fn key_len(self) -> KeyLen {
|
|
|
+ self.key_bits
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -590,12 +633,6 @@ impl<S: Scheme> AsymKey<Private, S> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl<P: KeyPrivacy> AsymKey<P, Sign> {
|
|
|
- fn signature_buf(&self) -> Signature {
|
|
|
- self.scheme.sig_buf()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
impl<'de, S: Scheme> Deserialize<'de> for AsymKey<Public, S> {
|
|
|
fn deserialize<D: Deserializer<'de>>(d: D) -> std::result::Result<Self, D::Error> {
|
|
|
const FIELDS: &[&str] = &["scheme", "pkey"];
|
|
@@ -698,7 +735,7 @@ impl Signer for AsymKey<Private, Sign> {
|
|
|
for part in parts {
|
|
|
signer.update(part)?;
|
|
|
}
|
|
|
- let mut signature = self.scheme.sig_buf();
|
|
|
+ let mut signature = Signature::empty(self.scheme);
|
|
|
signer.sign(signature.as_mut_slice())?;
|
|
|
Ok(signature)
|
|
|
}
|
|
@@ -1133,7 +1170,7 @@ mod tests {
|
|
|
#[test]
|
|
|
fn verify_writecap_invalid_signature() -> Result<()> {
|
|
|
let mut writecap = make_writecap(vec!["apps", "verse"])?;
|
|
|
- writecap.signature = Signature::default();
|
|
|
+ writecap.signature = Signature::empty(Sign::RSA_PSS_3072_SHA_256);
|
|
|
let result = verify_writecap(&writecap, &writecap.path);
|
|
|
if let Err(Error::InvalidSignature) = result {
|
|
|
Ok(())
|
|
@@ -1244,16 +1281,5 @@ mod tests {
|
|
|
assert_eq!(44, public_len);
|
|
|
assert_eq!(48, private_len);
|
|
|
}
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn rsa_signature_len() -> Result<()> {
|
|
|
- let key = make_key_pair();
|
|
|
- let signature = key.sign([NODE_PUBLIC_KEY.as_slice()].into_iter())?;
|
|
|
- let length = match signature {
|
|
|
- Signature::Rsa(data) => data.len(),
|
|
|
- };
|
|
|
- assert_eq!(RSA_KEY_BYTES, length);
|
|
|
- Ok(())
|
|
|
- }
|
|
|
}
|
|
|
}
|