diff options
| author | benj <benj@rse8.com> | 2023-04-24 13:24:45 -0700 |
|---|---|---|
| committer | benj <benj@rse8.com> | 2023-04-24 13:24:45 -0700 |
| commit | eb92f823c31a5e702af7005231f0d6915aad3342 (patch) | |
| tree | bb624786a47accb2dfcfe95d20c00c9624c28a9c /crates/secd/src/util/crypter.rs | |
| parent | 176aae037400b43cb3971cd968afe59c73b3097a (diff) | |
| download | secdiam-eb92f823c31a5e702af7005231f0d6915aad3342.tar secdiam-eb92f823c31a5e702af7005231f0d6915aad3342.tar.gz secdiam-eb92f823c31a5e702af7005231f0d6915aad3342.tar.bz2 secdiam-eb92f823c31a5e702af7005231f0d6915aad3342.tar.lz secdiam-eb92f823c31a5e702af7005231f0d6915aad3342.tar.xz secdiam-eb92f823c31a5e702af7005231f0d6915aad3342.tar.zst secdiam-eb92f823c31a5e702af7005231f0d6915aad3342.zip | |
email templates, sendgrid, creds, and some experimental things
Started playing with namespace configs and integrating with zanzibar impls. Still lot's of experimenting and dead code going on.
Diffstat (limited to '')
| -rw-r--r-- | crates/secd/src/util/crypter.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/crates/secd/src/util/crypter.rs b/crates/secd/src/util/crypter.rs new file mode 100644 index 0000000..1717377 --- /dev/null +++ b/crates/secd/src/util/crypter.rs @@ -0,0 +1,87 @@ +use aes_gcm::{ + aead::{Aead, KeyInit, OsRng}, + Aes256Gcm, Nonce, +}; +use argon2::{ + password_hash::{self, SaltString}, + Argon2, PasswordHasher, +}; +use derive_more::Display; +use rand::Rng; +use sha2::{Digest, Sha256}; +use thiserror::Error; + +#[derive(Debug, Display, Error)] +pub enum CrypterError { + EncryptError(String), + DecryptError(String), + DecodeError(String), + HashError(String), +} + +pub struct Crypter { + pub key: Vec<u8>, +} + +impl Crypter { + pub fn new(key: &[u8]) -> Self { + Self { key: key.to_vec() } + } + + pub fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>, CrypterError> { + let mut hasher = Sha256::new(); + hasher.update(&self.key); + + let cipher = Aes256Gcm::new(&hasher.finalize()); + + let rbs = rand::thread_rng().gen::<[u8; 12]>(); + let iv = Nonce::from_slice(&rbs); + let crypt = cipher + .encrypt(&iv, data) + .map_err(|e| CrypterError::EncryptError(e.to_string()))?; + + let mut msg = iv.to_vec(); + msg.extend_from_slice(&crypt); + Ok(msg) + } + + pub fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, CrypterError> { + let mut hasher = Sha256::new(); + hasher.update(&self.key); + + let cipher = Aes256Gcm::new(&hasher.finalize()); + + let iv = Nonce::from_slice(&data[0..=11]); + let data = &data[12..]; + Ok(cipher + .decrypt(&iv, data) + .map_err(|e| CrypterError::DecryptError(e.to_string()))?) + } + + pub fn hash(&self, data: &[u8]) -> Result<String, CrypterError> { + let salt = SaltString::generate(&mut OsRng); + let hasher = Argon2::default(); + Ok(hasher + .hash_password(data, &salt) + .map_err(|e| CrypterError::HashError(e.to_string()))? + .to_string()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn encrypt_data_test() { + let crypter = Crypter { + key: "testkey".to_string().into_bytes(), + }; + + let plaintext = "This is a secret."; + let enc = crypter.encrypt(&plaintext.as_bytes()).unwrap(); + + let res = crypter.decrypt(&enc).unwrap(); + assert_eq!(plaintext, std::str::from_utf8(&res).unwrap()); + } +} |
