Skip to main content

minisign/
helpers.rs

1use std::cmp;
2use std::time::{SystemTime, UNIX_EPOCH};
3
4#[cfg(any(windows, unix))]
5use rpassword::prompt_password;
6
7use crate::constants::*;
8use crate::errors::*;
9
10#[cfg(not(any(windows, unix)))]
11fn prompt_password(prompt: &str) -> Result<String> {
12    use std::io::{stdin, stdout, Write};
13
14    stdout().write_all(prompt.as_bytes())?;
15    stdout().flush()?;
16    let mut password = String::new();
17    stdin().read_line(&mut password)?;
18    Ok(password)
19}
20
21pub fn store_u64_le(x: u64) -> [u8; 8] {
22    let b1: u8 = (x & 0xff) as u8;
23    let b2: u8 = ((x >> 8) & 0xff) as u8;
24    let b3: u8 = ((x >> 16) & 0xff) as u8;
25    let b4: u8 = ((x >> 24) & 0xff) as u8;
26    let b5: u8 = ((x >> 32) & 0xff) as u8;
27    let b6: u8 = ((x >> 40) & 0xff) as u8;
28    let b7: u8 = ((x >> 48) & 0xff) as u8;
29    let b8: u8 = ((x >> 56) & 0xff) as u8;
30    [b1, b2, b3, b4, b5, b6, b7, b8]
31}
32
33#[allow(clippy::cast_lossless)]
34pub fn load_u64_le(x: &[u8]) -> u64 {
35    (x[0] as u64)
36        | (x[1] as u64) << 8
37        | (x[2] as u64) << 16
38        | (x[3] as u64) << 24
39        | (x[4] as u64) << 32
40        | (x[5] as u64) << 40
41        | (x[6] as u64) << 48
42        | (x[7] as u64) << 56
43}
44
45pub fn raw_scrypt_params(memlimit: usize, opslimit: u64, n_log2_max: u8) -> Result<scrypt::Params> {
46    let opslimit = cmp::max(32768, opslimit);
47    let mut n_log2 = 1u8;
48    let r = 8u32;
49    let p;
50    if opslimit < (memlimit / 32) as u64 {
51        p = 1;
52        let maxn = opslimit / (u64::from(r) * 4);
53        while n_log2 < 63 {
54            if 1u64 << n_log2 > maxn / 2 {
55                break;
56            }
57            n_log2 += 1;
58        }
59    } else {
60        let maxn = memlimit as u64 / (u64::from(r) * 128);
61        while n_log2 < 63 {
62            if 1u64 << n_log2 > maxn / 2 {
63                break;
64            }
65            n_log2 += 1;
66        }
67        let maxrp = cmp::min(0x3fff_ffff_u32, ((opslimit / 4) / (1u64 << n_log2)) as u32);
68        p = maxrp / r;
69    }
70    if n_log2 > n_log2_max {
71        return Err(PError::new(ErrorKind::KDF, "scrypt parameters too high"));
72    }
73    scrypt::Params::new(n_log2, r, p, scrypt::Params::RECOMMENDED_LEN).map_err(Into::into)
74}
75
76pub fn get_password(prompt: &str) -> Result<String> {
77    let pwd = prompt_password(prompt)?;
78    if pwd.is_empty() {
79        println!("<empty>");
80        Ok(pwd)
81    } else if pwd.len() > PASSWORD_MAXBYTES {
82        Err(PError::new(
83            ErrorKind::Misc,
84            "passphrase can't exceed 1024 bytes length",
85        ))
86    } else {
87        Ok(pwd)
88    }
89}
90
91pub fn unix_timestamp() -> u64 {
92    let start = SystemTime::now();
93    let since_the_epoch = start
94        .duration_since(UNIX_EPOCH)
95        .expect("system clock is incorrect");
96    since_the_epoch.as_secs()
97}