1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

use botan_sys::*;
use utils::*;

/// Password based key derivation function
///
/// # Examples
/// ```
/// let rng = botan::RandomNumberGenerator::new().unwrap();
/// let salt = rng.read(10).unwrap();
/// let key = botan::derive_key_from_password("Scrypt", 32, "passphrase", &salt, 8192, 8, 1).unwrap();
/// assert_eq!(key.len(), 32);
/// ```
pub fn derive_key_from_password(
    algo: &str,
    out_len: usize,
    passphrase: &str,
    salt: &[u8],
    param1: usize,
    param2: usize,
    param3: usize) -> Result<Vec<u8>> {

    let algo = make_cstr(algo)?;
    let passphrase = make_cstr(passphrase)?;

    let mut output = vec![0u8; out_len];

    call_botan! {
        botan_pwdhash(algo.as_ptr(),
                      param1,
                      param2,
                      param3,
                      output.as_mut_ptr(),
                      output.len(),
                      passphrase.as_ptr(),
                      0,
                      salt.as_ptr(),
                      salt.len())
    }

    Ok(output)
}

/// Password based key derivation function
///
/// Note currently only PBKDF2 is supported by this interface.
/// For PBKDF2, iterations >= 100000 is recommended.
///
/// # Examples
/// ```
/// let rng = botan::RandomNumberGenerator::new().unwrap();
/// let salt = rng.read(10).unwrap();
/// let key = botan::pbkdf("PBKDF2(SHA-256)", 32, "passphrase", &salt, 10000).unwrap();
/// assert_eq!(key.len(), 32);
/// ```
pub fn pbkdf(algo: &str,
             out_len: usize,
             passphrase: &str,
             salt: &[u8],
             iterations: usize) -> Result<Vec<u8>> {

    derive_key_from_password(algo, out_len, passphrase, salt, iterations, 0, 0)
}

/// Scrypt key derivation
///
/// The n, r, p parameters control how much time and memory is used.
/// As of 2018, n = 32768, r = 8, p = 1 seems sufficient.
///
/// # Examples
/// ```
/// let rng = botan::RandomNumberGenerator::new().unwrap();
/// let salt = rng.read(10).unwrap();
/// let n = 32768;
/// let r = 8;
/// let p = 1;
/// let key = botan::scrypt(32, "passphrase", &salt, n, r, p).unwrap();
/// assert_eq!(key.len(), 32);
/// ```
pub fn scrypt(out_len: usize,
              passphrase: &str,
              salt: &[u8],
              n: usize,
              r: usize,
              p: usize) -> Result<Vec<u8>> {

    derive_key_from_password("Scrypt", out_len, passphrase, salt, n, r, p)
}