Crate encrypted_message
source ·Expand description
Safely encrypt & store serializable data using AES-256-GCM.
§Key configuration
First, you need to create a key configuration that implements the KeyConfig trait.
If your key configuration implements the Default trait, you can use the shorthand methods
of the EncryptedMessage struct.
The first key provided is considered the primary key, & is always used to encrypt new payloads. The following keys are used in the order provided when the primary key can’t decrypt a payload. This allows you to rotate keys.
Two key decoders are provided, HexKeyDecoder
& Base64KeyDecoder,
to help you store your key(s) as strings.
use encrypted_message::{
key_config::Secret,
utilities::key_decoder::HexKeyDecoder,
};
#[derive(Debug, Default)]
struct KeyConfig;
impl encrypted_message::KeyConfig for KeyConfig {
fn keys(&self) -> Vec<Secret<[u8; 32]>> {
// Load the keys from an environment variable, & wrap them in a `Secret`.
let keys = std::env::var("ENCRYPTION_KEYS").unwrap()
.split(", ")
.map(|key| Secret::new(key.to_string()))
.collect();
HexKeyDecoder::decode_keys(keys)
}
}You can generate secure 32-byte keys using the openssl command-line tool. Remember to use
HexKeyDecoder to decode the key.
openssl rand -hex 32
§Encryption strategies
Two encryption strategies are provided, Deterministic & Randomized.
Deterministicencryption will always produce the same encrypted message for the same payload, allowing you to query encrypted data.Randomizedencryption will always produce a different encrypted message for the same payload. More secure thanDeterministic, but impossible to query without decrypting all data.
It’s recommended to use different keys for each encryption strategy.
§Defining encrypted fields
You can now define your encrypted fields using the EncryptedMessage struct.
The first type parameter is the payload type, the second is the encryption strategy, & the third is the key configuration type.
use encrypted_message::{EncryptedMessage, strategy::Randomized};
struct User {
diary: EncryptedMessage<String, Randomized, KeyConfig>,
}§Encrypting & decrypting payloads
If your KeyConfig implements the Default trait (like above), you can use the shorthand methods:
// Encrypt a user's diary.
let mut user = User {
diary: EncryptedMessage::encrypt("Very personal stuff".to_string()).unwrap(),
};
// Decrypt the user's diary.
let decrypted: String = user.diary.decrypt().unwrap();
// Update the user's diary using the same encryption strategy & key config.
user.diary = user.diary.with_new_payload("More personal stuff".to_string()).unwrap();If your KeyConfig depends on external data:
use encrypted_message::{
EncryptedMessage,
key_config::Secret,
strategy::Randomized,
utilities::key_generation::derive_key_from,
};
use secrecy::{ExposeSecret as _, SecretString};
#[derive(Debug)]
struct UserKeyConfig {
user_password: SecretString,
salt: SecretString,
}
impl encrypted_message::KeyConfig for UserKeyConfig {
fn keys(&self) -> Vec<Secret<[u8; 32]>> {
let raw_key = self.user_password.expose_secret().as_bytes();
let salt = self.salt.expose_secret().as_bytes();
vec![derive_key_from(&raw_key, &salt, 2_u32.pow(16))]
}
}
struct User {
diary: EncryptedMessage<String, Randomized, UserKeyConfig>,
}
// Define the user's key configuration.
let key_config = UserKeyConfig {
user_password: "human-password-that-should-be-derived".to_string().into(),
salt: "unique-salt".to_string().into(),
};
// Encrypt a user's diary.
let mut user = User {
diary: EncryptedMessage::encrypt_with_key_config("Very personal stuff".to_string(), &key_config).unwrap(),
};
// Decrypt the user's diary.
let decrypted: String = user.diary.decrypt_with_key_config(&key_config).unwrap();
// Update the user's diary using the same encryption strategy & key config.
user.diary = user.diary.with_new_payload_and_key_config("More personal stuff".to_string(), &key_config).unwrap();§Integration with Diesel
EncryptedMessage implements FromSql & ToSql,
allowing you to use EncryptedMessage as a field type in your models.
Re-exports§
pub use error::EncryptionError;pub use error::DecryptionError;pub use key_config::KeyConfig;
Modules§
- Error types for the encryption & decryption operations.
- Contains the
KeyConfigtrait used to define a key configuration to use withEncryptedMessage. - All the encryption strategies that can be used with
EncryptedMessage. - This module contains utility functions to help you generate keys, as well as decode keys from different formats.
Structs§
- Used to safely handle & transport encrypted data within your application. It contains an encrypted payload, along with a nonce & tag that are used in the encryption & decryption processes.