Browse Source

Split public and private asymmetric keys into two different types.

Matthew Carr 2 years ago
parent
commit
dd19b80c56

+ 1 - 0
crates/.vscode/settings.json

@@ -11,6 +11,7 @@
         "encrypter",
         "Hashable",
         "newtype",
+        "pkey",
         "PKCS",
         "readcap",
         "readcaps",

+ 195 - 175
crates/btnode/src/crypto/mod.rs

@@ -6,7 +6,7 @@ use super::*;
 use openssl::{
     error::ErrorStack,
     encrypt::{Encrypter, Decrypter},
-    pkey::{PKey, Public as OsslPublic},
+    pkey::{PKey, Public, Private},
     symm::{Cipher, encrypt as openssl_encrypt, decrypt as openssl_decrypt},
     rand::rand_bytes,
     rsa::{Rsa, Padding as OpensslPadding},
@@ -14,8 +14,14 @@ use openssl::{
     sign::{Signer as OsslSigner, Verifier as OsslVerifier}
 };
 use serde_block_tree::{self, to_vec, from_vec, write_to};
-use serde::de::{DeserializeOwned};
-use std::str::FromStr;
+use serde::{
+    de::{self, DeserializeOwned, Deserializer, SeqAccess, Visitor},
+    ser::{Serializer, SerializeStruct},
+};
+use std::{
+    str::FromStr,
+    sync::Arc,
+};
 use strum_macros::{EnumString, EnumDiscriminants, Display};
 
 /// Data that may or may not be encrypted.
@@ -195,33 +201,6 @@ impl Default for Signature {
     }
 }
 
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
-pub(crate) enum RsaPadding {
-    None,
-    Pkcs1,
-    Pkcs1Oaep,
-    Pkcs1Pss,
-}
-
-impl Default for RsaPadding {
-    fn default() -> Self {
-        RsaPadding::Pkcs1
-    }
-}
-
-impl Copy for RsaPadding {}
-
-impl From<RsaPadding> for OpensslPadding {
-    fn from(padding: RsaPadding) -> OpensslPadding {
-        match padding {
-            RsaPadding::None => OpensslPadding::NONE,
-            RsaPadding::Pkcs1 => OpensslPadding::PKCS1,
-            RsaPadding::Pkcs1Oaep => OpensslPadding::PKCS1_OAEP,
-            RsaPadding::Pkcs1Pss => OpensslPadding::PKCS1_PSS,
-        }
-    }
-}
-
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
 #[strum_discriminants(name(SymKeyKind))]
 pub(crate) enum SymKey {
@@ -264,7 +243,7 @@ impl SymKey {
         }
     }
 
