123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914 |
- use super::*;
- use openssl::{
- error::ErrorStack,
- encrypt::{Encrypter, Decrypter},
- pkey::{PKey, Public, Private},
- symm::{Cipher, encrypt as openssl_encrypt, decrypt as openssl_decrypt},
- rand::rand_bytes,
- rsa::{Rsa, Padding as OpensslPadding},
- hash::{hash, MessageDigest},
- sign::{Signer, Verifier}
- };
- use serde_block_tree::{self, to_vec, from_vec, write_to};
- use serde::de::{DeserializeOwned};
- use std::str::FromStr;
- use strum_macros::{EnumString, EnumDiscriminants, Display};
- #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
- pub enum Cryptotext<T: Serialize> {
-
- Plain(T),
-
- Cipher(Vec<u8>),
- }
- #[derive(Debug)]
- pub enum Error {
- NoReadCap,
- NoKeyAvailable,
- MissingPrivateKey,
- KeyVariantUnsupported,
- BlockNotEncrypted,
- InvalidFormat,
- Message(String),
- Serde(serde_block_tree::Error),
- }
- impl Display for Error {
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- match self {
- Error::NoReadCap => write!(f, "no readcap"),
- Error::NoKeyAvailable => write!(f, "no key available"),
- Error::MissingPrivateKey => write!(f, "private key was missing"),
- Error::KeyVariantUnsupported => write!(f, "unsupported key variant"),
- Error::BlockNotEncrypted => write!(f, "block was not encrypted"),
- Error::InvalidFormat => write!(f, "invalid format"),
- Error::Message(message) => f.write_str(message.as_str()),
- Error::Serde(serde_err) => serde_err.fmt(f),
- }
- }
- }
- impl From<ErrorStack> for Error {
- fn from(error: ErrorStack) -> Error {
- Error::Message(error.to_string())
- }
- }
- impl From<serde_block_tree::Error> for Error {
- fn from(error: serde_block_tree::Error) -> Error {
- Error::Serde(error)
- }
- }
- pub type Result<T> = std::result::Result<T, Error>;
- #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable, Clone, EnumDiscriminants)]
- #[strum_discriminants(derive(EnumString, Display))]
- pub enum Hash {
- Sha2_256([u8; 32]),
- #[serde(with = "BigArray")]
- Sha2_512([u8; 64]),
- }
- impl Hash {
-
-
- const HASH_SEP: char = ':';
- }
- impl From<HashDiscriminants> for Hash {
- fn from(discriminant: HashDiscriminants) -> Hash {
- match discriminant {
- HashDiscriminants::Sha2_512 => Hash::Sha2_512([0u8; 64]),
- HashDiscriminants::Sha2_256 => Hash::Sha2_256([0u8; 32])
- }
- }
- }
- impl AsRef<[u8]> for Hash {
- fn as_ref(&self) -> &[u8] {
- match self {
- Hash::Sha2_256(arr) => arr,
- Hash::Sha2_512(arr) => arr
- }
- }
- }
- impl AsMut<[u8]> for Hash {
- fn as_mut(&mut self) -> &mut [u8] {
- match self {
- Hash::Sha2_256(arr) => arr,
- Hash::Sha2_512(arr) => arr
- }
- }
- }
- impl TryFrom<&str> for Hash {
- type Error = Error;
- fn try_from(string: &str) -> Result<Hash> {
- let mut split: Vec<&str> = string.split(Self::HASH_SEP).collect();
- if split.len() != 2 {
- return Err(Error::InvalidFormat)
- };
- let second = split.pop().ok_or(Error::InvalidFormat)?;
- let first = split.pop().ok_or(Error::InvalidFormat)?;
- let mut hash = Hash::from(HashDiscriminants::from_str(first)
- .map_err(|_| Error::InvalidFormat)?);
- base64_url::decode_to_slice(second, hash.as_mut())
- .map_err(|_| Error::InvalidFormat)?;
- Ok(hash)
- }
- }
- impl Display for Hash {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let hash_type: HashDiscriminants = self.into();
- let hash_data = base64_url::encode(self.as_ref());
- write!(f, "{}{}{}", hash_type, Hash::HASH_SEP, hash_data)
- }
- }
- const RSA_SIG_LEN: usize = 512;
- #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
- pub enum Signature {
- #[serde(with = "BigArray")]
- Rsa([u8; RSA_SIG_LEN]),
- }
- pub enum SignatureId {
- Rsa
- }
- impl Signature {
- fn new(id: SignatureId) -> Signature {
- match id {
- SignatureId::Rsa => Signature::Rsa([0; RSA_SIG_LEN])
- }
- }
- fn as_slice(&self) -> &[u8] {
- match self {
- Signature::Rsa(buf) => buf.as_slice()
- }
- }
- fn as_mut_slice(&mut self) -> &mut [u8] {
- match self {
- Signature::Rsa(buf) => buf.as_mut_slice()
- }
- }
- }
- impl Default for Signature {
- fn default() -> Self {
- Signature::Rsa([0; RSA_SIG_LEN])
- }
- }
- pub enum KeyId {
-
- Aes256Cbc,
- Aes256Ctr,
- Rsa,
- }
- #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
- pub enum RsaPadding {
- None,
- Pkcs1,
- Pkcs1Oaep,
- Pkcs1Pss,
- }
- 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)]
- pub enum Key {
-
-
-
- Aes256Cbc {
- key: [u8; 32],
- iv: [u8; 16],
- },
-
- Aes256Ctr {
- key: [u8; 32],
- iv: [u8; 16]
- },
- Rsa {
- public: Vec<u8>,
- private: Option<Vec<u8>>,
- padding: RsaPadding,
- },
- }
- impl Key {
-
-
- fn key_slice(&self) -> Option<&[u8]> {
- match self {
- Key::Aes256Cbc { key, .. } => Some(key),
- Key::Aes256Ctr { key, .. } => Some(key),
- Key::Rsa { private, .. } => match private {
- Some(key) => Some(key.as_slice()),
- None => None,
- },
- }
- }
-
- fn iv_slice(&self) -> Option<&[u8]> {
- match self {
- Key::Aes256Cbc { iv, .. } => Some(iv),
- _ => None,
- }
- }
- pub fn generate(id: KeyId) -> Result<Key> {
- match id {
- KeyId::Aes256Cbc => {
- let mut key = [0; 32];
- let mut iv = [0; 16];
- rand_bytes(&mut key).map_err(Error::from)?;
- rand_bytes(&mut iv).map_err(Error::from)?;
- Ok(Key::Aes256Cbc { key, iv })
- },
- KeyId::Aes256Ctr => {
- let mut key = [0; 32];
- let mut iv = [0; 16];
- rand_bytes(&mut key).map_err(Error::from)?;
- rand_bytes(&mut iv).map_err(Error::from)?;
- Ok(Key::Aes256Ctr { key, iv })
- },
- KeyId::Rsa => {
- let key = PKey::from_rsa(Rsa::generate(4096)?)?;
- let public= key.public_key_to_der().map_err(Error::from)?;
- let private = Some(key.private_key_to_der().map_err(Error::from)?);
- Ok(Key::Rsa { public, private, padding: RsaPadding::Pkcs1 })
- },
- }
- }
-
- pub fn to_principal(&self) -> Principal {
- let slice = match self {
- Key::Rsa { public, .. } => public.as_slice(),
- Key::Aes256Cbc { key, .. } => key,
- Key::Aes256Ctr { key, .. } => key,
- };
- let mut buf = [0; 32];
- let bytes = hash(MessageDigest::sha256(), slice).unwrap();
- buf.copy_from_slice(&*bytes);
- Principal(Hash::Sha2_256(buf))
- }
- }
- enum EncryptionAlgo<'a> {
- Symmetric {
- cipher: Cipher,
- key: &'a [u8],
- iv: Option<&'a [u8]>
- },
- Asymmetric {
- key: PKey<Public>,
- rsa_padding: Option<OpensslPadding>,
- }
- }
- impl<'a> EncryptionAlgo<'a> {
- fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- match self {
- EncryptionAlgo::Symmetric { cipher, key, iv } => {
- openssl_encrypt(*cipher, key, *iv, slice).map_err(Error::from)
- },
- EncryptionAlgo::Asymmetric { key, rsa_padding } => {
- let mut encrypter = Encrypter::new(key).map_err(Error::from)?;
- if let Some(padding) = rsa_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];
- let ciphertext_len = encrypter.encrypt(slice, &mut ciphertext)
- .map_err(Error::from)?;
- ciphertext.truncate(ciphertext_len);
- Ok(ciphertext)
- }
- }
- }
- }
- impl<'a> TryFrom<&'a Key> for EncryptionAlgo<'a> {
- type Error = Error;
- fn try_from(key: &'a Key) -> Result<EncryptionAlgo<'a>> {
- match key {
- Key::Aes256Cbc { key: key_slice, iv } => Ok(EncryptionAlgo::Symmetric {
- cipher: Cipher::aes_256_cbc(),
- key: key_slice,
- iv: Some(iv),
- }),
- Key::Aes256Ctr { key: key_slice, iv } => Ok(EncryptionAlgo::Symmetric {
- cipher: Cipher::aes_256_ctr(),
- key: key_slice,
- iv: Some(iv),
- }),
- Key::Rsa { public, padding, .. } => {
- let pkey = PKey::public_key_from_der(public.as_slice())
- .map_err(|err| Error::Message(err.to_string()));
- Ok(EncryptionAlgo::Asymmetric { key: pkey?, rsa_padding: Some((*padding).into()) })
- },
- }
- }
- }
- enum DecryptionAlgo<'a> {
- Symmetric {
- cipher: Cipher,
- key: &'a [u8],
- iv: Option<&'a [u8]>
- },
- Asymmetric(PKey<Private>),
- }
- impl<'a> DecryptionAlgo<'a> {
- fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
- match self {
- DecryptionAlgo::Symmetric { cipher, key, iv } => {
- openssl_decrypt(*cipher, key, *iv, slice).map_err(Error::from)
- },
- DecryptionAlgo::Asymmetric(pkey) => {
- 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)
- },
- }
- }
- }
- impl<'a> TryFrom<&'a Key> for DecryptionAlgo<'a> {
- type Error = Error;
- fn try_from(key: &'a Key) -> Result<DecryptionAlgo<'a>> {
- match key {
- Key::Aes256Cbc { key: key_slice, iv } => Ok(DecryptionAlgo::Symmetric {
- cipher: Cipher::aes_256_cbc(),
- key: key_slice,
- iv: Some(iv),
- }),
- Key::Aes256Ctr { key: key_slice, iv } => Ok(DecryptionAlgo::Symmetric {
- cipher: Cipher::aes_256_ctr(),
- key: key_slice,
- iv: Some(iv),
- }),
- Key::Rsa { private, .. } => {
- let private = private.as_ref().ok_or(Error::MissingPrivateKey)?;
- let pkey = PKey::private_key_from_der(private.as_slice()).map_err(Error::from);
- Ok(DecryptionAlgo::Asymmetric(pkey?))
- }
- }
- }
- }
- struct SignAlgo {
- key: PKey<Private>,
- digest: MessageDigest,
- signature: Signature
- }
- impl SignAlgo {
- fn sign<'a, I: Iterator<Item = &'a [u8]>>(&mut self, parts: I) -> Result<()> {
- let mut signer = Signer::new(self.digest, &self.key).map_err(Error::from)?;
- for part in parts {
- signer.update(part).map_err(Error::from)?;
- }
- let buf = self.signature.as_mut_slice();
- signer.sign(buf).map_err(Error::from)?;
- Ok(())
- }
- }
- 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(),
- signature: Signature::new(SignatureId::Rsa)
- })
- },
- _ => Err(Error::KeyVariantUnsupported)
- }
- }
- }
- struct VerifyAlgo {
- key: PKey<Public>,
- digest: MessageDigest,
- }
- impl VerifyAlgo {
- fn verify<'a, I: Iterator<Item = &'a [u8]>>(
- &'a self, parts: I, signature: &[u8]
- ) -> Result<bool> {
- let mut verifier = Verifier::new(self.digest, &self.key).map_err(Error::from)?;
- for part in parts {
- verifier.update(part).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> {
- let VersionedBlock::V0(mut block) = versioned_block;
- let body = match block.body {
- Cryptotext::Cipher(_) => return Ok(VersionedBlock::V0(block)),
- Cryptotext::Plain(body) => body
- };
- let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
- .ok_or(Error::NoReadCap)?;
- let block_key = decrypt(read_cap, key)?;
- let new_body = encrypt_slice(&body, &block_key)?;
- block.body = Cryptotext::Cipher(new_body);
- block.readcaps.insert(principal_owned, encrypt(&block_key, key)?);
- Ok(VersionedBlock::V0(block))
- }
- pub(crate) fn decrypt_block(
- versioned_block: VersionedBlock, principal: &Principal, key: &Key
- ) -> Result<VersionedBlock> {
- let VersionedBlock::V0(mut block) = versioned_block;
- let body = match block.body {
- Cryptotext::Plain(_) => return Ok(VersionedBlock::V0(block)),
- Cryptotext::Cipher(body) => body
- };
- let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
- .ok_or(Error::NoReadCap)?;
- let block_key = decrypt(read_cap, key)?;
- let new_body = decrypt_slice(&body, &block_key)?;
- block.body = Cryptotext::Plain(new_body);
- block.readcaps.insert(principal_owned, Cryptotext::Plain(block_key));
- Ok(VersionedBlock::V0(block))
- }
- fn encrypt<T: Serialize>(value: &T, key: &Key) -> Result<Cryptotext<T>> {
- let data = to_vec(value).map_err(Error::from)?;
- let vec = encrypt_slice(&data, key);
- Ok(Cryptotext::Cipher(vec?))
- }
- fn decrypt<T: Serialize + DeserializeOwned>(cryptotext: Cryptotext<T>, key: &Key) -> Result<T> {
- let data = match cryptotext {
- Cryptotext::Plain(value) => return Ok(value),
- Cryptotext::Cipher(data) => data
- };
- let vec = decrypt_slice(&data, key);
- from_vec(&vec?).map_err(Error::from)
- }
- fn encrypt_slice(plaintext: &[u8], key: &Key) -> Result<Vec<u8>> {
- let algo = EncryptionAlgo::try_from(key)?;
- algo.encrypt(plaintext)
- }
- fn decrypt_slice(ciphertext: &[u8], key: &Key) -> Result<Vec<u8>> {
- let algo = DecryptionAlgo::try_from(key)?;
- algo.decrypt(ciphertext)
- }
- #[derive(Serialize)]
- struct SigHeader<'a> {
- path: &'a Path,
- readcaps: &'a HashMap<Principal, Cryptotext<Key>>,
- writecap: &'a Writecap,
- }
- impl<'a> From<&'a Block> for SigHeader<'a> {
- fn from(block: &'a Block) -> SigHeader<'a> {
- SigHeader {
- path: &block.path,
- readcaps: &block.readcaps,
- writecap: &block.writecap,
- }
- }
- }
- fn get_body(block: &Block) -> Result<&[u8]> {
- let body = match &block.body {
- Cryptotext::Cipher(body) => body,
- Cryptotext::Plain(_) => {
- return Err(Error::BlockNotEncrypted);
- }
- };
- Ok(body)
- }
- pub(crate) fn sign_block(versioned_block: &mut VersionedBlock, writecap: Writecap) -> Result<()> {
- let VersionedBlock::V0(block) = versioned_block;
- block.writecap = writecap;
- let body = get_body(block)?;
- let sig_header = SigHeader::from(&*block);
- let header = to_vec(&sig_header)?;
- let mut sign_algo = SignAlgo::try_from(&block.writecap.signing_key)?;
- sign_algo.sign([header.as_slice(), body].into_iter())?;
- block.signature = sign_algo.signature;
- Ok(())
- }
- pub(crate) fn verify_block(versioned_block: &VersionedBlock) -> Result<bool> {
- let VersionedBlock::V0(block) = versioned_block;
- 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();
- if !verify_algo.verify(parts, block.signature.as_slice())? {
- return Ok(false);
- }
- Ok(true)
- }
- #[derive(Serialize)]
- struct WritecapSig<'a> {
- issued_to: &'a Principal,
- path: &'a Path,
- expires: &'a Epoch,
- signing_key: &'a Key,
- }
- impl<'a> From<&'a Writecap> for WritecapSig<'a> {
- fn from(writecap: &'a Writecap) -> WritecapSig<'a> {
- WritecapSig {
- issued_to: &writecap.issued_to,
- path: &writecap.path,
- expires: &writecap.expires,
- signing_key: &writecap.signing_key,
- }
- }
- }
- pub(crate) fn sign_writecap(writecap: &mut Writecap, key: &Key) -> Result<()> {
- let mut sign_algo = SignAlgo::try_from(key)?;
- let sig_input = to_vec(&WritecapSig::from(&*writecap))?;
- sign_algo.sign([sig_input.as_slice()].into_iter())?;
- writecap.signature = sign_algo.signature;
- Ok(())
- }
- #[derive(Debug, PartialEq)]
- pub(crate) enum WritecapAuthzErr {
-
- UnauthorizedPath,
-
- Expired,
-
- NotChained,
-
- InvalidSignature,
-
- RootDoesNotOwnPath,
-
- Serde(String),
-
- Crypto(String),
- }
- pub(crate) fn verify_writecap(
- mut writecap: &Writecap, path: &Path
- ) -> std::result::Result<(), WritecapAuthzErr> {
- let mut prev: Option<&Writecap> = None;
- let mut sig_input = Vec::new();
- let now = Epoch::now();
- loop {
- if !writecap.path.contains(path) {
- return Err(WritecapAuthzErr::UnauthorizedPath);
- }
- if writecap.expires <= now {
- return Err(WritecapAuthzErr::Expired);
- }
- if let Some(prev) = &prev {
- if prev.signing_key.to_principal() != writecap.issued_to {
- return Err(WritecapAuthzErr::NotChained);
- }
- }
- 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
- .verify([sig_input.as_slice()].into_iter(), writecap.signature.as_slice())
- .map_err(|e| WritecapAuthzErr::Crypto(e.to_string()))?;
- if !valid {
- return Err(WritecapAuthzErr::InvalidSignature);
- }
- match &writecap.next {
- Some(next) => {
- prev = Some(writecap);
- writecap = next;
- },
- None => {
-
-
- if writecap.signing_key.to_principal() == path.owner {
- return Ok(());
- }
- else {
- return Err(WritecapAuthzErr::RootDoesNotOwnPath)
- }
- }
- }
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- use test_helpers::*;
- #[test]
- fn key_aes256cbc_key_slice_is_correct() -> Result<()> {
- let key = Key::Aes256Cbc { key: KEY, iv: IV };
- let key_part = key.key_slice().ok_or(Error::NoKeyAvailable);
- assert_eq!(KEY, key_part?);
- Ok(())
- }
- #[test]
- fn key_aes256cbc_iv_slice_is_correct() {
- let key = Key::Aes256Cbc { key: KEY, iv: IV };
- let iv_part = key.iv_slice().unwrap();
- assert_eq!(IV, iv_part);
- }
- fn encrypt_decrypt_block_test_case(
- mut actual: VersionedBlock, principal: &Principal, key: &Key
- ) -> Result<()> {
- let expected = actual.clone();
- actual = encrypt_block(actual, principal, key)?;
- actual = decrypt_block(actual, principal, key)?;
- assert_eq!(expected, actual);
- Ok(())
- }
- fn make_versioned_block(principal: Principal, block_key: Key) -> Result<VersionedBlock> {
- let mut block = make_block()?;
- block.readcaps.clear();
- block.readcaps.insert(principal, Cryptotext::Plain(block_key));
- Ok(VersionedBlock::V0(block))
- }
- #[test]
- fn encrypt_decrypt_block_aes256cbc() -> Result<()> {
- let principal = make_principal();
- let block_key = Key::Aes256Cbc { key: BLOCK_KEY, iv: BLOCK_IV };
- let block = make_versioned_block(principal.clone(), block_key)?;
- let key = Key::Aes256Cbc { key: KEY, iv: IV };
- encrypt_decrypt_block_test_case(block, &principal, &key)
- }
- #[test]
- fn encrypt_decrypt_block_aes256ctr() -> Result<()> {
- let principal = make_principal();
- let block_key = Key::Aes256Ctr { key: BLOCK_KEY, iv: BLOCK_IV };
- let block = make_versioned_block(principal.clone(), block_key)?;
- let key = Key::Aes256Ctr { key: KEY, iv: IV };
- encrypt_decrypt_block_test_case(block, &principal, &key)
- }
- #[test]
- fn encrypt_decrypt_block_rsa() -> Result<()> {
- let principal = make_principal();
- let block_key = Key::Aes256Ctr { key: BLOCK_KEY, iv: BLOCK_IV };
- let block = make_versioned_block(principal.clone(), block_key)?;
- let key = Key::generate(KeyId::Rsa)?;
- encrypt_decrypt_block_test_case(block, &principal, &key)
- }
- #[test]
- fn rsa_sign_and_verify() -> Result<()> {
- let key = Key::generate(KeyId::Rsa)?;
- let header = b"About: lyrics".as_slice();
- let message = b"Everything that feels so good is bad bad bad.".as_slice();
- let mut signer = SignAlgo::try_from(&key)?;
- signer.sign([header, message].into_iter())?;
- let verifier = VerifyAlgo::try_from(&key)?;
- let verified = verifier.verify([header, message].into_iter(), signer.signature.as_slice())?;
- assert_eq!(true, verified);
- Ok(())
- }
- #[test]
- fn sign_verify_block_rsa() -> Result<()> {
- let principal = make_principal();
- let block_key = Key::Aes256Ctr { key: BLOCK_KEY, iv: BLOCK_IV };
- let mut block = make_versioned_block(principal.clone(), block_key)?;
- let key = Key::generate(KeyId::Rsa)?;
- let writecap = Writecap {
- issued_to: Principal(Hash::Sha2_256(PRINCIPAL)),
- path: make_path(vec!["contacts", "emergency"]),
- expires: Epoch(1649904316),
- signing_key: key,
- signature: Signature::Rsa(SIGNATURE),
- next: None,
- };
- block = encrypt_block(block, &principal, &writecap.signing_key)?;
- sign_block(&mut block, writecap)?;
- assert_eq!(true, verify_block(&block)?);
- Ok(())
- }
- #[test]
- fn hash_to_string() {
- let hash = make_principal().0;
- let string = hash.to_string();
- assert_eq!("Sha2_256:dSip4J0kurN5VhVo_aTipM-ywOOWrqJuRRVQ7aa-bew", string)
- }
- #[test]
- fn hash_to_string_round_trip() -> Result<()> {
- let expected = make_principal().0;
- let string = expected.to_string();
- let actual = Hash::try_from(string.as_str())?;
- assert_eq!(expected, actual);
- Ok(())
- }
- #[test]
- fn verify_writecap_valid() -> Result<()> {
- let writecap = make_writecap()?;
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Ok(()), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_signature() -> Result<()> {
- let mut writecap = make_writecap()?;
- writecap.signature = Signature::default();
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::InvalidSignature), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_path_not_contained() -> Result<()> {
- let writecap = make_writecap()?;
- let mut path = writecap.path.clone();
- path.components.pop();
-
-
- let result = verify_writecap(&writecap, &path);
- assert_eq!(Err(WritecapAuthzErr::UnauthorizedPath), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_expired() -> Result<()> {
- let mut writecap = make_writecap()?;
- writecap.expires = Epoch::now() - Duration::from_secs(1);
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::Expired), result);
- Ok(())
- }
- #[test]
- 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)?;
- let node_key = Key::Rsa {
- public: Vec::from(NODE_PUBLIC_KEY), private: None, padding: RsaPadding::Pkcs1
- };
- let writecap = make_writecap_trusted_by(
- root_writecap, &root_key, &node_key, vec!["apps", "contacts"])?;
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::NotChained), result);
- Ok(())
- }
- #[test]
- fn verify_writecap_invalid_root_doesnt_own_path() -> Result<()> {
- 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)?;
- let node_key = Key::Rsa {
- public: Vec::from(NODE_PUBLIC_KEY), private: None, padding: RsaPadding::Pkcs1
- };
- let writecap = make_writecap_trusted_by(
- root_writecap, &root_key, &node_key, vec!["apps", "contacts"])?;
- let result = verify_writecap(&writecap, &writecap.path);
- assert_eq!(Err(WritecapAuthzErr::RootDoesNotOwnPath), result);
- Ok(())
- }
-
- mod dependency_tests {
- use super::*;
- use openssl::{
- ec::{EcGroup, EcKey},
- nid::Nid,
- };
-
- #[test]
- fn aes_256_cbc_roundtrip() {
- use super::*;
- let expected = b"We attack at the crack of noon!";
- let cipher = Cipher::aes_256_cbc();
- let ciphertext = openssl_encrypt(cipher, &KEY, Some(&IV), expected).unwrap();
- let actual = openssl_decrypt(cipher, &KEY, Some(&IV), ciphertext.as_slice()).unwrap();
- assert_eq!(expected, actual.as_slice());
- }
-
- #[test]
- fn secp256k1_key_lengths() {
- let group = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
- let key = EcKey::generate(&group).unwrap();
- let public = key.public_key_to_der().unwrap();
- let private = key.private_key_to_der().unwrap();
- let public_len = public.len();
- let private_len = private.len();
- assert_eq!(88, public_len);
- assert_eq!(118, private_len);
- }
- #[test]
- fn ed25519_key_lengths() {
- let key = PKey::generate_x25519().unwrap();
- let public = key.public_key_to_der().unwrap();
- let private = key.private_key_to_der().unwrap();
- let public_len = public.len();
- let private_len = private.len();
- assert_eq!(44, public_len);
- assert_eq!(48, private_len);
- }
- #[test]
- fn rsa_signature_len() -> Result<()> {
- use openssl::rsa::Rsa;
- let key = Key::generate(KeyId::Rsa)?;
- let sign_algo = SignAlgo::try_from(&key)?;
- let private = match &key {
- Key::Rsa { private: Some(private), .. } => private,
- _ => return Err(Error::Message("Incorrect key returned.".to_string()))
- };
- let rsa = Rsa::private_key_from_der(private)?;
- let pkey = PKey::from_rsa(rsa)?;
- let signer = Signer::new(sign_algo.digest, &pkey)?;
- assert_eq!(RSA_SIG_LEN, signer.len()?);
- Ok(())
- }
- }
- }
|