2023-07-03 16:23:56 +02:00
use aes ::cipher ::InvalidLength ;
2023-07-02 16:44:18 +02:00
use rand ::Rng ;
2023-07-03 16:23:56 +02:00
2021-08-19 22:54:18 +02:00
use serde ::{ Deserialize , Serialize } ;
use thiserror ::Error ;
2023-07-03 16:23:56 +02:00
mod argon2id_aes ;
2023-07-02 16:44:18 +02:00
#[ cfg(feature = " keyring " ) ]
mod keyring ;
2023-07-03 16:23:56 +02:00
mod legacy ;
pub use argon2id_aes ::* ;
pub use legacy ::* ;
2023-07-02 16:44:18 +02:00
#[ cfg(feature = " keyring " ) ]
pub use crate ::encryption ::keyring ::* ;
2021-08-19 22:54:18 +02:00
#[ derive(Debug, Clone, Serialize, Deserialize) ]
2023-07-03 16:23:56 +02:00
#[ serde(tag = " scheme " ) ]
2021-08-19 22:54:18 +02:00
pub enum EncryptionScheme {
2023-07-03 16:23:56 +02:00
Argon2idAes256 ( Argon2idAes256 ) ,
LegacySdaCompatible ( LegacySdaCompatible ) ,
2021-08-19 22:54:18 +02:00
}
pub trait EntryEncryptor {
2023-07-03 16:23:56 +02:00
fn generate ( ) -> Self ;
2021-08-19 22:54:18 +02:00
fn encrypt (
2023-07-03 16:23:56 +02:00
& self ,
2023-06-23 19:36:23 +02:00
passkey : & str ,
2021-08-19 22:54:18 +02:00
plaintext : Vec < u8 > ,
) -> anyhow ::Result < Vec < u8 > , EntryEncryptionError > ;
fn decrypt (
2023-07-03 16:23:56 +02:00
& self ,
2023-06-23 19:36:23 +02:00
passkey : & str ,
2021-08-19 22:54:18 +02:00
ciphertext : Vec < u8 > ,
) -> anyhow ::Result < Vec < u8 > , EntryEncryptionError > ;
}
2023-07-03 16:23:56 +02:00
impl EntryEncryptor for EncryptionScheme {
fn generate ( ) -> Self {
EncryptionScheme ::Argon2idAes256 ( Argon2idAes256 ::generate ( ) )
2021-08-19 23:15:10 +02:00
}
2021-08-19 22:54:18 +02:00
fn encrypt (
2023-07-03 16:23:56 +02:00
& self ,
2023-06-23 19:36:23 +02:00
passkey : & str ,
2021-08-19 22:54:18 +02:00
plaintext : Vec < u8 > ,
) -> anyhow ::Result < Vec < u8 > , EntryEncryptionError > {
2023-07-03 16:23:56 +02:00
match self {
EncryptionScheme ::Argon2idAes256 ( scheme ) = > scheme . encrypt ( passkey , plaintext ) ,
EncryptionScheme ::LegacySdaCompatible ( scheme ) = > scheme . encrypt ( passkey , plaintext ) ,
}
2021-08-19 22:54:18 +02:00
}
fn decrypt (
2023-07-03 16:23:56 +02:00
& self ,
2023-06-23 19:36:23 +02:00
passkey : & str ,
2021-08-19 22:54:18 +02:00
ciphertext : Vec < u8 > ,
) -> anyhow ::Result < Vec < u8 > , EntryEncryptionError > {
2023-07-03 16:23:56 +02:00
match self {
EncryptionScheme ::Argon2idAes256 ( scheme ) = > scheme . decrypt ( passkey , ciphertext ) ,
EncryptionScheme ::LegacySdaCompatible ( scheme ) = > scheme . decrypt ( passkey , ciphertext ) ,
}
2021-08-19 22:54:18 +02:00
}
}
#[ derive(Debug, Error) ]
pub enum EntryEncryptionError {
2023-06-27 01:02:48 +02:00
#[ error( " Invalid ciphertext length. The ciphertext must be a multiple of 16 bytes. " ) ]
InvalidCipherTextLength ,
2021-08-19 22:54:18 +02:00
#[ error(transparent) ]
Unknown ( #[ from ] anyhow ::Error ) ,
}
/// For some reason, these errors do not get converted to `ManifestAccountLoadError`s, even though they get converted into `anyhow::Error` just fine. I am too lazy to figure out why right now.
2023-06-27 01:02:48 +02:00
impl From < InvalidLength > for EntryEncryptionError {
fn from ( error : InvalidLength ) -> Self {
2023-06-22 22:20:15 +02:00
Self ::Unknown ( anyhow ::Error ::from ( error ) )
2021-08-19 22:54:18 +02:00
}
}
2023-06-27 01:02:48 +02:00
impl From < inout ::NotEqualError > for EntryEncryptionError {
fn from ( error : inout ::NotEqualError ) -> Self {
2023-06-22 22:20:15 +02:00
Self ::Unknown ( anyhow ::Error ::from ( error ) )
2021-08-19 22:54:18 +02:00
}
}
2023-06-27 01:02:48 +02:00
impl From < inout ::PadError > for EntryEncryptionError {
fn from ( error : inout ::PadError ) -> Self {
Self ::Unknown ( anyhow ::Error ::from ( error ) )
2021-08-19 22:54:18 +02:00
}
}
2023-06-27 01:02:48 +02:00
impl From < inout ::block_padding ::UnpadError > for EntryEncryptionError {
fn from ( error : inout ::block_padding ::UnpadError ) -> Self {
Self ::Unknown ( anyhow ::Error ::from ( error ) )
2021-08-19 22:54:18 +02:00
}
}
2023-06-27 01:02:48 +02:00
2021-08-19 22:54:18 +02:00
impl From < base64 ::DecodeError > for EntryEncryptionError {
fn from ( error : base64 ::DecodeError ) -> Self {
2023-06-22 22:20:15 +02:00
Self ::Unknown ( anyhow ::Error ::from ( error ) )
2021-08-19 22:54:18 +02:00
}
}
impl From < std ::io ::Error > for EntryEncryptionError {
fn from ( error : std ::io ::Error ) -> Self {
2023-06-22 22:20:15 +02:00
Self ::Unknown ( anyhow ::Error ::from ( error ) )
2021-08-19 22:54:18 +02:00
}
}
2023-07-02 16:44:18 +02:00
pub fn generate_keyring_id ( ) -> String {
let rng = rand ::thread_rng ( ) ;
rng . sample_iter ( rand ::distributions ::Alphanumeric )
. take ( 32 )
. map ( char ::from )
. collect ( )
}