feat: pedning add chacha20-poly1305
This commit is contained in:
29
Cargo.lock
generated
29
Cargo.lock
generated
@@ -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",
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
157
src/crypto_cryptor.rs
Normal 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());
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user