Skip to content

Commit d48762a

Browse files
authored
sha-crypt: unify Params type (#772)
The previous `Sha256Params` and `Sha512Params` types were otherwise identical, so this commit unifies them into a single type
1 parent c5f8a75 commit d48762a

5 files changed

Lines changed: 91 additions & 143 deletions

File tree

sha-crypt/src/errors.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
33
use core::fmt;
44

5+
/// Result type for the `sha-crypt` crate with its [`Error`] type.
6+
pub type Result<T> = core::result::Result<T, Error>;
7+
58
/// Error type.
69
#[derive(Debug)]
710
pub enum Error {

sha-crypt/src/lib.rs

Lines changed: 44 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ mod simple;
3939

4040
pub use crate::{
4141
consts::{BLOCK_SIZE_SHA256, BLOCK_SIZE_SHA512},
42-
errors::Error,
43-
params::{ROUNDS_DEFAULT, ROUNDS_MAX, ROUNDS_MIN, Sha256Params, Sha512Params},
42+
errors::{Error, Result},
43+
params::Params,
4444
};
4545

4646
#[cfg(feature = "simple")]
@@ -53,25 +53,17 @@ pub use {
5353
use alloc::vec::Vec;
5454
use sha2::{Digest, Sha256, Sha512};
5555

56-
/// The SHA512 crypt function returned as byte vector
56+
/// The SHA-256 crypt function returned as byte vector
5757
///
5858
/// If the provided hash is longer than defs::SALT_MAX_LEN character, it will
5959
/// be stripped down to defs::SALT_MAX_LEN characters.
6060
///
6161
/// # Arguments
62-
/// - `password` - The password to process as a byte vector
63-
/// - `salt` - The salt value to use as a byte vector
64-
/// - `params` - The Sha512Params to use
62+
/// - `password`: the password to process as a byte vector
63+
/// - `salt`: the salt value to use as a byte vector
64+
/// - `params`: the parameters to use
6565
/// **WARNING: Make sure to compare this value in constant time!**
66-
///
67-
/// # Returns
68-
/// - `Ok(())` if calculation was successful
69-
/// - `Err(errors::CryptError)` otherwise
70-
pub fn sha512_crypt(
71-
password: &[u8],
72-
salt: &[u8],
73-
params: &Sha512Params,
74-
) -> [u8; BLOCK_SIZE_SHA512] {
66+
pub fn sha256_crypt(password: &[u8], salt: &[u8], params: &Params) -> [u8; BLOCK_SIZE_SHA256] {
7567
let pw_len = password.len();
7668

7769
let salt_len = salt.len();
@@ -81,10 +73,10 @@ pub fn sha512_crypt(
8173
};
8274
let salt_len = salt.len();
8375

84-
let digest_a = sha512crypt_intermediate(password, salt);
76+
let digest_a = sha256crypt_intermediate(password, salt);
8577

8678
// 13.
87-
let mut hasher_alt = Sha512::default();
79+
let mut hasher_alt = Sha256::default();
8880

8981
// 14.
9082
for _ in 0..pw_len {
@@ -99,7 +91,7 @@ pub fn sha512_crypt(
9991
let p_vec = produce_byte_seq(pw_len, &dp);
10092

10193
// 17.
102-
hasher_alt = Sha512::default();
94+
hasher_alt = Sha256::default();
10395

10496
// 18.
10597
// For every character in the password add the entire password.
@@ -116,11 +108,11 @@ pub fn sha512_crypt(
116108
let s_vec = produce_byte_seq(salt_len, &ds);
117109

118110
let mut digest_c = digest_a;
119-
// Repeatedly run the collected hash value through SHA512 to burn
111+
// Repeatedly run the collected hash value through SHA256 to burn
120112
// CPU cycles
121113
for i in 0..params.rounds {
122114
// new hasher
123-
let mut hasher = Sha512::default();
115+
let mut hasher = Sha256::default();
124116

125117
// Add key or last result
126118
if (i & 1) != 0 {
@@ -152,25 +144,17 @@ pub fn sha512_crypt(
152144
digest_c
153145
}
154146

155-
/// The SHA256 crypt function returned as byte vector
147+
/// The SHA-512 crypt function returned as byte vector
156148
///
157149
/// If the provided hash is longer than defs::SALT_MAX_LEN character, it will
158150
/// be stripped down to defs::SALT_MAX_LEN characters.
159151
///
160152
/// # Arguments
161-
/// - `password` - The password to process as a byte vector
153+
/// - `password`The password to process as a byte vector
162154
/// - `salt` - The salt value to use as a byte vector
163-
/// - `params` - The Sha256Params to use
155+
/// - `params` - The parameters to use
164156
/// **WARNING: Make sure to compare this value in constant time!**
165-
///
166-
/// # Returns
167-
/// - `Ok(())` if calculation was successful
168-
/// - `Err(errors::CryptError)` otherwise
169-
pub fn sha256_crypt(
170-
password: &[u8],
171-
salt: &[u8],
172-
params: &Sha256Params,
173-
) -> [u8; BLOCK_SIZE_SHA256] {
157+
pub fn sha512_crypt(password: &[u8], salt: &[u8], params: &Params) -> [u8; BLOCK_SIZE_SHA512] {
174158
let pw_len = password.len();
175159

176160
let salt_len = salt.len();
@@ -180,10 +164,10 @@ pub fn sha256_crypt(
180164
};
181165
let salt_len = salt.len();
182166

183-
let digest_a = sha256crypt_intermediate(password, salt);
167+
let digest_a = sha512crypt_intermediate(password, salt);
184168

185169
// 13.
186-
let mut hasher_alt = Sha256::default();
170+
let mut hasher_alt = Sha512::default();
187171

188172
// 14.
189173
for _ in 0..pw_len {
@@ -198,7 +182,7 @@ pub fn sha256_crypt(
198182
let p_vec = produce_byte_seq(pw_len, &dp);
199183

200184
// 17.
201-
hasher_alt = Sha256::default();
185+
hasher_alt = Sha512::default();
202186

203187
// 18.
204188
// For every character in the password add the entire password.
@@ -215,11 +199,11 @@ pub fn sha256_crypt(
215199
let s_vec = produce_byte_seq(salt_len, &ds);
216200

217201
let mut digest_c = digest_a;
218-
// Repeatedly run the collected hash value through SHA256 to burn
202+
// Repeatedly run the collected hash value through SHA512 to burn
219203
// CPU cycles
220204
for i in 0..params.rounds {
221205
// new hasher
222-
let mut hasher = Sha256::default();
206+
let mut hasher = Sha512::default();
223207

224208
// Add key or last result
225209
if (i & 1) != 0 {
@@ -251,28 +235,15 @@ pub fn sha256_crypt(
251235
digest_c
252236
}
253237

254-
fn produce_byte_seq(len: usize, fill_from: &[u8]) -> Vec<u8> {
255-
let bs = fill_from.len();
256-
let mut seq: Vec<u8> = vec![0; len];
257-
let mut offset: usize = 0;
258-
for _ in 0..(len / bs) {
259-
seq[offset..offset + bs].clone_from_slice(fill_from);
260-
offset += bs;
261-
}
262-
let from_slice = &fill_from[..(len % bs)];
263-
seq[offset..offset + (len % bs)].clone_from_slice(from_slice);
264-
seq
265-
}
266-
267-
fn sha512crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA512] {
238+
fn sha256crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA256] {
268239
let pw_len = password.len();
269240

270-
let mut hasher = Sha512::default();
241+
let mut hasher = Sha256::default();
271242
hasher.update(password);
272243
hasher.update(salt);
273244

274245
// 4.
275-
let mut hasher_alt = Sha512::default();
246+
let mut hasher_alt = Sha256::default();
276247
// 5.
277248
hasher_alt.update(password);
278249
// 6.
@@ -283,11 +254,11 @@ fn sha512crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA
283254
let digest_b = hasher_alt.finalize();
284255

285256
// 9.
286-
for _ in 0..(pw_len / BLOCK_SIZE_SHA512) {
257+
for _ in 0..(pw_len / BLOCK_SIZE_SHA256) {
287258
hasher.update(digest_b);
288259
}
289260
// 10.
290-
hasher.update(&digest_b[..(pw_len % BLOCK_SIZE_SHA512)]);
261+
hasher.update(&digest_b[..(pw_len % BLOCK_SIZE_SHA256)]);
291262

292263
// 11
293264
let mut n = pw_len;
@@ -307,15 +278,15 @@ fn sha512crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA
307278
hasher.finalize().as_slice().try_into().unwrap()
308279
}
309280

310-
fn sha256crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA256] {
281+
fn sha512crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA512] {
311282
let pw_len = password.len();
312283

313-
let mut hasher = Sha256::default();
284+
let mut hasher = Sha512::default();
314285
hasher.update(password);
315286
hasher.update(salt);
316287

317288
// 4.
318-
let mut hasher_alt = Sha256::default();
289+
let mut hasher_alt = Sha512::default();
319290
// 5.
320291
hasher_alt.update(password);
321292
// 6.
@@ -326,11 +297,11 @@ fn sha256crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA
326297
let digest_b = hasher_alt.finalize();
327298

328299
// 9.
329-
for _ in 0..(pw_len / BLOCK_SIZE_SHA256) {
300+
for _ in 0..(pw_len / BLOCK_SIZE_SHA512) {
330301
hasher.update(digest_b);
331302
}
332303
// 10.
333-
hasher.update(&digest_b[..(pw_len % BLOCK_SIZE_SHA256)]);
304+
hasher.update(&digest_b[..(pw_len % BLOCK_SIZE_SHA512)]);
334305

335306
// 11
336307
let mut n = pw_len;
@@ -349,3 +320,16 @@ fn sha256crypt_intermediate(password: &[u8], salt: &[u8]) -> [u8; BLOCK_SIZE_SHA
349320
// 12.
350321
hasher.finalize().as_slice().try_into().unwrap()
351322
}
323+
324+
fn produce_byte_seq(len: usize, fill_from: &[u8]) -> Vec<u8> {
325+
let bs = fill_from.len();
326+
let mut seq: Vec<u8> = vec![0; len];
327+
let mut offset: usize = 0;
328+
for _ in 0..(len / bs) {
329+
seq[offset..offset + bs].clone_from_slice(fill_from);
330+
offset += bs;
331+
}
332+
let from_slice = &fill_from[..(len % bs)];
333+
seq[offset..offset + (len % bs)].clone_from_slice(from_slice);
334+
seq
335+
}

sha-crypt/src/params.rs

Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,79 @@
11
//! Algorithm parameters.
22
3-
use crate::errors;
3+
use crate::{Error, Result};
44
use core::{
55
default::Default,
66
fmt::{self, Display},
77
str::FromStr,
88
};
99

10-
/// Default number of rounds.
11-
pub const ROUNDS_DEFAULT: u32 = 5_000;
12-
13-
/// Minimum number of rounds allowed.
14-
pub const ROUNDS_MIN: u32 = 1_000;
15-
16-
/// Maximum number of rounds allowed.
17-
pub const ROUNDS_MAX: u32 = 999_999_999;
18-
1910
/// Algorithm parameters.
2011
#[derive(Debug, Clone)]
21-
pub struct Sha512Params {
12+
pub struct Params {
13+
/// Number of times to apply the digest function
2214
pub(crate) rounds: u32,
2315
}
2416

25-
impl Default for Sha512Params {
26-
fn default() -> Self {
27-
Sha512Params {
28-
rounds: ROUNDS_DEFAULT,
29-
}
30-
}
31-
}
17+
impl Params {
18+
/// Default number of rounds.
19+
pub const ROUNDS_DEFAULT: u32 = 5_000;
3220

33-
impl Display for Sha512Params {
34-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35-
write!(f, "rounds={}", self.rounds)
36-
}
37-
}
21+
/// Minimum number of rounds allowed.
22+
pub const ROUNDS_MIN: u32 = 1_000;
3823

39-
impl FromStr for Sha512Params {
40-
type Err = errors::Error;
24+
/// Maximum number of rounds allowed.
25+
pub const ROUNDS_MAX: u32 = 999_999_999;
4126

42-
fn from_str(_s: &str) -> Result<Self, errors::Error> {
43-
todo!()
44-
}
45-
}
46-
47-
impl Sha512Params {
4827
/// Create new algorithm parameters.
49-
pub fn new(rounds: u32) -> Result<Sha512Params, errors::Error> {
50-
if (ROUNDS_MIN..=ROUNDS_MAX).contains(&rounds) {
51-
Ok(Sha512Params { rounds })
52-
} else {
53-
Err(errors::Error::RoundsError)
28+
pub fn new(rounds: u32) -> Result<Params> {
29+
match rounds {
30+
Self::ROUNDS_MIN..=Self::ROUNDS_MAX => Ok(Params { rounds }),
31+
_ => Err(Error::RoundsError),
5432
}
5533
}
5634
}
5735

58-
/// Algorithm parameters.
59-
#[derive(Debug, Clone)]
60-
pub struct Sha256Params {
61-
pub(crate) rounds: u32,
62-
}
63-
64-
impl Default for Sha256Params {
36+
impl Default for Params {
6537
fn default() -> Self {
66-
Sha256Params {
67-
rounds: ROUNDS_DEFAULT,
38+
Params {
39+
rounds: Self::ROUNDS_DEFAULT,
6840
}
6941
}
7042
}
7143

72-
impl Display for Sha256Params {
44+
impl Display for Params {
7345
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7446
write!(f, "rounds={}", self.rounds)
7547
}
7648
}
7749

78-
impl FromStr for Sha256Params {
79-
type Err = errors::Error;
50+
impl FromStr for Params {
51+
type Err = Error;
8052

81-
fn from_str(_s: &str) -> Result<Self, errors::Error> {
53+
fn from_str(_s: &str) -> Result<Self> {
8254
todo!()
8355
}
8456
}
8557

86-
impl Sha256Params {
87-
/// Create new algorithm parameters.
88-
pub fn new(rounds: u32) -> Result<Sha256Params, errors::Error> {
89-
if (ROUNDS_MIN..=ROUNDS_MAX).contains(&rounds) {
90-
Ok(Sha256Params { rounds })
91-
} else {
92-
Err(errors::Error::RoundsError)
93-
}
94-
}
95-
}
96-
9758
#[cfg(test)]
9859
mod tests {
99-
use super::{ROUNDS_MAX, ROUNDS_MIN, Sha256Params, Sha512Params};
60+
use super::Params;
10061

10162
#[test]
10263
fn test_sha256_crypt_invalid_rounds() {
103-
let params = Sha256Params::new(ROUNDS_MAX + 1);
64+
let params = Params::new(Params::ROUNDS_MAX + 1);
10465
assert!(params.is_err());
10566

106-
let params = Sha256Params::new(ROUNDS_MIN - 1);
67+
let params = Params::new(Params::ROUNDS_MIN - 1);
10768
assert!(params.is_err());
10869
}
10970

11071
#[test]
11172
fn test_sha512_crypt_invalid_rounds() {
112-
let params = Sha512Params::new(ROUNDS_MAX + 1);
73+
let params = Params::new(Params::ROUNDS_MAX + 1);
11374
assert!(params.is_err());
11475

115-
let params = Sha512Params::new(ROUNDS_MIN - 1);
76+
let params = Params::new(Params::ROUNDS_MIN - 1);
11677
assert!(params.is_err());
11778
}
11879
}

0 commit comments

Comments
 (0)