dup_crypto/scrypt/
params.rs

1//  Copyright (C) 2020  Éloïs SANCHEZ.
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
16//! Manage cryptographic operations for DUniter Protocols and the Duniter eco-system most broadly.
17//!
18//! Scrypt parameters
19
20use std::mem::size_of;
21
22/// The Scrypt parameter values.
23#[derive(Clone, Copy)]
24pub struct ScryptParams {
25    pub(crate) log_n: u8,
26    pub(crate) r: u32,
27    pub(crate) p: u32,
28}
29
30impl Default for ScryptParams {
31    fn default() -> Self {
32        ScryptParams {
33            log_n: 12,
34            r: 16,
35            p: 1,
36        }
37    }
38}
39
40impl ScryptParams {
41    ///
42    /// Create a new instance of ScryptParams.
43    ///
44    /// # Arguments
45    ///
46    /// * `log_n` - The log2 of the Scrypt parameter N
47    /// * `r` - The Scrypt parameter r
48    /// * `p` - The Scrypt parameter p
49    ///
50    ///
51    pub fn new(log_n: u8, r: u32, p: u32) -> ScryptParams {
52        assert!(r > 0);
53        assert!(p > 0);
54        assert!(log_n > 0);
55        assert!((log_n as usize) < size_of::<usize>() * 8);
56        assert!(
57            size_of::<usize>() >= size_of::<u32>()
58                || (r <= std::usize::MAX as u32 && p < std::usize::MAX as u32)
59        );
60
61        let r = r as usize;
62        let p = p as usize;
63
64        let n: usize = 1 << log_n;
65
66        // check that r * 128 doesn't overflow
67        let r128 = if let Some(r128) = r.checked_mul(128) {
68            r128
69        } else {
70            panic!("Invalid Scrypt parameters.");
71        };
72
73        // check that n * r * 128 doesn't overflow
74        if r128.checked_mul(n).is_none() {
75            panic!("Invalid Scrypt parameters.");
76        };
77
78        // check that p * r * 128 doesn't overflow
79        if r128.checked_mul(p).is_none() {
80            panic!("Invalid Scrypt parameters.");
81        };
82
83        // This check required by Scrypt:
84        // check: n < 2^(128 * r / 8)
85        // r * 16 won't overflow since r128 didn't
86        assert!((log_n as usize) < r * 16);
87
88        // This check required by Scrypt:
89        // check: p <= ((2^32-1) * 32) / (128 * r)
90        // It takes a bit of re-arranging to get the check above into this form, but, it is indeed
91        // the same.
92        assert!(r * p < 0x4000_0000);
93
94        ScryptParams {
95            log_n,
96            r: r as u32,
97            p: p as u32,
98        }
99    }
100}