@@ -113,53 +113,30 @@ use blake2::{digest, Blake2b, Digest};
113
113
114
114
#[ cfg( all( feature = "alloc" , feature = "password-hash" ) ) ]
115
115
use {
116
- core:: convert:: { TryFrom , TryInto } ,
117
- password_hash:: { Decimal , Ident , Salt } ,
116
+ core:: convert:: TryFrom ,
117
+ password_hash:: { Decimal , Ident , ParamsString , Salt } ,
118
118
} ;
119
119
120
120
/// Maximum password length in bytes.
121
- pub const MAX_PWD_LENGTH : usize = 0xFFFFFFFF ;
122
-
123
- /// Minimum and maximum associated data length in bytes.
124
- pub const MAX_AD_LENGTH : usize = 0xFFFFFFFF ;
121
+ pub const MAX_PWD_LEN : usize = 0xFFFFFFFF ;
125
122
126
123
/// Minimum and maximum salt length in bytes.
127
- pub const MIN_SALT_LENGTH : usize = 8 ;
124
+ pub const MIN_SALT_LEN : usize = 8 ;
128
125
129
126
/// Maximum salt length in bytes.
130
- pub const MAX_SALT_LENGTH : usize = 0xFFFFFFFF ;
127
+ pub const MAX_SALT_LEN : usize = 0xFFFFFFFF ;
131
128
132
129
/// Maximum secret key length in bytes.
133
- pub const MAX_SECRET_LENGTH : usize = 0xFFFFFFFF ;
130
+ pub const MAX_SECRET_LEN : usize = 0xFFFFFFFF ;
134
131
135
132
/// Argon2 context.
136
133
///
137
- /// Holds the following Argon2 inputs:
138
- ///
139
- /// - output array and its length,
140
- /// - password and its length,
141
- /// - salt and its length,
142
- /// - secret and its length,
143
- /// - associated data and its length,
144
- /// - number of passes, amount of used memory (in KBytes, can be rounded up a bit)
145
- /// - number of parallel threads that will be run.
146
- ///
147
- /// All the parameters above affect the output hash value.
148
- /// Additionally, two function pointers can be provided to allocate and
149
- /// deallocate the memory (if NULL, memory will be allocated internally).
150
- /// Also, three flags indicate whether to erase password, secret as soon as they
151
- /// are pre-hashed (and thus not needed anymore), and the entire memory
152
- ///
153
- /// Simplest situation: you have output array `out[8]`, password is stored in
154
- /// `pwd[32]`, salt is stored in `salt[16]`, you do not have keys nor associated
155
- /// data.
134
+ /// This is the primary type of this crate's API, and contains the following:
156
135
///
157
- /// You need to spend 1 GB of RAM and you run 5 passes of Argon2d with
158
- /// 4 parallel lanes.
159
- ///
160
- /// You want to erase the password, but you're OK with last pass not being
161
- /// erased.
162
- // TODO(tarcieri): replace `Params`-related fields with an internally-stored struct
136
+ /// - Argon2 [`Algorithm`] variant to be used
137
+ /// - Argon2 [`Version`] to be used
138
+ /// - Default set of [`Params`] to be used
139
+ /// - (Optional) Secret key a.k.a. "pepper" to be used
163
140
#[ derive( Clone ) ]
164
141
pub struct Argon2 < ' key > {
165
142
/// Algorithm to use
@@ -199,7 +176,7 @@ impl<'key> Argon2<'key> {
199
176
version : Version ,
200
177
params : Params ,
201
178
) -> Result < Self > {
202
- if MAX_SECRET_LENGTH < secret. len ( ) {
179
+ if MAX_SECRET_LEN < secret. len ( ) {
203
180
return Err ( Error :: SecretTooLong ) ;
204
181
}
205
182
@@ -214,15 +191,9 @@ impl<'key> Argon2<'key> {
214
191
/// Hash a password and associated parameters into the provided output buffer.
215
192
#[ cfg( feature = "alloc" ) ]
216
193
#[ cfg_attr( docsrs, doc( cfg( feature = "alloc" ) ) ) ]
217
- pub fn hash_password_into (
218
- & self ,
219
- pwd : & [ u8 ] ,
220
- salt : & [ u8 ] ,
221
- ad : & [ u8 ] ,
222
- out : & mut [ u8 ] ,
223
- ) -> Result < ( ) > {
194
+ pub fn hash_password_into ( & self , pwd : & [ u8 ] , salt : & [ u8 ] , out : & mut [ u8 ] ) -> Result < ( ) > {
224
195
let mut blocks = vec ! [ Block :: default ( ) ; self . params. block_count( ) ] ;
225
- self . hash_password_into_with_memory ( pwd, salt, ad , out, & mut blocks)
196
+ self . hash_password_into_with_memory ( pwd, salt, out, & mut blocks)
226
197
}
227
198
228
199
/// Hash a password and associated parameters into the provided output buffer.
@@ -238,49 +209,33 @@ impl<'key> Argon2<'key> {
238
209
& self ,
239
210
pwd : & [ u8 ] ,
240
211
salt : & [ u8 ] ,
241
- ad : & [ u8 ] ,
242
212
out : & mut [ u8 ] ,
243
213
mut memory_blocks : impl AsMut < [ Block ] > ,
244
214
) -> Result < ( ) > {
245
215
// Validate output length
246
- if out. len ( )
247
- < self
248
- . params
249
- . output_len ( )
250
- . unwrap_or ( Params :: MIN_OUTPUT_LENGTH )
251
- {
216
+ if out. len ( ) < self . params . output_len ( ) . unwrap_or ( Params :: MIN_OUTPUT_LEN ) {
252
217
return Err ( Error :: OutputTooShort ) ;
253
218
}
254
219
255
- if out. len ( )
256
- > self
257
- . params
258
- . output_len ( )
259
- . unwrap_or ( Params :: MAX_OUTPUT_LENGTH )
260
- {
220
+ if out. len ( ) > self . params . output_len ( ) . unwrap_or ( Params :: MAX_OUTPUT_LEN ) {
261
221
return Err ( Error :: OutputTooLong ) ;
262
222
}
263
223
264
- if pwd. len ( ) > MAX_PWD_LENGTH {
224
+ if pwd. len ( ) > MAX_PWD_LEN {
265
225
return Err ( Error :: PwdTooLong ) ;
266
226
}
267
227
268
228
// Validate salt (required param)
269
- if salt. len ( ) < MIN_SALT_LENGTH {
229
+ if salt. len ( ) < MIN_SALT_LEN {
270
230
return Err ( Error :: SaltTooShort ) ;
271
231
}
272
232
273
- if salt. len ( ) > MAX_SALT_LENGTH {
233
+ if salt. len ( ) > MAX_SALT_LEN {
274
234
return Err ( Error :: SaltTooLong ) ;
275
235
}
276
236
277
- // Validate associated data (optional param)
278
- if ad. len ( ) > MAX_AD_LENGTH {
279
- return Err ( Error :: AdTooLong ) ;
280
- }
281
-
282
237
// Hashing all inputs
283
- let initial_hash = self . initial_hash ( pwd, salt, ad , out) ;
238
+ let initial_hash = self . initial_hash ( pwd, salt, out) ;
284
239
285
240
let segment_length = self . params . segment_length ( ) ;
286
241
let block_count = self . params . block_count ( ) ;
@@ -298,12 +253,11 @@ impl<'key> Argon2<'key> {
298
253
& self . params
299
254
}
300
255
301
- /// Hashes all the inputs into `blockhash[PREHASH_DIGEST_LENGTH ]`.
256
+ /// Hashes all the inputs into `blockhash[PREHASH_DIGEST_LEN ]`.
302
257
pub ( crate ) fn initial_hash (
303
258
& self ,
304
259
pwd : & [ u8 ] ,
305
260
salt : & [ u8 ] ,
306
- ad : & [ u8 ] ,
307
261
out : & [ u8 ] ,
308
262
) -> digest:: Output < Blake2b > {
309
263
let mut digest = Blake2b :: new ( ) ;
@@ -325,8 +279,8 @@ impl<'key> Argon2<'key> {
325
279
digest. update ( 0u32 . to_le_bytes ( ) ) ;
326
280
}
327
281
328
- digest. update ( & ( ad . len ( ) as u32 ) . to_le_bytes ( ) ) ;
329
- digest. update ( ad ) ;
282
+ digest. update ( & ( self . params . data ( ) . len ( ) as u32 ) . to_le_bytes ( ) ) ;
283
+ digest. update ( self . params . data ( ) ) ;
330
284
digest. finalize ( )
331
285
}
332
286
}
@@ -348,22 +302,19 @@ impl PasswordHasher for Argon2<'_> {
348
302
let salt = Salt :: try_from ( salt. as_ref ( ) ) ?;
349
303
let mut salt_arr = [ 0u8 ; 64 ] ;
350
304
let salt_bytes = salt. b64_decode ( & mut salt_arr) ?;
351
-
352
- // TODO(tarcieri): support the `data` parameter (i.e. associated data)
353
- let ad = b"" ;
354
305
let output_len = self
355
306
. params
356
307
. output_len ( )
357
- . unwrap_or ( Params :: DEFAULT_OUTPUT_LENGTH ) ;
308
+ . unwrap_or ( Params :: DEFAULT_OUTPUT_LEN ) ;
358
309
359
310
let output = password_hash:: Output :: init_with ( output_len, |out| {
360
- Ok ( self . hash_password_into ( password, salt_bytes, ad , out) ?)
311
+ Ok ( self . hash_password_into ( password, salt_bytes, out) ?)
361
312
} ) ?;
362
313
363
314
Ok ( PasswordHash {
364
315
algorithm : self . algorithm . ident ( ) ,
365
316
version : Some ( self . version . into ( ) ) ,
366
- params : self . params . try_into ( ) ?,
317
+ params : ParamsString :: try_from ( & self . params ) ?,
367
318
salt : Some ( salt) ,
368
319
hash : Some ( output) ,
369
320
} )
@@ -407,7 +358,7 @@ impl<'key> From<Params> for Argon2<'key> {
407
358
408
359
impl < ' key > From < & Params > for Argon2 < ' key > {
409
360
fn from ( params : & Params ) -> Self {
410
- Self :: from ( * params)
361
+ Self :: from ( params. clone ( ) )
411
362
}
412
363
}
413
364
0 commit comments