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}