Crate encrypted_message

Source
Expand description

§Configuration

First, you’ll need to create a configuration type by implementing the Config trait. If your configuration type 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.

use encrypted_message::{
    config::{Config, Secret, ExposeSecret as _},
    strategy::Randomized,
};

#[derive(Debug, Default)]
struct EncryptionConfig;
impl Config for EncryptionConfig {
    type Strategy = Randomized;

    fn keys(&self) -> Vec<Secret<[u8; 32]>> {
        std::env::var("ENCRYPTION_KEYS").unwrap()
            .split(", ")
            .map(|hex_key| {
                let hex_key = Secret::new(hex_key.to_string());
                let mut key = [0; 32];
                hex::decode_to_slice(hex_key.expose_secret(), &mut key).unwrap();

                key.into()
            })
            .collect()
    }
}

You can generate secure 32-byte keys using the openssl command-line tool:

openssl rand -hex 32

§Encryption strategies

Two encryption strategies are provided, Deterministic & Randomized.

  • Deterministic encryption will always produce the same encrypted message for the same payload, allowing you to query encrypted data.
  • Randomized encryption will always produce a different encrypted message for the same payload. More secure than Deterministic, 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 configuration type.

use encrypted_message::EncryptedMessage;

struct User {
    diary: EncryptedMessage<String, EncryptionConfig>,
}

§Encrypting & decrypting payloads

If your Config implements the Default trait (like above), you can use the shorthand methods:

// Encrypt a user's diary.
let user = User {
    diary: EncryptedMessage::encrypt("Very personal stuff".to_string()).unwrap(),
};

// Decrypt the user's diary.
let decrypted: String = user.diary.decrypt().unwrap();

If your Config depends on external data:

use encrypted_message::{
    EncryptedMessage,
    config::{Config, Secret, ExposeSecret as _},
    strategy::Randomized,
};
use pbkdf2::pbkdf2_hmac_array;
use sha2::Sha256;

#[derive(Debug)]
struct UserEncryptionConfig {
    user_password: Secret<String>,
    salt: Secret<String>,
}

impl Config for UserEncryptionConfig {
    type Strategy = Randomized;

    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![pbkdf2_hmac_array::<Sha256, 32>(raw_key, salt, 2_u32.pow(16)).into()]
    }
}

struct User {
    diary: EncryptedMessage<String, UserEncryptionConfig>,
}

// Define the user's encryption configuration.
let config = UserEncryptionConfig {
    user_password: "human-password-that-should-be-derived".to_string().into(),
    salt: "unique-salt".to_string().into(),
};

// Encrypt a user's diary.
let user = User {
    diary: EncryptedMessage::encrypt_with_config("Very personal stuff".to_string(), &config).unwrap(),
};

// Decrypt the user's diary.
let decrypted: String = user.diary.decrypt_with_config(&config).unwrap();

Re-exports§

pub use error::EncryptionError;
pub use error::DecryptionError;

Modules§

config
Contains the Config trait used to define the configuration for an EncryptedMessage.
error
Error types for the encryption & decryption operations.
strategy
All the encryption strategies that can be used with EncryptedMessage.

Structs§

EncryptedMessage
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.