feat: pedning add chacha20-poly1305

This commit is contained in:
2023-10-22 17:08:39 +08:00
parent b3359d205b
commit 83464dfb28
5 changed files with 183 additions and 6 deletions

29
Cargo.lock generated
View File

@@ -264,6 +264,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chacha20-poly1305-stream"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3de0436856104bf1d2e4d5ea07661cb1a16268157f2a130c48253237ef09a457"
dependencies = [
"constant_time_eq",
"hex",
]
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.31" version = "0.4.31"
@@ -353,6 +363,12 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
version = "0.8.4" version = "0.8.4"
@@ -361,9 +377,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.9" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@@ -1653,18 +1669,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.49" version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.49" version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -1717,6 +1733,7 @@ version = "0.4.4"
dependencies = [ dependencies = [
"aes-gcm-stream", "aes-gcm-stream",
"base64", "base64",
"chacha20-poly1305-stream",
"chrono", "chrono",
"clap", "clap",
"flate2", "flate2",

View File

@@ -11,6 +11,7 @@ repository = "https://git.hatter.ink/hatter/tiny-encrypt-rs"
[dependencies] [dependencies]
aes-gcm-stream = "0.2" aes-gcm-stream = "0.2"
base64 = "0.21" base64 = "0.21"
chacha20-poly1305-stream = "0.1.0"
chrono = "0.4" chrono = "0.4"
clap = { version = "4.4", features = ["derive"] } clap = { version = "4.4", features = ["derive"] }
flate2 = "1.0" flate2 = "1.0"

View File

@@ -8,6 +8,7 @@ pub const TINY_ENC_FILE_EXT: &str = ".tinyenc";
pub const TINY_ENC_CONFIG_FILE: &str = "~/.tinyencrypt/config-rs.json"; pub const TINY_ENC_CONFIG_FILE: &str = "~/.tinyencrypt/config-rs.json";
pub const TINY_ENC_AES_GCM: &str = "AES/GCM"; pub const TINY_ENC_AES_GCM: &str = "AES/GCM";
pub const TINY_ENC_CHACHA20_POLY1305: &str = "CHACHA20/POLY1305";
// Tiny enc magic tag // Tiny enc magic tag
pub const TINY_ENC_MAGIC_TAG: u16 = 0x01; pub const TINY_ENC_MAGIC_TAG: u16 = 0x01;

157
src/crypto_cryptor.rs Normal file
View File

@@ -0,0 +1,157 @@
use aes_gcm_stream::{Aes256GcmStreamDecryptor, Aes256GcmStreamEncryptor};
use chacha20_poly1305_stream::{ChaCha20Poly1305StreamDecryptor, ChaCha20Poly1305StreamEncryptor};
use rust_util::{opt_result, simple_error, XResult};
use zeroize::Zeroize;
use crate::consts;
#[derive(Debug, Copy, Clone)]
pub enum Cryptor {
Aes256Gcm,
ChaCha20Poly1305,
}
impl Cryptor {
pub fn from(algorithm: &str) -> XResult<Self> {
match algorithm {
"aes256-gcm" | consts::TINY_ENC_AES_GCM => Ok(Cryptor::Aes256Gcm),
"chacha20-poly1305" | consts::TINY_ENC_CHACHA20_POLY1305 => Ok(Cryptor::ChaCha20Poly1305),
_ => simple_error!("Unknown altorighm: {}",algorithm),
}
}
pub fn encryptor(self, key: &[u8], nonce: &[u8]) -> XResult<Box<dyn Encryptor>> {
get_encryptor(self, key, nonce)
}
pub fn decryptor(self, key: &[u8], nonce: &[u8]) -> XResult<Box<dyn Decryptor>> {
get_decryptor(self, key, nonce)
}
}
pub trait Encryptor {
fn update(&mut self, message: &[u8]) -> Vec<u8>;
fn finalize(&mut self) -> (Vec<u8>, Vec<u8>);
fn encrypt(&mut self, message: &[u8]) -> Vec<u8> {
let mut cipher_text = self.update(message);
let (last_block, tag) = self.finalize();
cipher_text.extend_from_slice(&last_block);
cipher_text.extend_from_slice(&tag);
cipher_text
}
}
pub trait Decryptor {
fn update(&mut self, message: &[u8]) -> Vec<u8>;
fn finalize(&mut self) -> XResult<Vec<u8>>;
fn decrypt(&mut self, message: &[u8]) -> XResult<Vec<u8>> {
let mut plaintext = self.update(message);
let last_block = self.finalize()?;
plaintext.extend_from_slice(&last_block);
Ok(plaintext)
}
}
fn get_encryptor(crypto: Cryptor, key: &[u8], nonce: &[u8]) -> XResult<Box<dyn Encryptor>> {
match crypto {
Cryptor::Aes256Gcm => {
let mut key: [u8; 32] = opt_result!(key.try_into(), "Bad AES 256 key: {}");
let aes256_gcm_stream_encryptor = Aes256GcmStreamEncryptor::new(key, nonce);
key.zeroize();
Ok(Box::new(Aes256GcmEncryptor {
aes256_gcm_stream_encryptor,
}))
}
Cryptor::ChaCha20Poly1305 => Ok(Box::new(ChaCha20Poly1305Encryptor {
chacha20_poly1305_stream_encryptor: ChaCha20Poly1305StreamEncryptor::new(key, nonce)?,
}))
}
}
fn get_decryptor(crypto: Cryptor, key: &[u8], nonce: &[u8]) -> XResult<Box<dyn Decryptor>> {
match crypto {
Cryptor::Aes256Gcm => {
let mut key: [u8; 32] = opt_result!(key.try_into(), "Bad AES 256 key: {}");
let aes256_gcm_stream_decryptor = Aes256GcmStreamDecryptor::new(key, nonce);
key.zeroize();
Ok(Box::new(Aes256GcmDecryptor {
aes256_gcm_stream_decryptor,
}))
}
Cryptor::ChaCha20Poly1305 => Ok(Box::new(ChaCha20Poly1305Decryptor {
chacha20_poly1305_stream_decryptor: ChaCha20Poly1305StreamDecryptor::new(key, nonce)?,
}))
}
}
pub struct Aes256GcmEncryptor {
aes256_gcm_stream_encryptor: Aes256GcmStreamEncryptor,
}
impl Encryptor for Aes256GcmEncryptor {
fn update(&mut self, message: &[u8]) -> Vec<u8> {
self.aes256_gcm_stream_encryptor.update(message)
}
fn finalize(&mut self) -> (Vec<u8>, Vec<u8>) {
self.aes256_gcm_stream_encryptor.finalize()
}
}
pub struct ChaCha20Poly1305Encryptor {
chacha20_poly1305_stream_encryptor: ChaCha20Poly1305StreamEncryptor,
}
impl Encryptor for ChaCha20Poly1305Encryptor {
fn update(&mut self, message: &[u8]) -> Vec<u8> {
self.chacha20_poly1305_stream_encryptor.update(message)
}
fn finalize(&mut self) -> (Vec<u8>, Vec<u8>) {
self.chacha20_poly1305_stream_encryptor.finalize()
}
}
pub struct Aes256GcmDecryptor {
aes256_gcm_stream_decryptor: Aes256GcmStreamDecryptor,
}
impl Decryptor for Aes256GcmDecryptor {
fn update(&mut self, message: &[u8]) -> Vec<u8> {
self.aes256_gcm_stream_decryptor.update(message)
}
fn finalize(&mut self) -> XResult<Vec<u8>> {
Ok(self.aes256_gcm_stream_decryptor.finalize()?)
}
}
pub struct ChaCha20Poly1305Decryptor {
chacha20_poly1305_stream_decryptor: ChaCha20Poly1305StreamDecryptor,
}
impl Decryptor for ChaCha20Poly1305Decryptor {
fn update(&mut self, message: &[u8]) -> Vec<u8> {
self.chacha20_poly1305_stream_decryptor.update(message)
}
fn finalize(&mut self) -> XResult<Vec<u8>> {
Ok(self.chacha20_poly1305_stream_decryptor.finalize()?)
}
}
#[test]
fn test_cryptor() {
let key = [0u8; 32];
let nonce = [0u8; 12];
let ciphertext = Cryptor::Aes256Gcm.encryptor(&key, &nonce).unwrap()
.encrypt(b"hello world");
let plaintext = Cryptor::Aes256Gcm.decryptor(&key, &nonce).unwrap()
.decrypt(&ciphertext).unwrap();
assert_eq!(b"hello world", plaintext.as_slice());
}

View File

@@ -23,6 +23,7 @@ mod config;
mod spec; mod spec;
mod crypto_aes; mod crypto_aes;
mod crypto_rsa; mod crypto_rsa;
mod crypto_cryptor;
mod wrap_key; mod wrap_key;
mod util_envelop; mod util_envelop;
mod util_file; mod util_file;