From 7019aa2635f8479d5728e43627e1bfd66b33d7cd Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 28 Aug 2024 04:59:58 +0000 Subject: [PATCH] age: Add `scrypt::Recipient::set_work_factor` for overriding default This can only be configured by using `scrypt::Recipient` directly in a library context. The helper method `Encryptor::with_user_passphrase` does not expose this, and `rage` continues to use the default. Closes str4d/rage#383. --- age/src/scrypt.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/age/src/scrypt.rs b/age/src/scrypt.rs index 3046718c..0b47f4db 100644 --- a/age/src/scrypt.rs +++ b/age/src/scrypt.rs @@ -104,12 +104,33 @@ fn target_scrypt_work_factor() -> u8 { /// [`x25519::Identity`]: crate::x25519::Identity pub struct Recipient { passphrase: SecretString, + log_n: u8, } impl Recipient { /// Constructs a new `Recipient` with the given passphrase. + /// + /// The scrypt work factor is picked to target about 1 second for encryption or + /// decryption on this device. Override it with [`Self::set_work_factor`]. pub fn new(passphrase: SecretString) -> Self { - Self { passphrase } + Self { + passphrase, + log_n: target_scrypt_work_factor(), + } + } + + /// Sets the scrypt work factor to `N = 2^log_n`. + /// + /// This method must be called before [`Self::wrap_file_key`] to have an effect. + /// + /// [`Self::wrap_file_key`]: crate::Recipient::wrap_file_key + /// + /// # Panics + /// + /// Panics if `log_n >= 64`. + pub fn set_work_factor(&mut self, log_n: u8) { + assert!(log_n < 64); + self.log_n = log_n; } } @@ -127,10 +148,8 @@ impl crate::Recipient for Recipient { inner_salt[..SCRYPT_SALT_LABEL.len()].copy_from_slice(SCRYPT_SALT_LABEL); inner_salt[SCRYPT_SALT_LABEL.len()..].copy_from_slice(&salt); - let log_n = target_scrypt_work_factor(); - let enc_key = - scrypt(&inner_salt, log_n, self.passphrase.expose_secret()).expect("log_n < 64"); + scrypt(&inner_salt, self.log_n, self.passphrase.expose_secret()).expect("log_n < 64"); let encrypted_file_key = aead_encrypt(&enc_key, file_key.expose_secret()); let encoded_salt = BASE64_STANDARD_NO_PAD.encode(salt);