|
@@ -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();
|