Skip to content

Commit 5f07487

Browse files
authored
password-hash: remove Encoding enum (#2102)
The encoding types in this crate are designed around the PHC String Format which uses "B64", a.k.a. unpadded non-URL-safe Base64. The `Encoding` type was designed to make it possible to use alternative encodings from Modular Crypt Format (MCF), but that doesn't actually make sense because PHC Strings mandate "B64". The `Encoding` type has since been extracted into the `mcf` crate as `mcf::Base64`: RustCrypto/formats#1918
1 parent f17bf09 commit 5f07487

File tree

6 files changed

+47
-170
lines changed

6 files changed

+47
-170
lines changed

password-hash/src/encoding.rs

Lines changed: 0 additions & 85 deletions
This file was deleted.

password-hash/src/lib.rs

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ pub use rand_core;
3333

3434
pub mod errors;
3535

36-
mod encoding;
3736
mod ident;
3837
mod output;
3938
mod params;
@@ -42,7 +41,6 @@ mod traits;
4241
mod value;
4342

4443
pub use crate::{
45-
encoding::Encoding,
4644
errors::{Error, Result},
4745
ident::Ident,
4846
output::Output,
@@ -128,11 +126,6 @@ pub struct PasswordHash<'a> {
128126
impl<'a> PasswordHash<'a> {
129127
/// Parse a password hash from a string in the PHC string format.
130128
pub fn new(s: &'a str) -> Result<Self> {
131-
Self::parse(s, Encoding::default())
132-
}
133-
134-
/// Parse a password hash from the given [`Encoding`].
135-
pub fn parse(s: &'a str, encoding: Encoding) -> Result<Self> {
136129
if s.is_empty() {
137130
return Err(Error::PhcStringField);
138131
}
@@ -185,7 +178,7 @@ impl<'a> PasswordHash<'a> {
185178
}
186179

187180
if let Some(field) = fields.next() {
188-
hash = Some(Output::decode(field, encoding)?);
181+
hash = Some(Output::decode(field)?);
189182
}
190183

191184
if fields.next().is_some() {
@@ -226,11 +219,6 @@ impl<'a> PasswordHash<'a> {
226219
Err(Error::Password)
227220
}
228221

229-
/// Get the [`Encoding`] that this [`PasswordHash`] is serialized with.
230-
pub fn encoding(&self) -> Encoding {
231-
self.hash.map(|h| h.encoding()).unwrap_or_default()
232-
}
233-
234222
/// Serialize this [`PasswordHash`] as a [`PasswordHashString`].
235223
#[cfg(feature = "alloc")]
236224
pub fn serialize(&self) -> PasswordHashString {
@@ -282,32 +270,19 @@ impl fmt::Display for PasswordHash<'_> {
282270
pub struct PasswordHashString {
283271
/// String value
284272
string: String,
285-
286-
/// String encoding
287-
encoding: Encoding,
288273
}
289274

290275
#[cfg(feature = "alloc")]
291276
#[allow(clippy::len_without_is_empty)]
292277
impl PasswordHashString {
293278
/// Parse a password hash from a string in the PHC string format.
294279
pub fn new(s: &str) -> Result<Self> {
295-
Self::parse(s, Encoding::default())
296-
}
297-
298-
/// Parse a password hash from the given [`Encoding`].
299-
pub fn parse(s: &str, encoding: Encoding) -> Result<Self> {
300-
Ok(PasswordHash::parse(s, encoding)?.into())
280+
PasswordHash::new(s).map(Into::into)
301281
}
302282

303283
/// Parse this owned string as a [`PasswordHash`].
304284
pub fn password_hash(&self) -> PasswordHash<'_> {
305-
PasswordHash::parse(&self.string, self.encoding).expect("malformed password hash")
306-
}
307-
308-
/// Get the [`Encoding`] that this [`PasswordHashString`] is serialized with.
309-
pub fn encoding(&self) -> Encoding {
310-
self.encoding
285+
PasswordHash::new(&self.string).expect("malformed password hash")
311286
}
312287

313288
/// Borrow this value as a `str`.
@@ -370,7 +345,6 @@ impl From<&PasswordHash<'_>> for PasswordHashString {
370345
fn from(hash: &PasswordHash<'_>) -> PasswordHashString {
371346
PasswordHashString {
372347
string: hash.to_string(),
373-
encoding: hash.encoding(),
374348
}
375349
}
376350
}

password-hash/src/output.rs

Lines changed: 34 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Outputs from password hashing functions.
22
3-
use crate::{Encoding, Error, Result};
3+
use crate::{Error, Result};
4+
use base64ct::{Base64Unpadded as B64, Encoding};
45
use core::{cmp::Ordering, fmt, str::FromStr};
56
use subtle::{Choice, ConstantTimeEq};
67

@@ -102,9 +103,6 @@ pub struct Output {
102103

103104
/// Length of the password hashing function output in bytes.
104105
length: u8,
105-
106-
/// Encoding which output should be serialized with.
107-
encoding: Encoding,
108106
}
109107

110108
#[allow(clippy::len_without_is_empty)]
@@ -130,15 +128,6 @@ impl Output {
130128
})
131129
}
132130

133-
/// Create a [`Output`] from the given byte slice and [`Encoding`],
134-
/// validating it according to [`Output::MIN_LENGTH`] and
135-
/// [`Output::MAX_LENGTH`] restrictions.
136-
pub fn new_with_encoding(input: &[u8], encoding: Encoding) -> Result<Self> {
137-
let mut result = Self::new(input)?;
138-
result.encoding = encoding;
139-
Ok(result)
140-
}
141-
142131
/// Initialize an [`Output`] using the provided method, which is given
143132
/// a mutable byte slice into which it should write the output.
144133
///
@@ -169,7 +158,6 @@ impl Output {
169158
Ok(Self {
170159
bytes,
171160
length: output_size as u8,
172-
encoding: Encoding::default(),
173161
})
174162
}
175163

@@ -178,52 +166,53 @@ impl Output {
178166
&self.bytes[..self.len()]
179167
}
180168

181-
/// Get the [`Encoding`] that this [`Output`] is serialized with.
182-
pub fn encoding(&self) -> Encoding {
183-
self.encoding
184-
}
185-
186-
/// Creates a copy of this [`Output`] with the specified [`Encoding`].
187-
pub fn with_encoding(&self, encoding: Encoding) -> Self {
188-
Self { encoding, ..*self }
189-
}
190-
191169
/// Get the length of the output value as a byte slice.
192170
pub fn len(&self) -> usize {
193171
usize::from(self.length)
194172
}
195173

196-
/// Parse B64-encoded [`Output`], i.e. using the PHC string
197-
/// specification's restricted interpretation of Base64.
198-
pub fn b64_decode(input: &str) -> Result<Self> {
199-
Self::decode(input, Encoding::B64)
174+
/// Parse "B64"-encoded [`Output`], i.e. using the PHC string specification's restricted
175+
/// interpretation of Base64.
176+
pub fn decode(input: &str) -> Result<Self> {
177+
let mut bytes = [0u8; Self::MAX_LENGTH];
178+
B64::decode(input, &mut bytes)
179+
.map_err(Into::into)
180+
.and_then(Self::new)
200181
}
201182

202-
/// Write B64-encoded [`Output`] to the provided buffer, returning
203-
/// a sub-slice containing the encoded data.
183+
/// Write "B64"-encoded [`Output`] to the provided buffer, returning a sub-slice containing the
184+
/// encoded data.
204185
///
205186
/// Returns an error if the buffer is too short to contain the output.
206-
pub fn b64_encode<'a>(&self, out: &'a mut [u8]) -> Result<&'a str> {
207-
self.encode(out, Encoding::B64)
187+
pub fn encode<'a>(&self, out: &'a mut [u8]) -> Result<&'a str> {
188+
Ok(B64::encode(self.as_ref(), out)?)
208189
}
209190

210-
/// Decode the given input string using the specified [`Encoding`].
211-
pub fn decode(input: &str, encoding: Encoding) -> Result<Self> {
212-
let mut bytes = [0u8; Self::MAX_LENGTH];
213-
encoding
214-
.decode(input, &mut bytes)
215-
.map_err(Into::into)
216-
.and_then(|decoded| Self::new_with_encoding(decoded, encoding))
191+
/// Get the length of this [`Output`] when encoded as "B64".
192+
pub fn encoded_len(&self) -> usize {
193+
B64::encoded_len(self.as_ref())
217194
}
218195

219-
/// Encode this [`Output`] using the specified [`Encoding`].
220-
pub fn encode<'a>(&self, out: &'a mut [u8], encoding: Encoding) -> Result<&'a str> {
221-
Ok(encoding.encode(self.as_ref(), out)?)
196+
/// DEPRECATED: parse B64-encoded [`Output`], i.e. using the PHC string specification's
197+
/// restricted interpretation of Base64.
198+
#[deprecated(since = "0.6.0", note = "Use `Output::decode` instead")]
199+
pub fn b64_decode(input: &str) -> Result<Self> {
200+
Self::decode(input)
201+
}
202+
203+
/// DEPRECATED: write B64-encoded [`Output`] to the provided buffer, returning a sub-slice
204+
/// containing the encoded data.
205+
///
206+
/// Returns an error if the buffer is too short to contain the output.
207+
#[deprecated(since = "0.6.0", note = "Use `Output::encode` instead")]
208+
pub fn b64_encode<'a>(&self, out: &'a mut [u8]) -> Result<&'a str> {
209+
self.encode(out)
222210
}
223211

