Browse Source

Added signing and verifying via RSA.

Matthew Carr 2 years ago
parent
commit
fb6bd051a5
1 changed files with 75 additions and 3 deletions
  1. 75 3
      crates/node/src/crypto.rs

+ 75 - 3
crates/node/src/crypto.rs

@@ -8,6 +8,8 @@ use openssl::{
     symm::{Cipher, encrypt as openssl_encrypt, decrypt as openssl_decrypt},
     rand::rand_bytes,
     rsa::{Rsa, Padding as OpensslPadding},
+    hash::MessageDigest,
+    sign::{Signer, Verifier}
 };
 use serde_block_tree::{self, to_vec, from_vec};
 use serde::de::{DeserializeOwned};
@@ -27,6 +29,7 @@ pub enum Error {
     NoReadCap,
     NoKeyAvailable,
     MissingPrivateKey,
+    KeyVariantUnsupported,
     Message(String),
     Serde(serde_block_tree::Error),
 }
@@ -267,6 +270,64 @@ impl<'a> TryFrom<&'a Key> for DecryptionAlgo<'a> {
     }
 }
 
+struct SignAlgo {
+    key: PKey<Private>,
+    digest: MessageDigest,
+}
+
+impl SignAlgo {
+    fn sign(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        let mut signer = Signer::new(self.digest, &self.key).map_err(Error::from)?;
+        signer.update(slice).map_err(Error::from)?;
+        signer.sign_to_vec().map_err(Error::from)
+    }
+}
+
+impl TryFrom<&Key> for SignAlgo {
+    type Error = Error;
+    fn try_from(key: &Key) -> Result<SignAlgo> {
+        match key {
+            Key::Rsa { private: Some(private), .. } => {
+                let rsa = Rsa::private_key_from_der(private.as_slice()).map_err(Error::from)?;
+                Ok(SignAlgo {
+                    key: PKey::from_rsa(rsa).map_err(Error::from)?,
+                    digest: MessageDigest::sha256()
+                })
+            },
+            _ => Err(Error::KeyVariantUnsupported)
+        }
+    }
+}
+
+struct VerifyAlgo {
+    key: PKey<Public>,
+    digest: MessageDigest,
+}
+
+impl VerifyAlgo {
+    fn verify(&self, slice: &[u8], signature: &[u8]) -> Result<bool> {
+        let mut verifier = Verifier::new(self.digest, &self.key).map_err(Error::from)?;
+        verifier.update(slice).map_err(Error::from)?;
+        verifier.verify(signature).map_err(Error::from)
+    }
+}
+
+impl TryFrom<&Key> for VerifyAlgo {
+    type Error = Error;
+    fn try_from(key: &Key) -> Result<VerifyAlgo> {
+        match key {
+            Key::Rsa { public, .. } => {
+                let rsa = Rsa::public_key_from_der(public.as_slice()).map_err(Error::from)?;
+                Ok(VerifyAlgo {
+                    key: PKey::from_rsa(rsa).map_err(Error::from)?,
+                    digest: MessageDigest::sha256()
+                })
+            },
+            _ => Err(Error::KeyVariantUnsupported)
+        }
+    }
+}
+
 pub(crate) fn encrypt_block(
     versioned_block: VersionedBlock, principal: &Principal, key: &Key
 ) -> Result<VersionedBlock> {
@@ -390,6 +451,18 @@ mod tests {
         encrypt_decrypt_block_test_case(block, &principal, &key)
     }
 
+    #[test]
+    fn rsa_sign_and_verify() -> Result<()> {
+        let key = Key::generate(KeyId::Rsa)?;
+        let message = b"Everything that feels so good is bad bad bad.";
+        let signer = SignAlgo::try_from(&key)?;
+        let signature = signer.sign(message)?;
+        let verifier = VerifyAlgo::try_from(&key)?;
+        let verified = verifier.verify(message, signature.as_slice())?;
+        assert_eq!(true, verified);
+        Ok(())
+    }
+
     /// Tests that validate the dependencies of this module.
     mod dependency_tests {
         use super::*;
@@ -398,10 +471,9 @@ mod tests {
             nid::Nid,
         };
 
-        /// This test validates that data decrypted with the `Crypter` API matches data that was
-        /// previously encrypted using it.
+        /// This test validates that data encrypted with AES 256 CBC can later be decrypted.
         #[test]
-        fn crypter() {
+        fn aes_256_cbc_roundtrip() {
             use super::*;
             let expected = b"We attack at the crack of noon!";
             let cipher = Cipher::aes_256_cbc();