Skip to content

Commit bf6c956

Browse files
authored
pbkdf2: use Base64::Pbkdf2 (#815)
Use support for PBKDF2's special Base64 alphabet now natively implemented in the `base64ct` and `mcf` crates in RustCrypto/formats#2168.
1 parent 1ff0a06 commit bf6c956

File tree

4 files changed

+19
-39
lines changed

4 files changed

+19
-39
lines changed

Cargo.lock

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ opt-level = 2
2020
argon2 = { path = "./argon2" }
2121
pbkdf2 = { path = "./pbkdf2" }
2222
scrypt = { path = "./scrypt" }
23+
24+
mcf = { git = "https://github.com/RustCrypto/formats", branch = "base64ct/pbkdf2-alphabet" }

pbkdf2/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@
9393
//! # }
9494
//! ```
9595
96-
#[cfg(feature = "mcf")]
97-
extern crate alloc;
98-
9996
#[cfg(feature = "mcf")]
10097
pub mod mcf;
10198
#[cfg(feature = "phc")]

pbkdf2/src/mcf.rs

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
pub use mcf::{PasswordHash, PasswordHashRef};
1111

1212
use crate::{Algorithm, Params, Pbkdf2, pbkdf2_hmac};
13-
use alloc::{string::String, vec::Vec};
1413
use mcf::Base64;
1514
use password_hash::{
1615
CustomizedPasswordHasher, Error, PasswordHasher, PasswordVerifier, Result, Version,
@@ -55,19 +54,11 @@ impl CustomizedPasswordHasher<PasswordHash> for Pbkdf2 {
5554
f(password, salt, params.rounds(), out);
5655

5756
let mut mcf_hash = PasswordHash::from_id(algorithm.to_str()).expect("should have valid ID");
58-
5957
mcf_hash
6058
.push_displayable(params)
6159
.map_err(|_| Error::EncodingInvalid)?;
62-
63-
mcf_hash
64-
.push_str(&base64_encode(salt))
65-
.map_err(|_| Error::EncodingInvalid)?;
66-
67-
mcf_hash
68-
.push_str(&base64_encode(out))
69-
.map_err(|_| Error::EncodingInvalid)?;
70-
60+
mcf_hash.push_base64(salt, Base64::Pbkdf2);
61+
mcf_hash.push_base64(out, Base64::Pbkdf2);
7162
Ok(mcf_hash)
7263
}
7364
}
@@ -97,13 +88,17 @@ impl PasswordVerifier<PasswordHashRef> for Pbkdf2 {
9788
next = fields.next().ok_or(Error::EncodingInvalid)?;
9889
}
9990

100-
let salt = base64_decode(next.as_str())?;
91+
// decode salt
92+
let salt = next
93+
.decode_base64(Base64::Pbkdf2)
94+
.map_err(|_| Error::EncodingInvalid)?;
10195

10296
// decode expected password hash
10397
let expected = fields
10498
.next()
105-
.ok_or(Error::EncodingInvalid)
106-
.and_then(|field| base64_decode(field.as_str()))?;
99+
.ok_or(Error::EncodingInvalid)?
100+
.decode_base64(Base64::Pbkdf2)
101+
.map_err(|_| Error::EncodingInvalid)?;
107102

108103
// should be the last field
109104
if fields.next().is_some() {
@@ -136,25 +131,12 @@ impl PasswordVerifier<PasswordHashRef> for Pbkdf2 {
136131
}
137132
}
138133

139-
// Base64 support: PBKDF2 uses a variant of standard unpadded Base64 which substitutes the `+`
140-
// character for `.` and this is a distinct encoding from the bcrypt and crypt Base64 variants.
141-
142-
fn base64_decode(base64: &str) -> Result<Vec<u8>> {
143-
Base64::B64
144-
.decode_vec(&base64.replace('.', "+"))
145-
.map_err(|_| Error::EncodingInvalid)
146-
}
147-
148-
fn base64_encode(bytes: &[u8]) -> String {
149-
Base64::B64.encode_string(bytes).replace('+', ".")
150-
}
151-
152-
// TODO(tarcieri): tests for SHA-1 and SHA-512
134+
// TODO(tarcieri): tests for SHA-1
153135
#[cfg(test)]
154136
mod tests {
155-
use super::{Error, base64_decode};
137+
use super::Error;
156138
use crate::{Params, Pbkdf2};
157-
use mcf::PasswordHash;
139+
use mcf::{Base64, PasswordHash};
158140
use password_hash::{CustomizedPasswordHasher, PasswordVerifier};
159141

160142
// Example adapted from:
@@ -167,7 +149,7 @@ mod tests {
167149
const EXAMPLE_HASH: &str =
168150
"$pbkdf2-sha256$8000$XAuBMIYQQogxRg$tRRlz8hYn63B9LYiCd6PRo6FMiunY9ozmMMI3srxeRE";
169151

170-
let salt = base64_decode(EXAMPLE_SALT).unwrap();
152+
let salt = Base64::Pbkdf2.decode_vec(EXAMPLE_SALT).unwrap();
171153
let params = Params::new(EXAMPLE_ROUNDS).unwrap();
172154

173155
let actual_hash: PasswordHash = Pbkdf2::SHA256
@@ -197,7 +179,7 @@ mod tests {
197179
const EXAMPLE_SALT: &str = "O4fwPmdMyRmDUIrx/h9jTA";
198180
const EXAMPLE_HASH: &str = "$pbkdf2-sha512$25000$O4fwPmdMyRmDUIrx/h9jTA$Xlp267ZwEbG4aOpN3Bve/ATo3rFA7WH8iMdS16Xbe9rc6P5welk1yiXEMPy7.BFp0qsncipHumaW1trCWVvq/A";
199181

200-
let salt = base64_decode(EXAMPLE_SALT).unwrap();
182+
let salt = Base64::Pbkdf2.decode_vec(EXAMPLE_SALT).unwrap();
201183
let params = Params::new_with_output_len(EXAMPLE_ROUNDS, 64).unwrap();
202184

203185
let actual_hash: PasswordHash = Pbkdf2::SHA512

0 commit comments

Comments
 (0)