-    fn params<'a>(&'a self) -> SymParams<'a> {
+    fn params(&self) -> SymParams {
         let (cipher, key, iv) = match self {
             SymKey::Aes256Cbc { key, iv } => (Cipher::aes_256_cbc(), key, Some(iv.as_slice())),
             SymKey::Aes256Ctr { key, iv } => (Cipher::aes_256_ctr(), key, Some(iv.as_slice())),
@@ -274,53 +253,109 @@ impl SymKey {
 }
 
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
-pub(crate) struct Public;
-
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
-pub(crate) struct Private;
+pub(crate) enum AsymKeyKind {
+    Rsa,
+}
 
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
-#[strum_discriminants(name(AsymKeyKind))]
-pub(crate) enum AsymKey<T> {
-    Rsa {
-        der: Vec<u8>,
-        padding: RsaPadding,
-        kind: T,
-    }
+#[derive(Debug, Clone)]
+pub(crate) struct AsymKeyPub {
+    kind: AsymKeyKind,
+    pkey: PKey<Public>,
 }
 
-impl<T> AsymKey<T> {
-    pub(crate) fn as_slice(&self) -> &[u8] {
-        match self {
-            AsymKey::Rsa { der, .. } => der.as_slice()
-        }
+impl AsymKeyPub {
+    pub(crate) fn new(kind: AsymKeyKind, der: &[u8]) -> Result<AsymKeyPub> {
+        let pkey = match kind {
+            AsymKeyKind::Rsa => {
+                let rsa = Rsa::public_key_from_der(der).map_err(Error::from)?;
+                PKey::from_rsa(rsa).map_err(Error::from)?
+            }
+        };
+        Ok(AsymKeyPub { kind, pkey })
     }
 
     fn digest(&self) -> MessageDigest {
-        match self {
-            AsymKey::Rsa { .. } => MessageDigest::sha256(),
+        match self.kind {
+            AsymKeyKind::Rsa => MessageDigest::sha256(),
         }
     }
 
     fn signature_buf(&self) -> Signature {
-        match self {
-            AsymKey::Rsa { .. } => Signature::new(SignatureKind::Rsa),
+        match self.kind {
+            AsymKeyKind::Rsa => Signature::new(SignatureKind::Rsa),
+        }
+    }
+
+    fn padding(&self) -> Option<OpensslPadding> {
+        match self.kind {
+            AsymKeyKind::Rsa => Some(OpensslPadding::PKCS1),
+        }
+    }
+
+    fn to_der(&self) -> Result<Vec<u8>> {
+        self.pkey.public_key_to_der().map_err(Error::from)
+    }
+}
+
+impl<'de> Deserialize<'de> for AsymKeyPub {
+    fn deserialize<D: Deserializer<'de>>(d: D) -> std::result::Result<Self, D::Error> {
+        const FIELDS: &[&str] = &["kind", "pkey"];
+
+        struct StructVisitor;
+
+        impl<'de> Visitor<'de> for StructVisitor {
+            type Value = AsymKeyPub;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+                formatter.write_fmt(format_args!("struct {}", stringify!(AsymKeyPub)))
+            }
+
+            fn visit_seq<V: SeqAccess<'de>>(
+                self, mut seq: V
+            ) -> std::result::Result<AsymKeyPub, V::Error> {
+                let kind: AsymKeyKind = seq.next_element()?
+                    .ok_or_else(|| de::Error::missing_field(FIELDS[0]))?;
+                let der: Vec<u8> = seq.next_element()?
+                    .ok_or_else(|| de::Error::missing_field(FIELDS[1]))?;
+                AsymKeyPub::new(kind, der.as_slice())
+                    .map_err(|e| de::Error::custom(e.to_string()))
+            }
         }
+
+        d.deserialize_struct(stringify!(AsymKeyPub), FIELDS, StructVisitor)
+    }
+}
+
+impl Serialize for AsymKeyPub {
+    fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
+        let mut struct_s = s.serialize_struct(stringify!(AsymKeyPub), 2)?;
+        struct_s.serialize_field("kind", &self.kind)?;
+        let der = self.pkey.public_key_to_der().unwrap();
+        struct_s.serialize_field("pkey", der.as_slice())?;
+        struct_s.end()
+    }
+}
+
+impl PartialEq for AsymKeyPub {
+    fn eq(&self, other: &Self) -> bool {
+        self.kind == other.kind && self.pkey.public_eq(&other.pkey)
     }
 }
 
-impl<T> Owned for AsymKey<T> {
+impl Owned for AsymKeyPub {
     fn owner_of_kind(&self, kind: HashKind) -> Principal {
         match kind {
             HashKind::Sha2_256 => {
                 let mut buf = [0; 32];
-                let bytes = hash(MessageDigest::sha256(), self.as_slice()).unwrap();
+                let der = self.to_der().unwrap();
+                let bytes = hash(MessageDigest::sha256(), der.as_slice()).unwrap();
                 buf.copy_from_slice(&*bytes);
                 Principal(Hash::Sha2_256(buf))
             },
             HashKind::Sha2_512 => {
                 let mut buf = [0; 64];
-                let bytes = hash(MessageDigest::sha512(), self.as_slice()).unwrap();
+                let der = self.to_der().unwrap();
+                let bytes = hash(MessageDigest::sha512(), der.as_slice()).unwrap();
                 buf.copy_from_slice(&*bytes);
                 Principal(Hash::Sha2_512(buf))
             }
@@ -328,29 +363,74 @@ impl<T> Owned for AsymKey<T> {
     }
 }
 
+pub(crate) trait AsymKeyPriv: Decryptor + Signer {}
+
+pub(crate) struct RsaPriv {
+    pkey: PKey<Private>,
+}
+
+impl RsaPriv {
+    fn digest() -> MessageDigest {
+        MessageDigest::sha256()
+    }
+
+    fn signature_buf() -> Signature {
+        Signature::new(SignatureKind::Rsa)
+    }
+}
+
+impl Decryptor for RsaPriv {
+    fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        let decrypter = Decrypter::new(&self.pkey).map_err(Error::from)?;
+        let buffer_len = decrypter.decrypt_len(slice).map_err(Error::from)?;
+        let mut plaintext = vec![0; buffer_len];
+        let plaintext_len = decrypter.decrypt(slice, &mut plaintext).map_err(Error::from)?;
+        plaintext.truncate(plaintext_len);
+        Ok(plaintext)
+    }
+}
+
+impl Signer for RsaPriv {
+    fn sign<'a>(&self, parts: &mut dyn Iterator<Item=&'a [u8]>) -> Result<Signature> {
+        let digest = RsaPriv::digest();
+        let mut signature = RsaPriv::signature_buf();
+
+        let mut signer = OsslSigner::new(digest, &self.pkey).map_err(Error::from)?;
+        for part in parts {
+            signer.update(part).map_err(Error::from)?;
+        }
+        let buf = signature.as_mut_slice();
+        signer.sign(buf).map_err(Error::from)?;
+        Ok(signature)
+    }
+}
+
+impl AsymKeyPriv for RsaPriv {}
+
+impl RsaPriv {
+    pub(crate) fn new(der: &[u8]) -> Result<RsaPriv> {
+        let rsa = Rsa::private_key_from_der(der).map_err(Error::from)?;
+        let pkey = PKey::from_rsa(rsa).map_err(Error::from)?;
+        Ok(RsaPriv { pkey })
+    }
+}
+
 pub(crate) struct KeyPair {
-    pub(crate) public: AsymKey<Public>,
-    pub(crate) private: AsymKey<Private>,
+    pub(crate) public: AsymKeyPub,
+    pub(crate) private: Arc<dyn AsymKeyPriv>,
 }
 
 impl KeyPair {
     pub(crate) fn generate(kind: AsymKeyKind) -> Result<KeyPair> {
         match kind {
             AsymKeyKind::Rsa => {
-                let key = PKey::from_rsa(Rsa::generate(4096)?)?;
-                let public = key.public_key_to_der().map_err(Error::from)?;
-                let private = key.private_key_to_der().map_err(Error::from)?;
+                let key = Rsa::generate(4096)?;
+                // TODO: Separating the keys this way seems inefficient. Investigate alternatives.
+                let public_der = key.public_key_to_der().map_err(Error::from)?;
+                let private_der = key.private_key_to_der().map_err(Error::from)?;
                 Ok(KeyPair {
-                    public: AsymKey::Rsa {
-                        der: public,
-                        padding: RsaPadding::default(),
-                        kind: Public,
-                    },
-                    private: AsymKey::Rsa {
-                        der: private,
-                        padding: RsaPadding::default(),
-                        kind: Private,
-                    },
+                    public: AsymKeyPub::new(AsymKeyKind::Rsa, public_der.as_slice())?,
+                    private: Arc::new(RsaPriv::new(private_der.as_slice())?),
                 })
             },
         }
@@ -374,15 +454,11 @@ impl Encryptor for SymKey {
     }
 }
 
-impl Encryptor for AsymKey<Public> {
+impl Encryptor for AsymKeyPub {
     fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        let (pkey, rsa_padding) = match self {
-            AsymKey::Rsa { der, padding, .. }
-                => (PKey::public_key_from_der(der.as_slice()).map_err(Error::from)?, Some(padding)),
-        };
-        let mut encrypter = Encrypter::new(&pkey).map_err(Error::from)?;
-        if let Some(padding) = rsa_padding {
-            encrypter.set_rsa_padding((*padding).into()).map_err(Error::from)?;
+        let mut encrypter = Encrypter::new(&self.pkey).map_err(Error::from)?;
+        if let Some(padding) = self.padding() {
+            encrypter.set_rsa_padding(padding).map_err(Error::from)?;
         }
         let buffer_len = encrypter.encrypt_len(slice).map_err(Error::from)?;
         let mut ciphertext = vec![0; buffer_len];
@@ -393,7 +469,7 @@ impl Encryptor for AsymKey<Public> {
     }
 }
 
-trait Decryptor {
+pub(crate) trait Decryptor {
     fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>>;
 }
 
@@ -404,56 +480,17 @@ impl Decryptor for SymKey {
     }
 }
 
-impl Decryptor for AsymKey<Private> {
-    fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        let pkey = match self {
-            AsymKey::Rsa { der, .. }
-                => PKey::private_key_from_der(der.as_slice()).map_err(Error::from)?
-        };
-        let decrypter = Decrypter::new(&pkey).map_err(Error::from)?;
-        let buffer_len = decrypter.decrypt_len(slice).map_err(Error::from)?;
-        let mut plaintext = vec![0; buffer_len];
-        let plaintext_len = decrypter.decrypt(slice, &mut plaintext).map_err(Error::from)?;
-        plaintext.truncate(plaintext_len);
-        Ok(plaintext)
-    }
-}
-
 pub(crate) trait Signer {
-    fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature>;
-}
-
-impl Signer for AsymKey<Private> {
-    fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
-        let pkey = match self {
-            AsymKey::Rsa { der, .. } => {
-                let rsa = Rsa::private_key_from_der(der.as_slice()).map_err(Error::from)?;
-                PKey::from_rsa(rsa).map_err(Error::from)?
-            }
-        };
-        let digest = self.digest();
-        let mut signature = self.signature_buf();
-
-        let mut signer = OsslSigner::new(digest, &pkey).map_err(Error::from)?;
-        for part in parts {
-            signer.update(part).map_err(Error::from)?;
-        }
-        let buf = signature.as_mut_slice();
-        signer.sign(buf).map_err(Error::from)?;
-        Ok(signature)
-    }
+    fn sign<'a>(&self, parts: &mut dyn Iterator<Item=&'a [u8]>) -> Result<Signature>;
 }
 
-struct VerifyAlgo {
-    key: PKey<OsslPublic>,
-    digest: MessageDigest,
+trait Verifier {
+    fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool>;
 }
 
-impl VerifyAlgo {
-    fn verify<'a, I: Iterator<Item = &'a [u8]>>(
-        &'a self, parts: I, signature: &[u8]
-    ) -> Result<bool> {
-        let mut verifier = OsslVerifier::new(self.digest, &self.key).map_err(Error::from)?;
+impl Verifier for AsymKeyPub {
+    fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
+        let mut verifier = OsslVerifier::new(self.digest(), &self.pkey).map_err(Error::from)?;
         for part in parts {
             verifier.update(part).map_err(Error::from)?;
         }
@@ -461,21 +498,6 @@ impl VerifyAlgo {
     }
 }
 
-impl TryFrom<&AsymKey<Public>> for VerifyAlgo {
-    type Error = Error;
-    fn try_from(key: &AsymKey<Public>) -> Result<VerifyAlgo> {
-        match key {
-            AsymKey::Rsa { der, .. } => {
-                let rsa = Rsa::public_key_from_der(der.as_slice()).map_err(Error::from)?;
-                Ok(VerifyAlgo {
-                    key: PKey::from_rsa(rsa).map_err(Error::from)?,
-                    digest: MessageDigest::sha256()
-                })
-            },
-        }
-    }
-}
-
 pub(crate) fn encrypt_block(
     mut block: Block, principal: &Principal, key: &KeyPair
 ) -> Result<Block> {
@@ -485,7 +507,7 @@ pub(crate) fn encrypt_block(
     };
     let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
         .ok_or(Error::NoReadCap)?;
-    let block_key = decrypt(read_cap, &key.private)?;
+    let block_key = decrypt(read_cap, key.private.as_ref())?;
     let new_body = block_key.encrypt(&body)?;
     block.body = Cryptotext::Cipher(new_body);
     block.readcaps.insert(principal_owned, encrypt(&block_key, &key.public)?);
@@ -493,7 +515,7 @@ pub(crate) fn encrypt_block(
 }
 
 pub(crate) fn decrypt_block(
-    mut block: Block, principal: &Principal, key: &AsymKey<Private>
+    mut block: Block, principal: &Principal, key: &dyn AsymKeyPriv
 ) -> Result<Block> {
     let body = match block.body {
         Cryptotext::Plain(_) => return Ok(block),
@@ -508,14 +530,16 @@ pub(crate) fn decrypt_block(
     Ok(block)
 }
 
-fn encrypt<'a, T: Serialize, K: Encryptor>(value: &T, key: &K) -> Result<Cryptotext<T>> {
+fn encrypt<T: Serialize, K: Encryptor>(value: &T, key: &K) -> Result<Cryptotext<T>> {
     let data = to_vec(value).map_err(Error::from)?;
     let vec = key.encrypt(&data);
     Ok(Cryptotext::Cipher(vec?))
 }
 
-fn decrypt<'a, T: Serialize + DeserializeOwned, K: Decryptor>(
-    cryptotext: Cryptotext<T>, key: &K
+/// TODO: When the trait upcasting feature lands in the stable channel change the type of `key`
+/// to `dyn Decryptor`. Tracking issue: https://github.com/rust-lang/rust/issues/65991
+fn decrypt<T: Serialize + DeserializeOwned>(
+    cryptotext: Cryptotext<T>, key: &dyn AsymKeyPriv
 ) -> Result<T> {
     let data = match cryptotext {
         Cryptotext::Plain(value) => return Ok(value),
@@ -553,13 +577,14 @@ fn get_body(block: &Block) -> Result<&[u8]> {
 }
 
 pub(crate) fn sign_block(
-    block: &mut Block, writecap: Writecap, priv_key: AsymKey<Private>
+    block: &mut Block, writecap: Writecap, priv_key: &dyn AsymKeyPriv
 ) -> Result<()> {
     block.writecap = writecap;
     let body = get_body(block)?;
     let sig_header = SigHeader::from(&*block);
     let header = to_vec(&sig_header)?;
-    block.signature = priv_key.sign([header.as_slice(), body].into_iter())?;
+    let signature = priv_key.sign(&mut [header.as_slice(), body].into_iter())?;
+    block.signature = signature;
     Ok(())
 }
 
@@ -567,9 +592,8 @@ pub(crate) fn verify_block(block: &Block) -> Result<bool> {
     let body = get_body(block)?;
     let sig_header = SigHeader::from(&*block);
     let header = to_vec(&sig_header)?;
-    let verify_algo = VerifyAlgo::try_from(&block.writecap.signing_key)?;
     let parts = [header.as_slice(), body].into_iter();
-    verify_algo.verify(parts, block.signature.as_slice())
+    block.writecap.signing_key.verify(parts, block.signature.as_slice())
 }
 
 #[derive(Serialize)]
@@ -577,7 +601,7 @@ struct WritecapSig<'a> {
     issued_to: &'a Principal,
     path: &'a Path,
     expires: &'a Epoch,
-    signing_key: &'a AsymKey<Public>,
+    signing_key: &'a AsymKeyPub,
 }
 
 impl<'a> From<&'a Writecap> for WritecapSig<'a> {
@@ -591,9 +615,11 @@ impl<'a> From<&'a Writecap> for WritecapSig<'a> {
     }
 }
 
-pub(crate) fn sign_writecap<S: Signer>(writecap: &mut Writecap, priv_key: &S) -> Result<()> {
+/// TODO: When the trait upcasting feature lands in the stable channel change the type of `priv_key`
+/// to `dyn Decryptor`. Tracking issue: https://github.com/rust-lang/rust/issues/65991
+pub(crate) fn sign_writecap(writecap: &mut Writecap, priv_key: &dyn AsymKeyPriv) -> Result<()> {
     let sig_input = to_vec(&WritecapSig::from(&*writecap))?;
-    writecap.signature = priv_key.sign([sig_input.as_slice()].into_iter())?;
+    writecap.signature = priv_key.sign(&mut [sig_input.as_slice()].into_iter())?;
     Ok(())
 }
 
@@ -639,9 +665,7 @@ pub(crate) fn verify_writecap(
         let sig = WritecapSig::from(writecap);
         sig_input.clear();
         write_to(&sig, &mut sig_input).map_err(|e| WritecapAuthzErr::Serde(e.to_string()))?;
-        let verify_algo = VerifyAlgo::try_from(&writecap.signing_key)
-            .map_err(|e| WritecapAuthzErr::Crypto(e.to_string()))?;
-        let valid = verify_algo
+        let valid = writecap.signing_key 
             .verify([sig_input.as_slice()].into_iter(), writecap.signature.as_slice())
             .map_err(|e| WritecapAuthzErr::Crypto(e.to_string()))?;
         if !valid {
@@ -681,7 +705,7 @@ mod tests {
             Cryptotext::Plain(_) => false
         };
         assert!(encrypted);
-        actual = decrypt_block(actual, principal, &key.private)?;
+        actual = decrypt_block(actual, principal, key.private.as_ref())?;
         assert_eq!(expected, actual);
         Ok(())
     }
@@ -709,9 +733,8 @@ mod tests {
         let key = make_key_pair();
         let header = b"About: lyrics".as_slice();
         let message = b"Everything that feels so good is bad bad bad.".as_slice();
-        let signature = key.private.sign([header, message].into_iter())?;
-        let verifier = VerifyAlgo::try_from(&key.public)?;
-        let verified = verifier.verify([header, message].into_iter(), signature.as_slice())?;
+        let signature = key.private.sign(&mut [header, message].into_iter())?;
+        let verified = key.public.verify([header, message].into_iter(), signature.as_slice())?;
         assert_eq!(true, verified);
         Ok(())
     }
@@ -731,7 +754,7 @@ mod tests {
             next: None,
         };
         block = encrypt_block(block, &principal, &key)?;
-        sign_block(&mut block, writecap, key.private)?;
+        sign_block(&mut block, writecap, key.private.as_ref())?;
         assert_eq!(true, verify_block(&block)?);
         Ok(())
     }
@@ -794,11 +817,10 @@ mod tests {
     fn verify_writecap_invalid_not_chained() -> Result<()> {
         let (mut root_writecap, root_key) = make_self_signed_writecap()?;
         root_writecap.issued_to = Principal(Hash::Sha2_256([0; 32]));
-        sign_writecap(&mut root_writecap, &root_key.private)?;
-        let node_key = AsymKey::Rsa {
-            der: Vec::from(NODE_PUBLIC_KEY),
-            padding: RsaPadding::Pkcs1,
-            kind: Public {},
+        sign_writecap(&mut root_writecap, root_key.private.as_ref())?;
+        let node_key = AsymKeyPub {
+            kind: AsymKeyKind::Rsa,
+            pkey: PKey::from_rsa(Rsa::public_key_from_der(NODE_PUBLIC_KEY.as_slice())?)?
         };
         let node_principal = node_key.owner();
         let writecap = make_writecap_trusted_by(
@@ -813,11 +835,10 @@ mod tests {
         let (mut root_writecap, root_key) = make_self_signed_writecap()?;
         let owner = Principal(Hash::Sha2_256([0; 32]));
         root_writecap.path = make_path_with_owner(owner, vec![]);
-        sign_writecap(&mut root_writecap, &root_key.private)?;
-        let node_key = AsymKey::Rsa {
-            der: Vec::from(NODE_PUBLIC_KEY),
-            padding: RsaPadding::Pkcs1,
-            kind: Public {}
+        sign_writecap(&mut root_writecap, root_key.private.as_ref())?;
+        let node_key = AsymKeyPub {
+            kind: AsymKeyKind::Rsa,
+            pkey: PKey::from_rsa(Rsa::public_key_from_der(NODE_PUBLIC_KEY.as_slice())?)?
         };
         let node_owner = node_key.owner();
         let writecap = make_writecap_trusted_by(
@@ -874,13 +895,12 @@ mod tests {
 
         #[test]
         fn rsa_signature_len() -> Result<()> {
-            use openssl::rsa::Rsa;
             let key = make_key_pair();
-            let der = key.private.as_slice();
-            let rsa = Rsa::private_key_from_der(der)?;
-            let pkey = PKey::from_rsa(rsa)?;
-            let signer = OsslSigner::new(key.private.digest(), &pkey)?;
-            assert_eq!(RSA_SIG_LEN, signer.len()?);
+            let signature = key.private.sign(&mut [NODE_PUBLIC_KEY.as_slice()].into_iter())?;
+            let length = match signature {
+                Signature::Rsa(data) => data.len(),
+            };
+            assert_eq!(RSA_SIG_LEN, length);
             Ok(())
         }
     }

+ 1 - 1
crates/btnode/src/crypto/tpm.rs

@@ -36,7 +36,7 @@ impl HasResponseCode for Tss2ResponseCode {
 
 impl HasResponseCode for TSS2_RC {
     fn response_code(&self) -> TSS2_RC {
-        self.clone()
+        *self
     }
 }
 

+ 2 - 2
crates/btnode/src/main.rs

@@ -25,7 +25,7 @@ mod test_helpers;
 mod serde_tests;
 
 mod crypto;
-use crypto::{Hash, HashKind, Signature, SymKey, AsymKey, Public, Cryptotext};
+use crypto::{Hash, HashKind, Signature, SymKey, AsymKeyPub, Cryptotext};
 
 /// A Block tagged with its version number. When a block of a previous version is received over
 /// the network or read from the filesystem, it is upgraded to the current version before being
@@ -79,7 +79,7 @@ struct Writecap {
     /// The point in time after which this write cap is no longer valid.
     expires: Epoch,
     /// The public key used to sign this write cap.
-    signing_key: AsymKey<Public>,
+    signing_key: AsymKeyPub,
     /// A digital signature which covers all of the fields in the write cap except for next.
     signature: Signature,
     /// The next write cap in the chain leading back to the root.

+ 20 - 18
crates/btnode/src/test_helpers.rs

@@ -3,7 +3,7 @@
 use super::*;
 use crypto::*;
 use serde_block_tree::{Error, Result};
-use std::{ fs::File, io::Write, fmt::Write as FmtWrite };
+use std::{ fs::File, io::Write, fmt::Write as FmtWrite, sync::Arc };
 
 pub const PRINCIPAL: [u8; 32] = [
     0x75, 0x28, 0xA9, 0xE0, 0x9D, 0x24, 0xBA, 0xB3, 0x79, 0x56, 0x15, 0x68, 0xFD, 0xA4, 0xE2, 0xA4,
@@ -462,6 +462,11 @@ pub const BLOCK_IV: [u8; 16] = [
     0xF2, 0xB5, 0x64, 0xF3, 0x82, 0xC6, 0xEC, 0x1E, 0x35, 0xAA, 0x34, 0xD1, 0x40, 0xA3, 0xA8, 0xB3,
 ];
 
+/// Converts the given error to a serde_block_tree error by turning it into a message.
+fn convert_err<E: Display>(err: E) -> Error {
+    Error::Message(err.to_string())
+}
+
 pub(crate) fn make_principal() -> Principal {
     Principal(Hash::Sha2_256(PRINCIPAL))
 }
@@ -498,23 +503,15 @@ pub(crate) fn make_writecap_trusted_by(
         signature: Signature::default(),
         next: Some(Box::from(next)),
     };
-    crypto::sign_writecap(&mut writecap, &trusting_key.private)
-        .map_err(|e| Error::Message(e.to_string()))?;
+    crypto::sign_writecap(&mut writecap, trusting_key.private.as_ref())
+        .map_err(convert_err)?;
     Ok(writecap)
 }
 
 pub(crate) fn make_key_pair() -> KeyPair {
     KeyPair {
-        public: AsymKey::Rsa {
-            der: Vec::from(ROOT_PUBLIC_KEY),
-            padding: RsaPadding::default(),
-            kind: Public
-        },
-        private: AsymKey::Rsa {
-            der: Vec::from(ROOT_PRIVATE_KEY),
-            padding: RsaPadding::default(),
-            kind: Private,
-        },
+        public: AsymKeyPub::new(AsymKeyKind::Rsa, ROOT_PUBLIC_KEY.as_slice()).unwrap(),
+        private: Arc::new(RsaPriv::new(ROOT_PRIVATE_KEY.as_slice()).unwrap()),
     }
 }
 
@@ -534,8 +531,8 @@ pub(crate) fn make_self_signed_writecap_with(key: &KeyPair) -> Result<Writecap>
         signature: Signature::default(),
         next: None,
     };
-    crypto::sign_writecap(&mut writecap, &key.private)
-        .map_err(|e| Error::Message(e.to_string()))?;
+    crypto::sign_writecap(&mut writecap, key.private.as_ref())
+        .map_err(convert_err)?;
     Ok(writecap)
 }
 
@@ -580,10 +577,15 @@ impl<'a> NamedSlice<'a> {
 }
 
 fn write_rsa_keys_to_file(path: &str) -> Result<()> {
-    let key = KeyPair::generate(AsymKeyKind::Rsa).map_err(|e| Error::Message(e.to_string()))?;
+    use openssl::{
+        rsa::Rsa,
+    };
+    let rsa = Rsa::generate(4096).map_err(convert_err)?;
+    let public_der = rsa.public_key_to_der().map_err(convert_err)?;
+    let private_der = rsa.private_key_to_der().map_err(convert_err)?;
     let slices = [
-        NamedSlice::new("PUBLIC", key.public.as_slice()),
-        NamedSlice::new("PRIVATE", key.private.as_slice())
+        NamedSlice::new("PUBLIC", public_der.as_slice()),
+        NamedSlice::new("PRIVATE", private_der.as_slice())
     ];
     write_to_file(path, slices.into_iter())
 }