224212
/// Get the length of this [`Output`] when encoded as B64.
213+
#[deprecated(since = "0.6.0", note = "Use `Output::encoded_len` instead")]
225214
pub fn b64_len(&self) -> usize {
226-
Encoding::B64.encoded_len(self.as_ref())
215+
self.encoded_len()
227216
}
228217
}
229218

@@ -243,7 +232,7 @@ impl FromStr for Output {
243232
type Err = Error;
244233

245234
fn from_str(s: &str) -> Result<Self> {
246-
Self::b64_decode(s)
235+
Self::decode(s)
247236
}
248237
}
249238

@@ -264,7 +253,7 @@ impl TryFrom<&[u8]> for Output {
264253
impl fmt::Display for Output {
265254
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266255
let mut buffer = [0u8; Self::B64_MAX_LENGTH];
267-
self.encode(&mut buffer, self.encoding)
256+
self.encode(&mut buffer)
268257
.map_err(|_| fmt::Error)
269258
.and_then(|encoded| f.write_str(encoded))
270259
}

password-hash/src/params.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
//! Algorithm parameters.
22
3-
use crate::errors::InvalidValue;
43
use crate::{
5-
Encoding, Error, Ident, Result,
4+
Error, Ident, Result,
5+
errors::InvalidValue,
66
value::{Decimal, Value},
77
};
8+
use base64ct::{Base64Unpadded as B64, Encoding};
89
use core::{
910
fmt::{self, Debug, Write},
1011
str::{self, FromStr},
@@ -67,9 +68,7 @@ impl ParamsString {
6768

6869
// Encode B64 value
6970
let offset = self.0.length as usize;
70-
let written = Encoding::B64
71-
.encode(bytes, &mut self.0.bytes[offset..])?
72-
.len();
71+
let written = B64::encode(bytes, &mut self.0.bytes[offset..])?.len();
7372

7473
self.0.length += written as u8;
7574
Ok(())

password-hash/src/salt.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Salt string support.
22
3-
use crate::{Encoding, Error, Result, Value};
3+
use crate::{Error, Result, Value, errors::InvalidValue};
4+
use base64ct::{Base64Unpadded as B64, Encoding};
45
use core::{fmt, str};
56

6-
use crate::errors::InvalidValue;
77
#[cfg(feature = "rand_core")]
88
use rand_core::{CryptoRng, TryCryptoRng};
99

@@ -239,7 +239,7 @@ impl SaltString {
239239
/// Returns `Error` if the slice is too long.
240240
pub fn encode_b64(input: &[u8]) -> Result<Self> {
241241
let mut bytes = [0u8; Salt::MAX_LENGTH];
242-
let length = Encoding::B64.encode(input, &mut bytes)?.len() as u8;
242+
let length = B64::encode(input, &mut bytes)?.len() as u8;
243243
Ok(Self {
244244
chars: bytes,
245245
length,

password-hash/src/value.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
//!
1414
//! [1]: https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md
1515
16-
use crate::errors::InvalidValue;
17-
use crate::{Encoding, Error, Result};
16+
use crate::{Error, Result, errors::InvalidValue};
17+
use base64ct::{Base64Unpadded as B64, Encoding};
1818
use core::{fmt, str};
1919

2020
/// Type used to represent decimal (i.e. integer) values.
@@ -69,7 +69,7 @@ impl<'a> Value<'a> {
6969
///
7070
/// [1]: https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md#argon2-encoding
7171
pub fn b64_decode<'b>(&self, buf: &'b mut [u8]) -> Result<&'b [u8]> {
72-
Ok(Encoding::B64.decode(self.as_str(), buf)?)
72+
Ok(B64::decode(self.as_str(), buf)?)
7373
}
7474

7575
/// Borrow this value as a `str`.

0 commit comments

Comments
 (0)