1#[allow(bad_style, dead_code)]
7mod sys;
8mod types;
9
10use std::convert::TryInto;
11use std::ffi::CStr;
12use types::{opt_slice_ptr_mut, opt_slice_len, opt_slice_ptr};
13
14pub use self::types::*;
15
16pub fn type2string(variant: Variant, uppercase: bool) -> &'static str {
20 unsafe {
21 let uppercase_i = if uppercase { 1 } else { 0 };
22 let str_ptr = sys::argon2_type2string(variant.to_c(), uppercase_i);
23 assert!(!str_ptr.is_null(), "null variant name.");
24 let str_cstr = CStr::from_ptr(str_ptr);
25 str_cstr.to_str().expect("Variant name is not valid UTF-8")
26 }
27}
28
29pub fn ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C, variant: Variant) -> Result<(), Error> {
31 unsafe {
32 Error::check_code(sys::argon2_ctx(&mut context.try_into()?, variant.to_c()) as _)
33 }
34}
35
36pub fn d_ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C) -> Result<(), Error> {
39 unsafe {
40 Error::check_code(sys::argon2d_ctx(&mut context.try_into()?))
41 }
42}
43
44pub fn i_ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C) -> Result<(), Error> {
48 unsafe {
49 Error::check_code(sys::argon2i_ctx(&mut context.try_into()?))
50 }
51}
52
53pub fn id_ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C) -> Result<(), Error> {
58 unsafe {
59 Error::check_code(sys::argon2id_ctx(&mut context.try_into()?))
60 }
61}
62
63pub fn i_hash_encoded(
78 t_cost: u32,
79 m_cost: u32,
80 parallelism: u32,
81 pwd: Option<&[u8]>,
82 salt: Option<&[u8]>,
83 hashlen: usize,
84 encoded: &mut [u8]) -> Result<(), Error> {
85 unsafe {
86 Error::check_code(
87 sys::argon2i_hash_encoded(
88 t_cost, m_cost, parallelism,
89 opt_slice_ptr(&pwd) as _,
90 opt_slice_len(&pwd),
91 opt_slice_ptr(&salt) as _,
92 opt_slice_len(&salt),
93 hashlen,
94 encoded.as_mut_ptr() as _,
95 encoded.len(),
96 )
97 )
98 }
99}
100
101pub fn i_hash_raw(
115 t_cost: u32,
116 m_cost: u32,
117 parallelism: u32,
118 pwd: Option<&[u8]>,
119 salt: Option<&[u8]>,
120 hash: &mut [u8]) -> Result<(), Error> {
121 unsafe {
122 Error::check_code(
123 sys::argon2i_hash_raw(
124 t_cost, m_cost, parallelism,
125 opt_slice_ptr(&pwd) as _,
126 opt_slice_len(&pwd),
127 opt_slice_ptr(&salt) as _,
128 opt_slice_len(&salt),
129 hash.as_mut_ptr() as _,
130 hash.len(),
131 )
132 )
133 }
134}
135
136pub fn d_hash_encoded(
151 t_cost: u32,
152 m_cost: u32,
153 parallelism: u32,
154 pwd: Option<&[u8]>,
155 salt: Option<&[u8]>,
156 hashlen: usize,
157 encoded: &mut [u8]) -> Result<(), Error> {
158 unsafe {
159 Error::check_code(
160 sys::argon2d_hash_encoded(
161 t_cost, m_cost, parallelism,
162 opt_slice_ptr(&pwd) as _,
163 opt_slice_len(&pwd),
164 opt_slice_ptr(&salt) as _,
165 opt_slice_len(&salt),
166 hashlen,
167 encoded.as_mut_ptr() as _,
168 encoded.len(),
169 )
170 )
171 }
172}
173
174pub fn d_hash_raw(
188 t_cost: u32,
189 m_cost: u32,
190 parallelism: u32,
191 pwd: Option<&[u8]>,
192 salt: Option<&[u8]>,
193 hash: &mut [u8]) -> Result<(), Error> {
194 unsafe {
195 Error::check_code(
196 sys::argon2d_hash_raw(
197 t_cost, m_cost, parallelism,
198 opt_slice_ptr(&pwd) as _,
199 opt_slice_len(&pwd),
200 opt_slice_ptr(&salt) as _,
201 opt_slice_len(&salt),
202 hash.as_mut_ptr() as _,
203 hash.len(),
204 )
205 )
206 }
207}
208
209pub fn id_hash_encoded(
224 t_cost: u32,
225 m_cost: u32,
226 parallelism: u32,
227 pwd: Option<&[u8]>,
228 salt: Option<&[u8]>,
229 hashlen: usize,
230 encoded: &mut [u8]) -> Result<(), Error> {
231 unsafe {
232 Error::check_code(
233 sys::argon2id_hash_encoded(
234 t_cost, m_cost, parallelism,
235 opt_slice_ptr(&pwd) as _,
236 opt_slice_len(&pwd),
237 opt_slice_ptr(&salt) as _,
238 opt_slice_len(&salt),
239 hashlen,
240 encoded.as_mut_ptr() as _,
241 encoded.len(),
242 )
243 )
244 }
245}
246
247pub fn id_hash_raw(
261 t_cost: u32,
262 m_cost: u32,
263 parallelism: u32,
264 pwd: Option<&[u8]>,
265 salt: Option<&[u8]>,
266 hash: &mut [u8]) -> Result<(), Error> {
267 unsafe {
268 Error::check_code(
269 sys::argon2id_hash_raw(
270 t_cost, m_cost, parallelism,
271 opt_slice_ptr(&pwd) as _,
272 opt_slice_len(&pwd),
273 opt_slice_ptr(&salt) as _,
274 opt_slice_len(&salt),
275 hash.as_mut_ptr() as _,
276 hash.len(),
277 )
278 )
279 }
280}
281
282pub fn hash(
299 t_cost: u32,
300 m_cost: u32,
301 parallelism: u32,
302 pwd: Option<&[u8]>,
303 salt: Option<&[u8]>,
304 mut hash: Option<&mut [u8]>,
305 mut encoded: Option<&mut [u8]>,
306 variant: Variant,
307 version: Version) -> Result<(), Error> {
308 unsafe {
309 Error::check_code(
310 sys::argon2_hash(
311 t_cost, m_cost, parallelism,
312 opt_slice_ptr(&pwd) as _,
313 opt_slice_len(&pwd),
314 opt_slice_ptr(&salt) as _,
315 opt_slice_len(&salt),
316 opt_slice_ptr_mut(&mut hash) as _,
317 opt_slice_len(&hash),
318 opt_slice_ptr_mut(&mut encoded) as _,
319 opt_slice_len(&encoded),
320 variant.to_c() as _,
321 version.to_c() as _,
322 )
323 )
324 }
325}
326
327pub fn i_verify(encoded: &CStr, pwd: Option<&[u8]>) -> Result<(), Error> {
333 unsafe {
334 Error::check_code(
335 sys::argon2i_verify(
336 encoded.as_ptr() as _,
337 opt_slice_ptr(&pwd) as _,
338 opt_slice_len(&pwd),
339 )
340 )
341 }
342}
343
344pub fn d_verify(encoded: &CStr, pwd: Option<&[u8]>) -> Result<(), Error> {
350 unsafe {
351 Error::check_code(
352 sys::argon2d_verify(
353 encoded.as_ptr() as _,
354 opt_slice_ptr(&pwd) as _,
355 opt_slice_len(&pwd),
356 )
357 )
358 }
359}
360
361pub fn id_verify(encoded: &CStr, pwd: Option<&[u8]>) -> Result<(), Error> {
367 unsafe {
368 Error::check_code(
369 sys::argon2id_verify(
370 encoded.as_ptr() as _,
371 opt_slice_ptr(&pwd) as _,
372 opt_slice_len(&pwd),
373 )
374 )
375 }
376}
377
378pub fn verify(encoded: &CStr, pwd: Option<&[u8]>, variant: Variant) -> Result<(), Error> {
384 unsafe {
385 Error::check_code(
386 sys::argon2_verify(
387 encoded.as_ptr() as _,
388 opt_slice_ptr(&pwd) as _,
389 opt_slice_len(&pwd),
390 variant.to_c() as _,
391 )
392 )
393 }
394}
395
396pub fn d_verify_ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C, hash: &[u8]) -> Result<(), Error> {
404
405 let mut argon_context = context.try_into()?;
406 if hash.len() as u32 != argon_context.outlen {
407 return Err(Error::BadParam("hash.len"))
408 }
409
410 unsafe {
411 Error::check_code(
412 sys::argon2d_verify_ctx(
413 &mut argon_context,
414 hash.as_ptr() as _,
415 )
416 )
417 }
418}
419
420pub fn i_verify_ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C, hash: &[u8]) -> Result<(), Error> {
428
429 let mut argon_context = context.try_into()?;
430 if hash.len() as u32 != argon_context.outlen {
431 return Err(Error::BadParam("hash.len"))
432 }
433
434 unsafe {
435 Error::check_code(
436 sys::argon2i_verify_ctx(
437 &mut argon_context,
438 hash.as_ptr() as _,
439 )
440 )
441 }
442}
443
444pub fn id_verify_ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C, hash: &[u8]) -> Result<(), Error> {
452
453 let mut argon_context = context.try_into()?;
454 if hash.len() as u32 != argon_context.outlen {
455 return Err(Error::BadParam("hash.len"))
456 }
457
458 unsafe {
459 Error::check_code(
460 sys::argon2id_verify_ctx(
461 &mut argon_context,
462 hash.as_ptr() as _,
463 )
464 )
465 }
466}
467
468pub fn verify_ctx<C: TryInto<sys::Argon2_Context, Error = self::Error>>(context: C, hash: &[u8], variant: Variant) -> Result<(), Error> {
476
477 let mut argon_context = context.try_into()?;
478 if hash.len() as u32 != argon_context.outlen {
479 return Err(Error::BadParam("hash.len"))
480 }
481
482 unsafe {
483 Error::check_code(
484 sys::argon2_verify_ctx(
485 &mut argon_context,
486 hash.as_ptr() as _,
487 variant.to_c() as _,
488 )
489 )
490 }
491}
492
493pub fn error_message(code: ErrorCode) -> &'static str {
495 unsafe {
496 let str_ptr = sys::argon2_error_message(code.to_c());
497 if str_ptr.is_null() {
498 "UNKNOWN_ERROR_CODE"
499 } else {
500 let str_cstr = CStr::from_ptr(str_ptr);
501 str_cstr.to_str().expect("Variant name is not valid UTF-8")
502 }
503 }
504}
505
506pub fn encodedlen(
520 t_cost: u32,
521 m_cost: u32,
522 parallelism: u32,
523 saltlen: u32,
524 hashlen: u32,
525 variant: Variant) -> usize {
526 unsafe {
527 sys::argon2_encodedlen(t_cost, m_cost, parallelism, saltlen, hashlen, variant.to_c() as _)
528 }
529}
530
531pub fn c_str(bytes: &[u8]) -> Result<&CStr, Error> {
536 for (idx, b) in bytes.iter().enumerate() {
537 if *b == 0 {
538 return Ok(CStr::from_bytes_with_nul(&bytes[0..(idx + 1)]).expect("Failed CStr conversion."));
539 }
540 }
541 Err(Error::BadParam("bytes"))
542}
543
544pub fn c_str_cow<'a>(bytes: &'a [u8]) -> std::borrow::Cow<'a, CStr> {
548 for (idx, b) in bytes.iter().enumerate() {
549 if *b == 0 {
550 return std::borrow::Cow::Borrowed(
551 CStr::from_bytes_with_nul(&bytes[0..(idx + 1)])
552 .expect("Failed CStr conversion.")
553 );
554 }
555 }
556
557 std::borrow::Cow::Owned(
558 std::ffi::CString::new(bytes).expect("Failed to create CString.")
559 )
560}
561
562#[cfg(test)]
563mod test {
564 use super::*;
565
566 #[test]
568 fn test_variant_names() {
569 assert_eq!("argon2i", type2string(Variant::I, false));
570 assert_eq!("Argon2i", type2string(Variant::I, true));
571 assert_eq!("argon2d", type2string(Variant::D, false));
572 assert_eq!("Argon2d", type2string(Variant::D, true));
573 assert_eq!("argon2id", type2string(Variant::ID, false));
574 assert_eq!("Argon2id", type2string(Variant::ID, true));
575 }
576
577 fn hex_conv(bytes: &[u8], hex_dest: &mut [u8]) {
578 const DIGITS: &[u8] = b"0123456789abcdef";
579 for (idx, byte) in bytes.iter().enumerate() {
580 hex_dest[(idx * 2)] = DIGITS[((*byte >> 4) as usize) & 0xF];
581 hex_dest[(idx * 2) + 1] = DIGITS[(*byte as usize) & 0xF];
582 }
583 }
584
585 fn str_conv(bytes: &[u8]) -> &str {
586 std::str::from_utf8(bytes).expect("Bad UTF-8 conversion.")
587 }
588
589 fn tovec(a: &[u8]) -> Vec<u8> {
590 let mut v = Vec::with_capacity(a.len());
591 v.extend_from_slice(a);
592 return v
593 }
594
595 fn hashtest_bytes(version: Version, t: u32, m: u32, p: u32, pwd: &mut [u8], salt: &mut [u8], hexref: &mut [u8], mcfref: &mut [u8], variant: Variant) {
596 const OUTLEN: usize = 32;
597 const ENCODED_LEN: usize = 108;
598
599 let mut out = [0u8; OUTLEN];
600 let mut hex_out = [0u8; OUTLEN * 2 + 4];
601 let mut encoded = [0u8; ENCODED_LEN];
602
603 println!("HASH TEST: $v={:?} t={}, m={}, p = {}, pass={}, salt={}",
604 version, t, m, p,
605 unsafe { std::str::from_utf8_unchecked(pwd) },
606 unsafe { std::str::from_utf8_unchecked(salt) },);
607
608 hash(t, 1<<m, p, Some(pwd), Some(salt), Some(&mut out), Some(&mut encoded), variant, version).expect("Test hash failed.");
609 hex_conv(&out, &mut hex_out);
610
611 assert_eq!(str_conv(hexref), str_conv(&hex_out[0..(OUTLEN * 2)]));
612
613 verify(
614 c_str(&encoded).expect("bad C string."), Some(pwd), variant
615 ).expect("Failed verify-1");
616
617 verify(
618 &c_str_cow(&mcfref), Some(pwd), variant
619 ).expect("Failed verify-1");
620 }
621
622 fn hashtest(version: Version, t: u32, m: u32, p: u32, pwd: &str, salt: &str, hexref: &str, mcfref: &str, variant: Variant) {
623 hashtest_bytes(
624 version, t, m, p,
625 &mut tovec(pwd.as_bytes()),
626 &mut tovec(salt.as_bytes()),
627 &mut tovec(hexref.as_bytes()),
628 &mut tovec(mcfref.as_bytes()),
629 variant);
630 }
631
632 macro_rules! check_error_code {
633 ($Code:ident, $Value:expr) => {
634 assert_eq!(Err(Error::Code(ErrorCode::$Code)), $Value)
635 }
636 }
637
638 #[test]
639 fn test_argon2i_0x10() {
640 println!("Test Argon2i version number: 0x{:02X}", (Version::Version10).to_int());
641 hashtest(Version::Version10, 2, 16, 1, "password", "somesalt",
642 "f6c4db4a54e2a370627aff3db6176b94a2a209a62c8e36152711802f7b30c694",
643 "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ",
644 Variant::I);
645 hashtest(Version::Version10, 2, 18, 1, "password", "somesalt",
646 "3e689aaa3d28a77cf2bc72a51ac53166761751182f1ee292e3f677a7da4c2467",
647 "$argon2i$m=262144,t=2,p=1$c29tZXNhbHQ$Pmiaqj0op3zyvHKlGsUxZnYXURgvHuKS4/Z3p9pMJGc",
648 Variant::I);
649 hashtest(Version::Version10, 2, 8, 1, "password", "somesalt",
650 "fd4dd83d762c49bdeaf57c47bdcd0c2f1babf863fdeb490df63ede9975fccf06",
651 "$argon2i$m=256,t=2,p=1$c29tZXNhbHQ$/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY",
652 Variant::I);
653 hashtest(Version::Version10, 2, 8, 2, "password", "somesalt",
654 "b6c11560a6a9d61eac706b79a2f97d68b4463aa3ad87e00c07e2b01e90c564fb",
655 "$argon2i$m=256,t=2,p=2$c29tZXNhbHQ$tsEVYKap1h6scGt5ovl9aLRGOqOth+AMB+KwHpDFZPs",
656 Variant::I);
657 hashtest(Version::Version10, 1, 16, 1, "password", "somesalt",
658 "81630552b8f3b1f48cdb1992c4c678643d490b2b5eb4ff6c4b3438b5621724b2",
659 "$argon2i$m=65536,t=1,p=1$c29tZXNhbHQ$gWMFUrjzsfSM2xmSxMZ4ZD1JCytetP9sSzQ4tWIXJLI",
660 Variant::I);
661 hashtest(Version::Version10, 4, 16, 1, "password", "somesalt",
662 "f212f01615e6eb5d74734dc3ef40ade2d51d052468d8c69440a3a1f2c1c2847b",
663 "$argon2i$m=65536,t=4,p=1$c29tZXNhbHQ$8hLwFhXm6110c03D70Ct4tUdBSRo2MaUQKOh8sHChHs",
664 Variant::I);
665 hashtest(Version::Version10, 2, 16, 1, "differentpassword", "somesalt",
666 "e9c902074b6754531a3a0be519e5baf404b30ce69b3f01ac3bf21229960109a3",
667 "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ$6ckCB0tnVFMaOgvlGeW69ASzDOabPwGsO/ISKZYBCaM",
668 Variant::I);
669 hashtest(Version::Version10, 2, 16, 1, "password", "diffsalt",
670 "79a103b90fe8aef8570cb31fc8b22259778916f8336b7bdac3892569d4f1c497",
671 "$argon2i$m=65536,t=2,p=1$ZGlmZnNhbHQ$eaEDuQ/orvhXDLMfyLIiWXeJFvgza3vaw4kladTxxJc",
672 Variant::I);
673 }
674
675 #[test]
676 #[ignore]
677 fn test_argon2i_0x10_large_ram() {
678 hashtest(Version::Version10, 2, 20, 1, "password", "somesalt",
679 "9690ec55d28d3ed32562f2e73ea62b02b018757643a2ae6e79528459de8106e9",
680 "$argon2i$m=1048576,t=2,p=1$c29tZXNhbHQ$lpDsVdKNPtMlYvLnPqYrArAYdXZDoq5ueVKEWd6BBuk",
681 Variant::I);
682 }
683
684 #[test]
685 fn test_argon2i_0x10_errors() {
686 check_error_code!(DecodingFail, verify(&c_str_cow(b"$argon2i$m=65536,t=2,p=1c29tZXNhbHQ$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"),
688 Some(b"password"), Variant::I));
689
690 check_error_code!(DecodingFail, verify(&c_str_cow(b"$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"),
692 Some(b"password"), Variant::I));
693
694 check_error_code!(SaltTooShort, verify(&c_str_cow(b"$argon2i$m=65536,t=2,p=1$$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"),
696 Some(b"password"), Variant::I));
697
698 check_error_code!(VerifyMismatch, verify(&c_str_cow(b"$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ$b2G3seW+uPzerwQQC+/E1K50CLLO7YXy0JRcaTuswRo"),
700 Some(b"password"), Variant::I));
701 }
702
703 #[test]
704 fn test_argon2i_0x13() {
705 println!("Test Argon2i version number: 0x{:02X}", (Version::Version13).to_int());
706
707 hashtest(Version::Version13, 2, 16, 1, "password", "somesalt",
708 "c1628832147d9720c5bd1cfd61367078729f6dfb6f8fea9ff98158e0d7816ed0",
709 "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA",
710 Variant::I);
711 hashtest(Version::Version13, 2, 18, 1, "password", "somesalt",
712 "296dbae80b807cdceaad44ae741b506f14db0959267b183b118f9b24229bc7cb",
713 "$argon2i$v=19$m=262144,t=2,p=1$c29tZXNhbHQ$KW266AuAfNzqrUSudBtQbxTbCVkmexg7EY+bJCKbx8s",
714 Variant::I);
715 hashtest(Version::Version13, 2, 8, 1, "password", "somesalt",
716 "89e9029f4637b295beb027056a7336c414fadd43f6b208645281cb214a56452f",
717 "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ$iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8",
718 Variant::I);
719 hashtest(Version::Version13, 2, 8, 2, "password", "somesalt",
720 "4ff5ce2769a1d7f4c8a491df09d41a9fbe90e5eb02155a13e4c01e20cd4eab61",
721 "$argon2i$v=19$m=256,t=2,p=2$c29tZXNhbHQ$T/XOJ2mh1/TIpJHfCdQan76Q5esCFVoT5MAeIM1Oq2E",
722 Variant::I);
723 hashtest(Version::Version13, 1, 16, 1, "password", "somesalt",
724 "d168075c4d985e13ebeae560cf8b94c3b5d8a16c51916b6f4ac2da3ac11bbecf",
725 "$argon2i$v=19$m=65536,t=1,p=1$c29tZXNhbHQ$0WgHXE2YXhPr6uVgz4uUw7XYoWxRkWtvSsLaOsEbvs8",
726 Variant::I);
727 hashtest(Version::Version13, 4, 16, 1, "password", "somesalt",
728 "aaa953d58af3706ce3df1aefd4a64a84e31d7f54175231f1285259f88174ce5b",
729 "$argon2i$v=19$m=65536,t=4,p=1$c29tZXNhbHQ$qqlT1YrzcGzj3xrv1KZKhOMdf1QXUjHxKFJZ+IF0zls",
730 Variant::I);
731 hashtest(Version::Version13, 2, 16, 1, "differentpassword", "somesalt",
732 "14ae8da01afea8700c2358dcef7c5358d9021282bd88663a4562f59fb74d22ee",
733 "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$FK6NoBr+qHAMI1jc73xTWNkCEoK9iGY6RWL1n7dNIu4",
734 Variant::I);
735 hashtest(Version::Version13, 2, 16, 1, "password", "diffsalt",
736 "b0357cccfbef91f3860b0dba447b2348cbefecadaf990abfe9cc40726c521271",
737 "$argon2i$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ$sDV8zPvvkfOGCw26RHsjSMvv7K2vmQq/6cxAcmxSEnE",
738 Variant::I);
739 }
740
741 #[test]
742 #[ignore]
743 pub fn test_argon2i_0x13_large_ram() {
744 hashtest(Version::Version13, 2, 20, 1, "password", "somesalt",
745 "d1587aca0922c3b5d6a83edab31bee3c4ebaef342ed6127a55d19b2351ad1f41",
746 "$argon2i$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ$0Vh6ygkiw7XWqD7asxvuPE667zQu1hJ6VdGbI1GtH0E",
747 Variant::I);
748 }
749
750 #[test]
751 fn test_argon2i_0x13_errors() {
752 check_error_code!(DecodingFail, verify(
754 &c_str_cow(b"$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQwWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA"),
755 Some(b"password"), Variant::I));
756
757 check_error_code!(DecodingFail, verify(
759 &c_str_cow(b"$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQwWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA"),
760 Some(b"password"), Variant::I));
761
762 check_error_code!(SaltTooShort, verify(
764 &c_str_cow(b"$argon2i$v=19$m=65536,t=2,p=1$$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ"),
765 Some(b"password"), Variant::I));
766
767 check_error_code!(VerifyMismatch, verify(
769 &c_str_cow(b"$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$8iIuixkI73Js3G1uMbezQXD0b8LG4SXGsOwoQkdAQIM"),
770 Some(b"password"), Variant::I));
771 }
772
773 #[test]
774 fn test_argon2id_0x13() {
775 println!("Test Argon2id version number: 0x{:02X}", (Version::Version13).to_int());
776
777 hashtest(Version::Version13, 2, 16, 1, "password", "somesalt",
778 "09316115d5cf24ed5a15a31a3ba326e5cf32edc24702987c02b6566f61913cf7",
779 "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$CTFhFdXPJO1aFaMaO6Mm5c8y7cJHAph8ArZWb2GRPPc", Variant::ID);
780 hashtest(Version::Version13, 2, 18, 1, "password", "somesalt",
781 "78fe1ec91fb3aa5657d72e710854e4c3d9b9198c742f9616c2f085bed95b2e8c",
782 "$argon2id$v=19$m=262144,t=2,p=1$c29tZXNhbHQ$eP4eyR+zqlZX1y5xCFTkw9m5GYx0L5YWwvCFvtlbLow", Variant::ID);
783 hashtest(Version::Version13, 2, 8, 1, "password", "somesalt",
784 "9dfeb910e80bad0311fee20f9c0e2b12c17987b4cac90c2ef54d5b3021c68bfe",
785 "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", Variant::ID);
786 hashtest(Version::Version13, 2, 8, 2, "password", "somesalt",
787 "6d093c501fd5999645e0ea3bf620d7b8be7fd2db59c20d9fff9539da2bf57037",
788 "$argon2id$v=19$m=256,t=2,p=2$c29tZXNhbHQ$bQk8UB/VmZZF4Oo79iDXuL5/0ttZwg2f/5U52iv1cDc", Variant::ID);
789 hashtest(Version::Version13, 1, 16, 1, "password", "somesalt",
790 "f6a5adc1ba723dddef9b5ac1d464e180fcd9dffc9d1cbf76cca2fed795d9ca98",
791 "$argon2id$v=19$m=65536,t=1,p=1$c29tZXNhbHQ$9qWtwbpyPd3vm1rB1GThgPzZ3/ydHL92zKL+15XZypg", Variant::ID);
792 hashtest(Version::Version13, 4, 16, 1, "password", "somesalt",
793 "9025d48e68ef7395cca9079da4c4ec3affb3c8911fe4f86d1a2520856f63172c",
794 "$argon2id$v=19$m=65536,t=4,p=1$c29tZXNhbHQ$kCXUjmjvc5XMqQedpMTsOv+zyJEf5PhtGiUghW9jFyw", Variant::ID);
795 hashtest(Version::Version13, 2, 16, 1, "differentpassword", "somesalt",
796 "0b84d652cf6b0c4beaef0dfe278ba6a80df6696281d7e0d2891b817d8c458fde",
797 "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ$C4TWUs9rDEvq7w3+J4umqA32aWKB1+DSiRuBfYxFj94", Variant::ID);
798 hashtest(Version::Version13, 2, 16, 1, "password", "diffsalt",
799 "bdf32b05ccc42eb15d58fd19b1f856b113da1e9a5874fdcc544308565aa8141c",
800 "$argon2id$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ$vfMrBczELrFdWP0ZsfhWsRPaHppYdP3MVEMIVlqoFBw", Variant::ID);
801 }
802
803 #[test]
804 fn test_common_error_states() {
805 const OUTLEN: usize = 32;
806 let mut out = [0u8; OUTLEN];
807
808 check_error_code!(MemoryTooLittle, hash(2, 1, 1,
809 Some(b"password"), Some(b"diffsalt"),
810 Some(&mut out), None,
811 Variant::ID, Version::Version13));
812 check_error_code!(SaltTooShort, hash(2, 1 << 12, 1,
813 Some(b"password"), Some(b"s"),
814 Some(&mut out), None,
815 Variant::ID, Version::Version13));
816
817 }
831}