From 4ad2f0a0dc3abb4cb10a6b82ca6a1f3a829eb1fb Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 5 Apr 2020 02:53:59 -0400 Subject: rename --- src/cipherstring.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/cipherstring.rs (limited to 'src/cipherstring.rs') diff --git a/src/cipherstring.rs b/src/cipherstring.rs new file mode 100644 index 0000000..75edec4 --- /dev/null +++ b/src/cipherstring.rs @@ -0,0 +1,95 @@ +use crate::prelude::*; + +use block_modes::BlockMode as _; +use hmac::Mac as _; + +pub struct CipherString { + ty: u8, + iv: Vec, + ciphertext: Vec, + mac: Option>, +} + +impl CipherString { + pub fn new(s: &str) -> Result { + let parts: Vec<&str> = s.split('.').collect(); + if parts.len() != 2 { + return Err(Error::InvalidCipherString); + } + + let ty = parts[0].as_bytes(); + if ty.len() != 1 { + return Err(Error::InvalidCipherString); + } + + let ty = ty[0] - b'0'; + let contents = parts[1]; + + let parts: Vec<&str> = contents.split('|').collect(); + if parts.len() < 2 || parts.len() > 3 { + return Err(Error::InvalidCipherString); + } + + let iv = + base64::decode(parts[0]).context(crate::error::InvalidBase64)?; + let ciphertext = + base64::decode(parts[1]).context(crate::error::InvalidBase64)?; + let mac = if parts.len() > 2 { + Some( + base64::decode(parts[2]) + .context(crate::error::InvalidBase64)?, + ) + } else { + None + }; + + Ok(Self { + ty, + iv, + ciphertext, + mac, + }) + } + + pub fn decrypt(&self, enc_key: &[u8], mac_key: &[u8]) -> Result> { + if self.ty != 2 { + unimplemented!() + } + + if let Some(mac) = &self.mac { + let mut digest = hmac::Hmac::::new_varkey(mac_key) + .map_err(|_| Error::InvalidMacKey)?; + digest.input(&self.iv); + digest.input(&self.ciphertext); + let calculated_mac = digest.result().code(); + + if !macs_equal(mac, &calculated_mac, mac_key)? { + return Err(Error::InvalidMac); + } + } + + let cipher = block_modes::Cbc::< + aes::Aes256, + block_modes::block_padding::Pkcs7, + >::new_var(enc_key, &self.iv) + .context(crate::error::CreateBlockMode)?; + + cipher + .decrypt_vec(&self.ciphertext) + .context(crate::error::Decrypt) + } +} + +fn macs_equal(mac1: &[u8], mac2: &[u8], mac_key: &[u8]) -> Result { + let mut digest = hmac::Hmac::::new_varkey(mac_key) + .map_err(|_| Error::InvalidMacKey)?; + digest.input(mac1); + let hmac1 = digest.result().code(); + + let mut digest = hmac::Hmac::::new_varkey(mac_key) + .map_err(|_| Error::InvalidMacKey)?; + digest.input(mac2); + let hmac2 = digest.result().code(); + + Ok(hmac1 == hmac2) +} -- cgit v1.2.3-54-g00ecf