192f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 292f3ab15Sopenharmony_ciuse libc::c_int; 392f3ab15Sopenharmony_ciuse std::convert::TryInto; 492f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 592f3ab15Sopenharmony_ciuse std::ptr; 692f3ab15Sopenharmony_ci 792f3ab15Sopenharmony_ciuse crate::cvt; 892f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 992f3ab15Sopenharmony_ciuse crate::hash::MessageDigest; 1092f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 1192f3ab15Sopenharmony_ciuse crate::symm::Cipher; 1292f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 1392f3ab15Sopenharmony_ci 1492f3ab15Sopenharmony_ci#[derive(Clone, Eq, PartialEq, Hash, Debug)] 1592f3ab15Sopenharmony_cipub struct KeyIvPair { 1692f3ab15Sopenharmony_ci pub key: Vec<u8>, 1792f3ab15Sopenharmony_ci pub iv: Option<Vec<u8>>, 1892f3ab15Sopenharmony_ci} 1992f3ab15Sopenharmony_ci 2092f3ab15Sopenharmony_ci/// Derives a key and an IV from various parameters. 2192f3ab15Sopenharmony_ci/// 2292f3ab15Sopenharmony_ci/// If specified, `salt` must be 8 bytes in length. 2392f3ab15Sopenharmony_ci/// 2492f3ab15Sopenharmony_ci/// If the total key and IV length is less than 16 bytes and MD5 is used then 2592f3ab15Sopenharmony_ci/// the algorithm is compatible with the key derivation algorithm from PKCS#5 2692f3ab15Sopenharmony_ci/// v1.5 or PBKDF1 from PKCS#5 v2.0. 2792f3ab15Sopenharmony_ci/// 2892f3ab15Sopenharmony_ci/// New applications should not use this and instead use 2992f3ab15Sopenharmony_ci/// `pbkdf2_hmac` or another more modern key derivation algorithm. 3092f3ab15Sopenharmony_ci#[corresponds(EVP_BytesToKey)] 3192f3ab15Sopenharmony_ci#[allow(clippy::useless_conversion)] 3292f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 3392f3ab15Sopenharmony_cipub fn bytes_to_key( 3492f3ab15Sopenharmony_ci cipher: Cipher, 3592f3ab15Sopenharmony_ci digest: MessageDigest, 3692f3ab15Sopenharmony_ci data: &[u8], 3792f3ab15Sopenharmony_ci salt: Option<&[u8]>, 3892f3ab15Sopenharmony_ci count: i32, 3992f3ab15Sopenharmony_ci) -> Result<KeyIvPair, ErrorStack> { 4092f3ab15Sopenharmony_ci unsafe { 4192f3ab15Sopenharmony_ci assert!(data.len() <= c_int::max_value() as usize); 4292f3ab15Sopenharmony_ci let salt_ptr = match salt { 4392f3ab15Sopenharmony_ci Some(salt) => { 4492f3ab15Sopenharmony_ci assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize); 4592f3ab15Sopenharmony_ci salt.as_ptr() 4692f3ab15Sopenharmony_ci } 4792f3ab15Sopenharmony_ci None => ptr::null(), 4892f3ab15Sopenharmony_ci }; 4992f3ab15Sopenharmony_ci 5092f3ab15Sopenharmony_ci ffi::init(); 5192f3ab15Sopenharmony_ci 5292f3ab15Sopenharmony_ci let mut iv = cipher.iv_len().map(|l| vec![0; l]); 5392f3ab15Sopenharmony_ci 5492f3ab15Sopenharmony_ci let cipher = cipher.as_ptr(); 5592f3ab15Sopenharmony_ci let digest = digest.as_ptr(); 5692f3ab15Sopenharmony_ci 5792f3ab15Sopenharmony_ci let len = cvt(ffi::EVP_BytesToKey( 5892f3ab15Sopenharmony_ci cipher, 5992f3ab15Sopenharmony_ci digest, 6092f3ab15Sopenharmony_ci salt_ptr, 6192f3ab15Sopenharmony_ci ptr::null(), 6292f3ab15Sopenharmony_ci data.len() as c_int, 6392f3ab15Sopenharmony_ci count.into(), 6492f3ab15Sopenharmony_ci ptr::null_mut(), 6592f3ab15Sopenharmony_ci ptr::null_mut(), 6692f3ab15Sopenharmony_ci ))?; 6792f3ab15Sopenharmony_ci 6892f3ab15Sopenharmony_ci let mut key = vec![0; len as usize]; 6992f3ab15Sopenharmony_ci let iv_ptr = iv 7092f3ab15Sopenharmony_ci .as_mut() 7192f3ab15Sopenharmony_ci .map(|v| v.as_mut_ptr()) 7292f3ab15Sopenharmony_ci .unwrap_or(ptr::null_mut()); 7392f3ab15Sopenharmony_ci 7492f3ab15Sopenharmony_ci cvt(ffi::EVP_BytesToKey( 7592f3ab15Sopenharmony_ci cipher, 7692f3ab15Sopenharmony_ci digest, 7792f3ab15Sopenharmony_ci salt_ptr, 7892f3ab15Sopenharmony_ci data.as_ptr(), 7992f3ab15Sopenharmony_ci data.len() as c_int, 8092f3ab15Sopenharmony_ci count as c_int, 8192f3ab15Sopenharmony_ci key.as_mut_ptr(), 8292f3ab15Sopenharmony_ci iv_ptr, 8392f3ab15Sopenharmony_ci ))?; 8492f3ab15Sopenharmony_ci 8592f3ab15Sopenharmony_ci Ok(KeyIvPair { key, iv }) 8692f3ab15Sopenharmony_ci } 8792f3ab15Sopenharmony_ci} 8892f3ab15Sopenharmony_ci 8992f3ab15Sopenharmony_ci/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function. 9092f3ab15Sopenharmony_ci#[corresponds(PKCS5_PBKDF2_HMAC)] 9192f3ab15Sopenharmony_cipub fn pbkdf2_hmac( 9292f3ab15Sopenharmony_ci pass: &[u8], 9392f3ab15Sopenharmony_ci salt: &[u8], 9492f3ab15Sopenharmony_ci iter: usize, 9592f3ab15Sopenharmony_ci hash: MessageDigest, 9692f3ab15Sopenharmony_ci key: &mut [u8], 9792f3ab15Sopenharmony_ci) -> Result<(), ErrorStack> { 9892f3ab15Sopenharmony_ci unsafe { 9992f3ab15Sopenharmony_ci ffi::init(); 10092f3ab15Sopenharmony_ci cvt(ffi::PKCS5_PBKDF2_HMAC( 10192f3ab15Sopenharmony_ci pass.as_ptr() as *const _, 10292f3ab15Sopenharmony_ci pass.len().try_into().unwrap(), 10392f3ab15Sopenharmony_ci salt.as_ptr(), 10492f3ab15Sopenharmony_ci salt.len().try_into().unwrap(), 10592f3ab15Sopenharmony_ci iter.try_into().unwrap(), 10692f3ab15Sopenharmony_ci hash.as_ptr(), 10792f3ab15Sopenharmony_ci key.len().try_into().unwrap(), 10892f3ab15Sopenharmony_ci key.as_mut_ptr(), 10992f3ab15Sopenharmony_ci )) 11092f3ab15Sopenharmony_ci .map(|_| ()) 11192f3ab15Sopenharmony_ci } 11292f3ab15Sopenharmony_ci} 11392f3ab15Sopenharmony_ci 11492f3ab15Sopenharmony_ci/// Derives a key from a password and salt using the scrypt algorithm. 11592f3ab15Sopenharmony_ci/// 11692f3ab15Sopenharmony_ci/// Requires OpenSSL 1.1.0 or newer. 11792f3ab15Sopenharmony_ci#[corresponds(EVP_PBE_scrypt)] 11892f3ab15Sopenharmony_ci#[cfg(any(ossl110, boringssl))] 11992f3ab15Sopenharmony_ci#[allow(clippy::useless_conversion)] 12092f3ab15Sopenharmony_cipub fn scrypt( 12192f3ab15Sopenharmony_ci pass: &[u8], 12292f3ab15Sopenharmony_ci salt: &[u8], 12392f3ab15Sopenharmony_ci n: u64, 12492f3ab15Sopenharmony_ci r: u64, 12592f3ab15Sopenharmony_ci p: u64, 12692f3ab15Sopenharmony_ci maxmem: u64, 12792f3ab15Sopenharmony_ci key: &mut [u8], 12892f3ab15Sopenharmony_ci) -> Result<(), ErrorStack> { 12992f3ab15Sopenharmony_ci unsafe { 13092f3ab15Sopenharmony_ci ffi::init(); 13192f3ab15Sopenharmony_ci cvt(ffi::EVP_PBE_scrypt( 13292f3ab15Sopenharmony_ci pass.as_ptr() as *const _, 13392f3ab15Sopenharmony_ci pass.len(), 13492f3ab15Sopenharmony_ci salt.as_ptr() as *const _, 13592f3ab15Sopenharmony_ci salt.len(), 13692f3ab15Sopenharmony_ci n, 13792f3ab15Sopenharmony_ci r, 13892f3ab15Sopenharmony_ci p, 13992f3ab15Sopenharmony_ci maxmem.try_into().unwrap(), 14092f3ab15Sopenharmony_ci key.as_mut_ptr() as *mut _, 14192f3ab15Sopenharmony_ci key.len(), 14292f3ab15Sopenharmony_ci )) 14392f3ab15Sopenharmony_ci .map(|_| ()) 14492f3ab15Sopenharmony_ci } 14592f3ab15Sopenharmony_ci} 14692f3ab15Sopenharmony_ci 14792f3ab15Sopenharmony_ci#[cfg(test)] 14892f3ab15Sopenharmony_cimod tests { 14992f3ab15Sopenharmony_ci use crate::hash::MessageDigest; 15092f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 15192f3ab15Sopenharmony_ci use crate::symm::Cipher; 15292f3ab15Sopenharmony_ci 15392f3ab15Sopenharmony_ci // Test vectors from 15492f3ab15Sopenharmony_ci // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c 15592f3ab15Sopenharmony_ci #[test] 15692f3ab15Sopenharmony_ci fn pbkdf2_hmac_sha256() { 15792f3ab15Sopenharmony_ci let mut buf = [0; 16]; 15892f3ab15Sopenharmony_ci 15992f3ab15Sopenharmony_ci super::pbkdf2_hmac(b"passwd", b"salt", 1, MessageDigest::sha256(), &mut buf).unwrap(); 16092f3ab15Sopenharmony_ci assert_eq!( 16192f3ab15Sopenharmony_ci buf, 16292f3ab15Sopenharmony_ci &[ 16392f3ab15Sopenharmony_ci 0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8, 0xec_u8, 16492f3ab15Sopenharmony_ci 0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8, 16592f3ab15Sopenharmony_ci ][..] 16692f3ab15Sopenharmony_ci ); 16792f3ab15Sopenharmony_ci 16892f3ab15Sopenharmony_ci super::pbkdf2_hmac( 16992f3ab15Sopenharmony_ci b"Password", 17092f3ab15Sopenharmony_ci b"NaCl", 17192f3ab15Sopenharmony_ci 80000, 17292f3ab15Sopenharmony_ci MessageDigest::sha256(), 17392f3ab15Sopenharmony_ci &mut buf, 17492f3ab15Sopenharmony_ci ) 17592f3ab15Sopenharmony_ci .unwrap(); 17692f3ab15Sopenharmony_ci assert_eq!( 17792f3ab15Sopenharmony_ci buf, 17892f3ab15Sopenharmony_ci &[ 17992f3ab15Sopenharmony_ci 0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8, 0x83_u8, 18092f3ab15Sopenharmony_ci 0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8, 18192f3ab15Sopenharmony_ci ][..] 18292f3ab15Sopenharmony_ci ); 18392f3ab15Sopenharmony_ci } 18492f3ab15Sopenharmony_ci 18592f3ab15Sopenharmony_ci // Test vectors from 18692f3ab15Sopenharmony_ci // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c 18792f3ab15Sopenharmony_ci #[test] 18892f3ab15Sopenharmony_ci fn pbkdf2_hmac_sha512() { 18992f3ab15Sopenharmony_ci let mut buf = [0; 64]; 19092f3ab15Sopenharmony_ci 19192f3ab15Sopenharmony_ci super::pbkdf2_hmac(b"password", b"NaCL", 1, MessageDigest::sha512(), &mut buf).unwrap(); 19292f3ab15Sopenharmony_ci assert_eq!( 19392f3ab15Sopenharmony_ci &buf[..], 19492f3ab15Sopenharmony_ci &[ 19592f3ab15Sopenharmony_ci 0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8, 0x94_u8, 19692f3ab15Sopenharmony_ci 0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8, 0xd3_u8, 0xc7_u8, 19792f3ab15Sopenharmony_ci 0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8, 0xb3_u8, 0x90_u8, 0xed_u8, 19892f3ab15Sopenharmony_ci 0x78_u8, 0xb3_u8, 0x05_u8, 0x65_u8, 0x6a_u8, 0xf8_u8, 0x14_u8, 0x8e_u8, 0x52_u8, 19992f3ab15Sopenharmony_ci 0x45_u8, 0x2b_u8, 0x22_u8, 0x16_u8, 0xb2_u8, 0xb8_u8, 0x09_u8, 0x8b_u8, 0x76_u8, 20092f3ab15Sopenharmony_ci 0x1f_u8, 0xc6_u8, 0x33_u8, 0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8, 20192f3ab15Sopenharmony_ci 0x5e_u8, 0x9f_u8, 0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8, 20292f3ab15Sopenharmony_ci 0x06_u8, 20392f3ab15Sopenharmony_ci ][..] 20492f3ab15Sopenharmony_ci ); 20592f3ab15Sopenharmony_ci 20692f3ab15Sopenharmony_ci super::pbkdf2_hmac( 20792f3ab15Sopenharmony_ci b"pass\0word", 20892f3ab15Sopenharmony_ci b"sa\0lt", 20992f3ab15Sopenharmony_ci 1, 21092f3ab15Sopenharmony_ci MessageDigest::sha512(), 21192f3ab15Sopenharmony_ci &mut buf, 21292f3ab15Sopenharmony_ci ) 21392f3ab15Sopenharmony_ci .unwrap(); 21492f3ab15Sopenharmony_ci assert_eq!( 21592f3ab15Sopenharmony_ci &buf[..], 21692f3ab15Sopenharmony_ci &[ 21792f3ab15Sopenharmony_ci 0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8, 0x8b_u8, 21892f3ab15Sopenharmony_ci 0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8, 0x2f_u8, 0x93_u8, 21992f3ab15Sopenharmony_ci 0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8, 0x0d_u8, 0x63_u8, 0xb8_u8, 22092f3ab15Sopenharmony_ci 0x83_u8, 0x29_u8, 0x87_u8, 0x10_u8, 0x90_u8, 0xe7_u8, 0x66_u8, 0x04_u8, 0xa4_u8, 22192f3ab15Sopenharmony_ci 0x9a_u8, 0xf0_u8, 0x8f_u8, 0xe7_u8, 0xc9_u8, 0xf5_u8, 0x71_u8, 0x56_u8, 0xc8_u8, 22292f3ab15Sopenharmony_ci 0x79_u8, 0x09_u8, 0x96_u8, 0xb2_u8, 0x0f_u8, 0x06_u8, 0xbc_u8, 0x53_u8, 0x5e_u8, 22392f3ab15Sopenharmony_ci 0x5a_u8, 0xb5_u8, 0x44_u8, 0x0d_u8, 0xf7_u8, 0xe8_u8, 0x78_u8, 0x29_u8, 0x6f_u8, 22492f3ab15Sopenharmony_ci 0xa7_u8, 22592f3ab15Sopenharmony_ci ][..] 22692f3ab15Sopenharmony_ci ); 22792f3ab15Sopenharmony_ci 22892f3ab15Sopenharmony_ci super::pbkdf2_hmac( 22992f3ab15Sopenharmony_ci b"passwordPASSWORDpassword", 23092f3ab15Sopenharmony_ci b"salt\0\0\0", 23192f3ab15Sopenharmony_ci 50, 23292f3ab15Sopenharmony_ci MessageDigest::sha512(), 23392f3ab15Sopenharmony_ci &mut buf, 23492f3ab15Sopenharmony_ci ) 23592f3ab15Sopenharmony_ci .unwrap(); 23692f3ab15Sopenharmony_ci assert_eq!( 23792f3ab15Sopenharmony_ci &buf[..], 23892f3ab15Sopenharmony_ci &[ 23992f3ab15Sopenharmony_ci 0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8, 0x85_u8, 24092f3ab15Sopenharmony_ci 0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8, 0x3b_u8, 0x30_u8, 24192f3ab15Sopenharmony_ci 0xee_u8, 0x2a_u8, 0x39_u8, 0xf5_u8, 0xad_u8, 0xca_u8, 0xc8_u8, 0xc9_u8, 0x37_u8, 24292f3ab15Sopenharmony_ci 0x5f_u8, 0x9b_u8, 0xda_u8, 0x1c_u8, 0xcd_u8, 0x1b_u8, 0x6f_u8, 0x0b_u8, 0x2f_u8, 24392f3ab15Sopenharmony_ci 0xc3_u8, 0xad_u8, 0xda_u8, 0x50_u8, 0x54_u8, 0x12_u8, 0xe7_u8, 0x9d_u8, 0x89_u8, 24492f3ab15Sopenharmony_ci 0x00_u8, 0x56_u8, 0xc6_u8, 0x2e_u8, 0x52_u8, 0x4c_u8, 0x7d_u8, 0x51_u8, 0x15_u8, 24592f3ab15Sopenharmony_ci 0x4b_u8, 0x1a_u8, 0x85_u8, 0x34_u8, 0x57_u8, 0x5b_u8, 0xd0_u8, 0x2d_u8, 0xee_u8, 24692f3ab15Sopenharmony_ci 0x39_u8, 24792f3ab15Sopenharmony_ci ][..] 24892f3ab15Sopenharmony_ci ); 24992f3ab15Sopenharmony_ci } 25092f3ab15Sopenharmony_ci 25192f3ab15Sopenharmony_ci #[test] 25292f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 25392f3ab15Sopenharmony_ci fn bytes_to_key() { 25492f3ab15Sopenharmony_ci let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8]; 25592f3ab15Sopenharmony_ci 25692f3ab15Sopenharmony_ci let data = [ 25792f3ab15Sopenharmony_ci 143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, 154_u8, 25892f3ab15Sopenharmony_ci 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 55_u8, 119_u8, 25992f3ab15Sopenharmony_ci 233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 65_u8, 207_u8, 26092f3ab15Sopenharmony_ci ]; 26192f3ab15Sopenharmony_ci 26292f3ab15Sopenharmony_ci let expected_key = vec![ 26392f3ab15Sopenharmony_ci 249_u8, 115_u8, 114_u8, 97_u8, 32_u8, 213_u8, 165_u8, 146_u8, 58_u8, 87_u8, 234_u8, 26492f3ab15Sopenharmony_ci 3_u8, 43_u8, 250_u8, 97_u8, 114_u8, 26_u8, 98_u8, 245_u8, 246_u8, 238_u8, 177_u8, 26592f3ab15Sopenharmony_ci 229_u8, 161_u8, 183_u8, 224_u8, 174_u8, 3_u8, 6_u8, 244_u8, 236_u8, 255_u8, 26692f3ab15Sopenharmony_ci ]; 26792f3ab15Sopenharmony_ci let expected_iv = vec![ 26892f3ab15Sopenharmony_ci 4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, 98_u8, 26992f3ab15Sopenharmony_ci 107_u8, 208_u8, 14_u8, 236_u8, 60_u8, 27092f3ab15Sopenharmony_ci ]; 27192f3ab15Sopenharmony_ci 27292f3ab15Sopenharmony_ci assert_eq!( 27392f3ab15Sopenharmony_ci super::bytes_to_key( 27492f3ab15Sopenharmony_ci Cipher::aes_256_cbc(), 27592f3ab15Sopenharmony_ci MessageDigest::sha1(), 27692f3ab15Sopenharmony_ci &data, 27792f3ab15Sopenharmony_ci Some(&salt), 27892f3ab15Sopenharmony_ci 1, 27992f3ab15Sopenharmony_ci ) 28092f3ab15Sopenharmony_ci .unwrap(), 28192f3ab15Sopenharmony_ci super::KeyIvPair { 28292f3ab15Sopenharmony_ci key: expected_key, 28392f3ab15Sopenharmony_ci iv: Some(expected_iv), 28492f3ab15Sopenharmony_ci } 28592f3ab15Sopenharmony_ci ); 28692f3ab15Sopenharmony_ci } 28792f3ab15Sopenharmony_ci 28892f3ab15Sopenharmony_ci #[test] 28992f3ab15Sopenharmony_ci #[cfg(any(ossl110, boringssl))] 29092f3ab15Sopenharmony_ci fn scrypt() { 29192f3ab15Sopenharmony_ci let pass = "pleaseletmein"; 29292f3ab15Sopenharmony_ci let salt = "SodiumChloride"; 29392f3ab15Sopenharmony_ci let expected = 29492f3ab15Sopenharmony_ci "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613\ 29592f3ab15Sopenharmony_ci f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887"; 29692f3ab15Sopenharmony_ci 29792f3ab15Sopenharmony_ci let mut actual = [0; 64]; 29892f3ab15Sopenharmony_ci super::scrypt( 29992f3ab15Sopenharmony_ci pass.as_bytes(), 30092f3ab15Sopenharmony_ci salt.as_bytes(), 30192f3ab15Sopenharmony_ci 16384, 30292f3ab15Sopenharmony_ci 8, 30392f3ab15Sopenharmony_ci 1, 30492f3ab15Sopenharmony_ci 0, 30592f3ab15Sopenharmony_ci &mut actual, 30692f3ab15Sopenharmony_ci ) 30792f3ab15Sopenharmony_ci .unwrap(); 30892f3ab15Sopenharmony_ci assert_eq!(hex::encode(&actual[..]), expected); 30992f3ab15Sopenharmony_ci } 31092f3ab15Sopenharmony_ci} 311