|
@@ -18,7 +18,7 @@ use strum_macros::{EnumString, EnumDiscriminants, Display};
|
|
|
|
|
|
/// Data that may or may not be encrypted.
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
|
-pub enum Cryptotext<T: Serialize> {
|
|
|
+pub(crate) enum Cryptotext<T: Serialize> {
|
|
|
/// The inner value of `T` is plaintext.
|
|
|
Plain(T),
|
|
|
/// The inner value is ciphertext.
|
|
@@ -27,7 +27,7 @@ pub enum Cryptotext<T: Serialize> {
|
|
|
|
|
|
/// Errors that can occur during cryptographic operations.
|
|
|
#[derive(Debug)]
|
|
|
-pub enum Error {
|
|
|
+pub(crate) enum Error {
|
|
|
NoReadCap,
|
|
|
NoKeyAvailable,
|
|
|
MissingPrivateKey,
|
|
@@ -65,13 +65,13 @@ impl From<serde_block_tree::Error> for Error {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub type Result<T> = std::result::Result<T, Error>;
|
|
|
+pub(crate) type Result<T> = std::result::Result<T, Error>;
|
|
|
|
|
|
/// A cryptographic hash.
|
|
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable, Clone, EnumDiscriminants)]
|
|
|
#[strum_discriminants(derive(EnumString, Display))]
|
|
|
#[strum_discriminants(name(HashKind))]
|
|
|
-pub enum Hash {
|
|
|
+pub(crate) enum Hash {
|
|
|
Sha2_256([u8; 32]),
|
|
|
#[serde(with = "BigArray")]
|
|
|
Sha2_512([u8; 64]),
|
|
@@ -149,12 +149,12 @@ const RSA_SIG_LEN: usize = 512;
|
|
|
|
|
|
/// A cryptographic signature.
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
|
-pub enum Signature {
|
|
|
+pub(crate) enum Signature {
|
|
|
#[serde(with = "BigArray")]
|
|
|
Rsa([u8; RSA_SIG_LEN]),
|
|
|
}
|
|
|
|
|
|
-pub enum SignatureId {
|
|
|
+pub(crate) enum SignatureId {
|
|
|
Rsa
|
|
|
}
|
|
|
|
|
@@ -185,7 +185,7 @@ impl Default for Signature {
|
|
|
}
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
|
-pub enum RsaPadding {
|
|
|
+pub(crate) enum RsaPadding {
|
|
|
None,
|
|
|
Pkcs1,
|
|
|
Pkcs1Oaep,
|
|
@@ -213,7 +213,7 @@ impl From<RsaPadding> for OpensslPadding {
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
|
|
|
#[strum_discriminants(name(SymKeyKind))]
|
|
|
-pub enum SymKey {
|
|
|
+pub(crate) enum SymKey {
|
|
|
/// A key for the AES 256 cipher in Cipher Block Chaining mode. Note that this includes the
|
|
|
/// initialization vector, so that a value of this variant contains all the information needed
|
|
|
/// to fully initialize a cipher context.
|
|
@@ -245,7 +245,7 @@ fn rand_array<const LEN: usize>() -> Result<[u8; LEN]> {
|
|
|
}
|
|
|
|
|
|
impl SymKey {
|
|
|
- pub fn generate(kind: SymKeyKind) -> Result<SymKey> {
|
|
|
+ pub(crate) fn generate(kind: SymKeyKind) -> Result<SymKey> {
|
|
|
match kind {
|
|
|
SymKeyKind::Aes256Cbc => {
|
|
|
Ok(SymKey::Aes256Cbc { key: rand_array()?, iv: rand_array()? })
|
|
@@ -258,14 +258,14 @@ impl SymKey {
|
|
|
}
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
|
-pub struct Public;
|
|
|
+pub(crate) struct Public;
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
|
-pub struct Private;
|
|
|
+pub(crate) struct Private;
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants)]
|
|
|
#[strum_discriminants(name(AsymKeyKind))]
|
|
|
-pub enum AsymKey<T> {
|
|
|
+pub(crate) enum AsymKey<T> {
|
|
|
Rsa {
|
|
|
der: Vec<u8>,
|
|
|
padding: RsaPadding,
|
|
@@ -274,7 +274,7 @@ pub enum AsymKey<T> {
|
|
|
}
|
|
|
|
|
|
impl<T> AsymKey<T> {
|
|
|
- pub fn as_slice(&self) -> &[u8] {
|
|
|
+ pub(crate) fn as_slice(&self) -> &[u8] {
|
|
|
match self {
|
|
|
AsymKey::Rsa { der, .. } => der.as_slice()
|
|
|
}
|
|
@@ -303,13 +303,13 @@ impl<T> Owned for AsymKey<T> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub struct KeyPair {
|
|
|
- pub public: AsymKey<Public>,
|
|
|
- pub private: AsymKey<Private>,
|
|
|
+pub(crate) struct KeyPair {
|
|
|
+ pub(crate) public: AsymKey<Public>,
|
|
|
+ pub(crate) private: AsymKey<Private>,
|
|
|
}
|
|
|
|
|
|
impl KeyPair {
|
|
|
- pub fn generate(kind: AsymKeyKind) -> Result<KeyPair> {
|
|
|
+ pub(crate) fn generate(kind: AsymKeyKind) -> Result<KeyPair> {
|
|
|
match kind {
|
|
|
AsymKeyKind::Rsa => {
|
|
|
let key = PKey::from_rsa(Rsa::generate(4096)?)?;
|
|
@@ -528,11 +528,10 @@ impl TryFrom<&AsymKey<Public>> for VerifyAlgo {
|
|
|
}
|
|
|
|
|
|
pub(crate) fn encrypt_block(
|
|
|
- versioned_block: VersionedBlock, principal: &Principal, key: &KeyPair
|
|
|
-) -> Result<VersionedBlock> {
|
|
|
- let VersionedBlock::V0(mut block) = versioned_block;
|
|
|
+ mut block: Block, principal: &Principal, key: &KeyPair
|
|
|
+) -> Result<Block> {
|
|
|
let body = match block.body {
|
|
|
- Cryptotext::Cipher(_) => return Ok(VersionedBlock::V0(block)),
|
|
|
+ Cryptotext::Cipher(_) => return Ok(block),
|
|
|
Cryptotext::Plain(body) => body
|
|
|
};
|
|
|
let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
|
|
@@ -541,15 +540,14 @@ pub(crate) fn encrypt_block(
|
|
|
let new_body = encrypt_slice(&body, &block_key)?;
|
|
|
block.body = Cryptotext::Cipher(new_body);
|
|
|
block.readcaps.insert(principal_owned, encrypt(&block_key, &key.public)?);
|
|
|
- Ok(VersionedBlock::V0(block))
|
|
|
+ Ok(block)
|
|
|
}
|
|
|
|
|
|
pub(crate) fn decrypt_block(
|
|
|
- versioned_block: VersionedBlock, principal: &Principal, key: &AsymKey<Private>
|
|
|
-) -> Result<VersionedBlock> {
|
|
|
- let VersionedBlock::V0(mut block) = versioned_block;
|
|
|
+ mut block: Block, principal: &Principal, key: &AsymKey<Private>
|
|
|
+) -> Result<Block> {
|
|
|
let body = match block.body {
|
|
|
- Cryptotext::Plain(_) => return Ok(VersionedBlock::V0(block)),
|
|
|
+ Cryptotext::Plain(_) => return Ok(block),
|
|
|
Cryptotext::Cipher(body) => body
|
|
|
};
|
|
|
let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
|
|
@@ -558,7 +556,7 @@ pub(crate) fn decrypt_block(
|
|
|
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))
|
|
|
+ Ok(block)
|
|
|
}
|
|
|
|
|
|
fn encrypt<'a, K: TryInto<EncryptionAlgo<'a>, Error = Error>, T: Serialize>(
|
|
@@ -622,9 +620,8 @@ fn get_body(block: &Block) -> Result<&[u8]> {
|
|
|
}
|
|
|
|
|
|
pub(crate) fn sign_block(
|
|
|
- versioned_block: &mut VersionedBlock, writecap: Writecap, priv_key: AsymKey<Private>
|
|
|
+ block: &mut Block, writecap: Writecap, priv_key: AsymKey<Private>
|
|
|
) -> Result<()> {
|
|
|
- let VersionedBlock::V0(block) = versioned_block;
|
|
|
block.writecap = writecap;
|
|
|
let body = get_body(block)?;
|
|
|
let sig_header = SigHeader::from(&*block);
|
|
@@ -635,8 +632,7 @@ pub(crate) fn sign_block(
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
-pub(crate) fn verify_block(versioned_block: &VersionedBlock) -> Result<bool> {
|
|
|
- let VersionedBlock::V0(block) = versioned_block;
|
|
|
+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)?;
|
|
@@ -750,36 +746,34 @@ mod tests {
|
|
|
use test_helpers::*;
|
|
|
|
|
|
fn encrypt_decrypt_block_test_case(
|
|
|
- mut actual: VersionedBlock, principal: &Principal, key: &KeyPair
|
|
|
+ mut actual: Block, principal: &Principal, key: &KeyPair
|
|
|
) -> Result<()> {
|
|
|
let expected = actual.clone();
|
|
|
actual = encrypt_block(actual, principal, key)?;
|
|
|
+ let encrypted = match &actual.body {
|
|
|
+ Cryptotext::Cipher(_) => true,
|
|
|
+ Cryptotext::Plain(_) => false
|
|
|
+ };
|
|
|
+ assert!(encrypted);
|
|
|
actual = decrypt_block(actual, principal, &key.private)?;
|
|
|
assert_eq!(expected, actual);
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
- fn make_versioned_block(principal: Principal, block_key: SymKey) -> 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 = SymKey::Aes256Cbc { key: BLOCK_KEY, iv: BLOCK_IV };
|
|
|
- let block = make_versioned_block(principal.clone(), block_key)?;
|
|
|
+ let readcap = make_readcap();
|
|
|
+ let principal = readcap.issued_to.clone();
|
|
|
+ let block = make_block_with(readcap)?;
|
|
|
let key = make_key_pair();
|
|
|
encrypt_decrypt_block_test_case(block, &principal, &key)
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
|
fn encrypt_decrypt_block_aes256ctr() -> Result<()> {
|
|
|
- let principal = make_principal();
|
|
|
- let block_key = SymKey::Aes256Ctr { key: BLOCK_KEY, iv: BLOCK_IV };
|
|
|
- let block = make_versioned_block(principal.clone(), block_key)?;
|
|
|
+ let readcap = make_readcap();
|
|
|
+ let principal = readcap.issued_to.clone();
|
|
|
+ let block = make_block_with(readcap)?;
|
|
|
let key = make_key_pair();
|
|
|
encrypt_decrypt_block_test_case(block, &principal, &key)
|
|
|
}
|
|
@@ -799,9 +793,9 @@ mod tests {
|
|
|
|
|
|
#[test]
|
|
|
fn sign_verify_block_rsa() -> Result<()> {
|
|
|
- let principal = make_principal();
|
|
|
- let block_key = SymKey::Aes256Ctr { key: BLOCK_KEY, iv: BLOCK_IV };
|
|
|
- let mut block = make_versioned_block(principal.clone(), block_key)?;
|
|
|
+ let readcap = make_readcap();
|
|
|
+ let principal = readcap.issued_to.clone();
|
|
|
+ let mut block = make_block_with(readcap)?;
|
|
|
let key = make_key_pair();
|
|
|
let writecap = Writecap {
|
|
|
issued_to: Principal(Hash::Sha2_256(PRINCIPAL)),
|