use openssl::hash::MessageDigest;
use openssl::symm::{decrypt_aead, Cipher, Crypter, Mode};
use std::io::Write;
+use chrono::{Local, TimeZone, DateTime};
/// Encryption Configuration with secret key
///
Ok((iv, tag))
}
- /// Compress and encrypt data using a random 16 byte IV.
- ///
- /// Return the encrypted data, including IV and MAC (MAGIC || IV || MAC || ENC_DATA).
- /// If compression does not help, we return the uncompresssed, encrypted data.
- pub fn encode_chunk(
+ /// Decompress and decrypt date, verify MAC.
+ pub fn decode_compressed_chunk(
&self,
- // The data you want to encode
data: &[u8],
- // Whether try to compress data before encryption
- compress: bool,
- // Magic number used for uncompressed results
- uncomp_magic: &[u8; 8],
- // Magic number used for compressed results
- comp_magic: &[u8; 8],
+ iv: &[u8; 16],
+ tag: &[u8; 16],
) -> Result<Vec<u8>, Error> {
- let iv = proxmox::sys::linux::random_data(16)?;
- let mut c = Crypter::new(self.cipher, Mode::Encrypt, &self.enc_key, Some(&iv))?;
- c.aad_update(b"")?; //??
-
- if compress {
- let compr_data = zstd::block::compress(data, 1)?;
- // Note: We only use compression if result is shorter
- if compr_data.len() < data.len() {
- let mut enc = vec![0; compr_data.len()+44+self.cipher.block_size()];
-
- enc[0..8].copy_from_slice(comp_magic);
- enc[8..12].copy_from_slice(&[0u8; 4]);
- enc[12..28].copy_from_slice(&iv);
-
- let count = c.update(&compr_data, &mut enc[44..])?;
- let rest = c.finalize(&mut enc[(44+count)..])?;
- enc.truncate(44 + count + rest);
-
- c.get_tag(&mut enc[28..44])?;
-
- return Ok(enc)
- }
- }
-
- let mut enc = vec![0; data.len()+44+self.cipher.block_size()];
-
- enc[0..8].copy_from_slice(uncomp_magic);
- enc[8..12].copy_from_slice(&[0u8; 4]);
- enc[12..28].copy_from_slice(&iv);
-
- let count = c.update(data, &mut enc[44..])?;
- let rest = c.finalize(&mut enc[(44+count)..])?;
- enc.truncate(44 + count + rest);
-
- c.get_tag(&mut enc[28..44])?;
-
- Ok(enc)
- }
-
- /// Decompress and decrypt chunk, verify MAC.
- ///
- /// Binrary ``data`` is expected to be in format returned by encode_chunk. The magic number
- /// is not used here.
- pub fn decode_compressed_chunk(&self, data: &[u8]) -> Result<Vec<u8>, Error> {
-
- if data.len() < 44 {
- bail!("Invalid chunk len (<44)");
- }
-
- // let magic = &data[0..8];
- // let crc = &data[8..12];
- let iv = &data[12..28];
- let mac = &data[28..44];
-
let dec = Vec::with_capacity(1024*1024);
let mut decompressor = zstd::stream::write::Decoder::new(dec)?;
let mut decr_buf = [0u8; BUFFER_SIZE];
let max_decoder_input = BUFFER_SIZE - self.cipher.block_size();
- let mut start = 44;
+ let mut start = 0;
loop {
let mut end = start + max_decoder_input;
if end > data.len() { end = data.len(); }
}
}
- c.set_tag(mac)?;
+ c.set_tag(tag)?;
let rest = c.finalize(&mut decr_buf)?;
if rest > 0 { decompressor.write_all(&decr_buf[..rest])?; }
Ok(decompressor.into_inner())
}
- /// Decrypt chunk, verify MAC.
- ///
- /// Binrary ``data`` is expected to be in format returned by encode_chunk. The magic number
- /// is not used here.
- pub fn decode_uncompressed_chunk(&self, data: &[u8]) -> Result<Vec<u8>, Error> {
-
- if data.len() < 44 {
- bail!("Invalid chunk len (<44)");
- }
-
- // let magic = &data[0..8];
- // let crc = &data[8..12];
- let iv = &data[12..28];
- let mac = &data[28..44];
+ /// Decrypt data, verify tag.
+ pub fn decode_uncompressed_chunk(
+ &self,
+ data: &[u8],
+ iv: &[u8; 16],
+ tag: &[u8; 16],
+ ) -> Result<Vec<u8>, Error> {
let decr_data = decrypt_aead(
self.cipher,
&self.enc_key,
Some(iv),
b"", //??
- &data[44..],
- mac,
+ data,
+ tag,
)?;
Ok(decr_data)
}
+
+ pub fn generate_rsa_encoded_key(
+ &self,
+ rsa: openssl::rsa::Rsa<openssl::pkey::Public>,
+ created: DateTime<Local>,
+ ) -> Result<Vec<u8>, Error> {
+
+ let modified = Local.timestamp(Local::now().timestamp(), 0);
+ let key_config = super::KeyConfig { kdf: None, created, modified, data: self.enc_key.to_vec() };
+ let data = serde_json::to_string(&key_config)?.as_bytes().to_vec();
+
+ let mut buffer = vec![0u8; rsa.size() as usize];
+ let len = rsa.public_encrypt(&data, &mut buffer, openssl::rsa::Padding::PKCS1)?;
+ if len != buffer.len() {
+ bail!("got unexpected length from rsa.public_encrypt().");
+ }
+ Ok(buffer)
+ }
}