diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-08-11 13:53:23 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-08-11 14:32:13 +0200 |
commit | be3f737fcf90c3a06fbb46f6c16c7acdba2b577e (patch) | |
tree | d20f6db3d3273ac177487578cc088c44d7945873 /openpgp/src/crypto/s2k.rs | |
parent | e25569baf8588194fe25ef3a817d4a94f64316fb (diff) |
openpgp: Add a constructor S2K::new_iterated.
- Creating S2K objects is tricky because not every iteration count
is representable. Add a constructor that helps with that.
Diffstat (limited to 'openpgp/src/crypto/s2k.rs')
-rw-r--r-- | openpgp/src/crypto/s2k.rs | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/openpgp/src/crypto/s2k.rs b/openpgp/src/crypto/s2k.rs index 319b17bc..11aa0435 100644 --- a/openpgp/src/crypto/s2k.rs +++ b/openpgp/src/crypto/s2k.rs @@ -66,25 +66,52 @@ pub enum S2K { impl Default for S2K { fn default() -> Self { - let mut salt = [0u8; 8]; - crate::crypto::random(&mut salt); - S2K::Iterated { + S2K::new_iterated( // SHA2-256, being optimized for implementations on // architectures with a word size of 32 bit, has a more // consistent runtime across different architectures than // SHA2-512. Furthermore, the digest size is large enough // for every cipher algorithm currently in use. - hash: HashAlgorithm::SHA256, - salt, + HashAlgorithm::SHA256, // This is the largest count that OpenPGP can represent. // On moderate machines, like my Intel(R) Core(TM) i5-2400 // CPU @ 3.10GHz, it takes ~354ms to derive a key. - hash_bytes: 65_011_712, - } + 0x3e00000, + ).expect("0x3e00000 is representable") } } impl S2K { + /// Creates a new iterated `S2K` object. + /// + /// Usually, you should use `S2K`s [`Default`] implementation to + /// create `S2K` objects with sane default parameters. The + /// parameters are chosen with contemporary machines in mind, and + /// should also be usable on lower-end devices like smart phones. + /// + /// [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html + /// + /// Using this method, you can tune the parameters for embedded + /// devices. Note, however, that this also decreases the work + /// factor for attackers doing dictionary attacks. + pub fn new_iterated(hash: HashAlgorithm, approx_hash_bytes: u32) + -> Result<Self> { + if approx_hash_bytes > 0x3e00000 { + Err(Error::InvalidArgument(format!( + "Number of bytes to hash not representable: {}", + approx_hash_bytes)).into()) + } else { + let mut salt = [0u8; 8]; + crate::crypto::random(&mut salt); + Ok(S2K::Iterated { + hash, + salt, + hash_bytes: + Self::nearest_hash_count(approx_hash_bytes as usize), + }) + } + } + /// Convert the string to a key using the S2K's parameters. pub fn derive_key(&self, password: &Password, key_size: usize) -> Result<SessionKey> { |