//! See the Wikipedia Artikel for [Authenticated
//! encryption](https://en.wikipedia.org/wiki/Authenticated_encryption)
//! for a short introduction.
-use failure::*;
-use openssl::pkcs5::pbkdf2_hmac;
+
+use std::io::Write;
+
+use anyhow::{bail, Error};
use openssl::hash::MessageDigest;
+use openssl::pkcs5::pbkdf2_hmac;
use openssl::symm::{decrypt_aead, Cipher, Crypter, Mode};
-use std::io::Write;
-use chrono::{Local, TimeZone, DateTime};
+use serde::{Deserialize, Serialize};
+
+use proxmox::api::api;
+
+#[api(default: "encrypt")]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
+#[serde(rename_all = "kebab-case")]
+/// Defines whether data is encrypted (using an AEAD cipher), only signed, or neither.
+pub enum CryptMode {
+ /// Don't encrypt.
+ None,
+ /// Encrypt.
+ Encrypt,
+ /// Only sign.
+ SignOnly,
+}
/// Encryption Configuration with secret key
///
id_pkey: openssl::pkey::PKey<openssl::pkey::Private>,
// The private key used by the cipher.
enc_key: [u8; 32],
-
}
impl CryptConfig {
Ok(Self { id_key, id_pkey, enc_key, cipher: Cipher::aes_256_gcm() })
}
+ /// Expose Cipher
+ pub fn cipher(&self) -> &Cipher {
+ &self.cipher
+ }
+
/// Compute a chunk digest using a secret name space.
///
/// Computes an SHA256 checksum over some secret data (derived
/// chunk digest values do not clash with values computed for
/// other sectret keys.
pub fn compute_digest(&self, data: &[u8]) -> [u8; 32] {
- // FIXME: use HMAC-SHA256 instead??
let mut hasher = openssl::sha::Sha256::new();
- hasher.update(&self.id_key);
hasher.update(data);
- let digest = hasher.finish();
- digest
+ hasher.update(&self.id_key); // at the end, to avoid length extensions attacks
+ hasher.finish()
}
pub fn data_signer(&self) -> openssl::sign::Signer {
pub fn generate_rsa_encoded_key(
&self,
rsa: openssl::rsa::Rsa<openssl::pkey::Public>,
- created: DateTime<Local>,
+ created: i64,
) -> Result<Vec<u8>, Error> {
- let modified = Local.timestamp(Local::now().timestamp(), 0);
+ let modified = proxmox::tools::time::epoch_i64();
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();