const K256: [u32; 64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
];
const SHA256_IV: [u32; 8] = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
];
pub fn sha256(data: &[u8]) -> [u8; 32] {
let mut state = SHA256_IV;
let total_len = data.len();
let mut offset = 0;
while offset + 64 <= data.len() {
sha256_process_block(&mut state, &data[offset..offset + 64]);
offset += 64;
}
let remaining = &data[offset..];
let mut last_block = [0u8; 128]; let rem_len = remaining.len();
last_block[..rem_len].copy_from_slice(remaining);
last_block[rem_len] = 0x80;
let bit_len = (total_len as u64) * 8;
if rem_len + 1 + 8 <= 64 {
last_block[56..64].copy_from_slice(&bit_len.to_be_bytes());
sha256_process_block(&mut state, &last_block[..64]);
} else {
last_block[120..128].copy_from_slice(&bit_len.to_be_bytes());
sha256_process_block(&mut state, &last_block[..64]);
sha256_process_block(&mut state, &last_block[64..128]);
}
let mut output = [0u8; 32];
for (i, word) in state.iter().enumerate() {
output[i * 4..(i + 1) * 4].copy_from_slice(&word.to_be_bytes());
}
output
}
fn sha256_process_block(state: &mut [u32; 8], block: &[u8]) {
let mut w = [0u32; 64];
for i in 0..16 {
w[i] = u32::from_be_bytes([
block[i * 4],
block[i * 4 + 1],
block[i * 4 + 2],
block[i * 4 + 3],
]);
}
for i in 16..64 {
let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
w[i] = s0
.wrapping_add(w[i - 7])
.wrapping_add(s1)
.wrapping_add(w[i - 16]);
}
let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = *state;
for i in 0..64 {
let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
let ch = (e & f) ^ (!e & g);
let temp1 = h
.wrapping_add(s1)
.wrapping_add(ch)
.wrapping_add(K256[i])
.wrapping_add(w[i]);
let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
let maj = (a & b) ^ (a & c) ^ (b & c);
let temp2 = s0.wrapping_add(maj);
h = g;
g = f;
f = e;
e = d.wrapping_add(temp1);
d = c;
c = b;
b = a;
a = temp1.wrapping_add(temp2);
}
state[0] = state[0].wrapping_add(a);
state[1] = state[1].wrapping_add(b);
state[2] = state[2].wrapping_add(c);
state[3] = state[3].wrapping_add(d);
state[4] = state[4].wrapping_add(e);
state[5] = state[5].wrapping_add(f);
state[6] = state[6].wrapping_add(g);
state[7] = state[7].wrapping_add(h);
}
pub fn sha256d(data: &[u8]) -> [u8; 32] {
sha256(&sha256(data))
}
pub fn hash256(data: &[u8]) -> [u8; 32] {
sha256d(data)
}
const K512: [u64; 80] = [
0x428a2f98d728ae22,
0x7137449123ef65cd,
0xb5c0fbcfec4d3b2f,
0xe9b5dba58189dbbc,
0x3956c25bf348b538,
0x59f111f1b605d019,
0x923f82a4af194f9b,
0xab1c5ed5da6d8118,
0xd807aa98a3030242,
0x12835b0145706fbe,
0x243185be4ee4b28c,
0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f,
0x80deb1fe3b1696b1,
0x9bdc06a725c71235,
0xc19bf174cf692694,
0xe49b69c19ef14ad2,
0xefbe4786384f25e3,
0x0fc19dc68b8cd5b5,
0x240ca1cc77ac9c65,
0x2de92c6f592b0275,
0x4a7484aa6ea6e483,
0x5cb0a9dcbd41fbd4,
0x76f988da831153b5,
0x983e5152ee66dfab,
0xa831c66d2db43210,
0xb00327c898fb213f,
0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2,
0xd5a79147930aa725,
0x06ca6351e003826f,
0x142929670a0e6e70,
0x27b70a8546d22ffc,
0x2e1b21385c26c926,
0x4d2c6dfc5ac42aed,
0x53380d139d95b3df,
0x650a73548baf63de,
0x766a0abb3c77b2a8,
0x81c2c92e47edaee6,
0x92722c851482353b,
0xa2bfe8a14cf10364,
0xa81a664bbc423001,
0xc24b8b70d0f89791,
0xc76c51a30654be30,
0xd192e819d6ef5218,
0xd69906245565a910,
0xf40e35855771202a,
0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8,
0x1e376c085141ab53,
0x2748774cdf8eeb99,
0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63,
0x4ed8aa4ae3418acb,
0x5b9cca4f7763e373,
0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc,
0x78a5636f43172f60,
0x84c87814a1f0ab72,
0x8cc702081a6439ec,
0x90befffa23631e28,
0xa4506cebde82bde9,
0xbef9a3f7b2c67915,
0xc67178f2e372532b,
0xca273eceea26619c,
0xd186b8c721c0c207,
0xeada7dd6cde0eb1e,
0xf57d4f7fee6ed178,
0x06f067aa72176fba,
0x0a637dc5a2c898a6,
0x113f9804bef90dae,
0x1b710b35131c471b,
0x28db77f523047d84,
0x32caab7b40c72493,
0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c,
0x4cc5d4becb3e42b6,
0x597f299cfc657e2a,
0x5fcb6fab3ad6faec,
0x6c44198c4a475817,
];
const SHA512_IV: [u64; 8] = [
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179,
];
pub fn sha512(data: &[u8]) -> [u8; 64] {
let mut state = SHA512_IV;
let total_len = data.len();
let mut offset = 0;
while offset + 128 <= data.len() {
sha512_process_block(&mut state, &data[offset..offset + 128]);
offset += 128;
}
let remaining = &data[offset..];
let mut last_block = [0u8; 256]; let rem_len = remaining.len();
last_block[..rem_len].copy_from_slice(remaining);
last_block[rem_len] = 0x80;
let bit_len = (total_len as u128) * 8;
if rem_len + 1 + 16 <= 128 {
last_block[112..128].copy_from_slice(&bit_len.to_be_bytes());
sha512_process_block(&mut state, &last_block[..128]);
} else {
last_block[240..256].copy_from_slice(&bit_len.to_be_bytes());
sha512_process_block(&mut state, &last_block[..128]);
sha512_process_block(&mut state, &last_block[128..256]);
}
let mut output = [0u8; 64];
for (i, word) in state.iter().enumerate() {
output[i * 8..(i + 1) * 8].copy_from_slice(&word.to_be_bytes());
}
output
}
fn sha512_process_block(state: &mut [u64; 8], block: &[u8]) {
let mut w = [0u64; 80];
for i in 0..16 {
w[i] = u64::from_be_bytes([
block[i * 8],
block[i * 8 + 1],
block[i * 8 + 2],
block[i * 8 + 3],
block[i * 8 + 4],
block[i * 8 + 5],
block[i * 8 + 6],
block[i * 8 + 7],
]);
}
for i in 16..80 {
let s0 = w[i - 15].rotate_right(1) ^ w[i - 15].rotate_right(8) ^ (w[i - 15] >> 7);
let s1 = w[i - 2].rotate_right(19) ^ w[i - 2].rotate_right(61) ^ (w[i - 2] >> 6);
w[i] = s0
.wrapping_add(w[i - 7])
.wrapping_add(s1)
.wrapping_add(w[i - 16]);
}
let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = *state;
for i in 0..80 {
let s1 = e.rotate_right(14) ^ e.rotate_right(18) ^ e.rotate_right(41);
let ch = (e & f) ^ (!e & g);
let temp1 = h
.wrapping_add(s1)
.wrapping_add(ch)
.wrapping_add(K512[i])
.wrapping_add(w[i]);
let s0 = a.rotate_right(28) ^ a.rotate_right(34) ^ a.rotate_right(39);
let maj = (a & b) ^ (a & c) ^ (b & c);
let temp2 = s0.wrapping_add(maj);
h = g;
g = f;
f = e;
e = d.wrapping_add(temp1);
d = c;
c = b;
b = a;
a = temp1.wrapping_add(temp2);
}
state[0] = state[0].wrapping_add(a);
state[1] = state[1].wrapping_add(b);
state[2] = state[2].wrapping_add(c);
state[3] = state[3].wrapping_add(d);
state[4] = state[4].wrapping_add(e);
state[5] = state[5].wrapping_add(f);
state[6] = state[6].wrapping_add(g);
state[7] = state[7].wrapping_add(h);
}
const RIPEMD160_IV: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
const RIPEMD160_R: [usize; 80] = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5,
2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4,
13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13,
];
const RIPEMD160_RH: [usize; 80] = [
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12,
4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5,
12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11,
];
const RIPEMD160_S: [u32; 80] = [
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15,
9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14,
15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6,
];
const RIPEMD160_SH: [u32; 80] = [
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12,
7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14,
6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11,
];
fn ripemd160_f(j: usize, x: u32, y: u32, z: u32) -> u32 {
if j <= 15 {
x ^ y ^ z
} else if j <= 31 {
(x & y) | (!x & z)
} else if j <= 47 {
(x | !y) ^ z
} else if j <= 63 {
(x & z) | (y & !z)
} else {
x ^ (y | !z)
}
}
fn ripemd160_k(j: usize) -> u32 {
if j <= 15 {
0x00000000
} else if j <= 31 {
0x5a827999
} else if j <= 47 {
0x6ed9eba1
} else if j <= 63 {
0x8f1bbcdc
} else {
0xa953fd4e
}
}
fn ripemd160_kh(j: usize) -> u32 {
if j <= 15 {
0x50a28be6
} else if j <= 31 {
0x5c4dd124
} else if j <= 47 {
0x6d703ef3
} else if j <= 63 {
0x7a6d76e9
} else {
0x00000000
}
}
pub fn ripemd160(data: &[u8]) -> [u8; 20] {
let mut state = RIPEMD160_IV;
let total_len = data.len();
let mut offset = 0;
while offset + 64 <= data.len() {
ripemd160_process_block(&mut state, &data[offset..offset + 64]);
offset += 64;
}
let remaining = &data[offset..];
let mut last_block = [0u8; 128];
let rem_len = remaining.len();
last_block[..rem_len].copy_from_slice(remaining);
last_block[rem_len] = 0x80;
let bit_len = (total_len as u64) * 8;
if rem_len + 1 + 8 <= 64 {
last_block[56..64].copy_from_slice(&bit_len.to_le_bytes());
ripemd160_process_block(&mut state, &last_block[..64]);
} else {
last_block[120..128].copy_from_slice(&bit_len.to_le_bytes());
ripemd160_process_block(&mut state, &last_block[..64]);
ripemd160_process_block(&mut state, &last_block[64..128]);
}
let mut output = [0u8; 20];
for (i, word) in state.iter().enumerate() {
output[i * 4..(i + 1) * 4].copy_from_slice(&word.to_le_bytes());
}
output
}
fn ripemd160_process_block(state: &mut [u32; 5], block: &[u8]) {
let mut x = [0u32; 16];
for i in 0..16 {
x[i] = u32::from_le_bytes([
block[i * 4],
block[i * 4 + 1],
block[i * 4 + 2],
block[i * 4 + 3],
]);
}
let mut al = state[0];
let mut bl = state[1];
let mut cl = state[2];
let mut dl = state[3];
let mut el = state[4];
let mut ar = al;
let mut br = bl;
let mut cr = cl;
let mut dr = dl;
let mut er = el;
for j in 0..80 {
let t = al
.wrapping_add(ripemd160_f(j, bl, cl, dl))
.wrapping_add(x[RIPEMD160_R[j]])
.wrapping_add(ripemd160_k(j))
.rotate_left(RIPEMD160_S[j])
.wrapping_add(el);
al = el;
el = dl;
dl = cl.rotate_left(10);
cl = bl;
bl = t;
let t = ar
.wrapping_add(ripemd160_f(79 - j, br, cr, dr))
.wrapping_add(x[RIPEMD160_RH[j]])
.wrapping_add(ripemd160_kh(j))
.rotate_left(RIPEMD160_SH[j])
.wrapping_add(er);
ar = er;
er = dr;
dr = cr.rotate_left(10);
cr = br;
br = t;
}
let t = state[1].wrapping_add(cl).wrapping_add(dr);
state[1] = state[2].wrapping_add(dl).wrapping_add(er);
state[2] = state[3].wrapping_add(el).wrapping_add(ar);
state[3] = state[4].wrapping_add(al).wrapping_add(br);
state[4] = state[0].wrapping_add(bl).wrapping_add(cr);
state[0] = t;
}
pub fn hash160(data: &[u8]) -> [u8; 20] {
ripemd160(&sha256(data))
}
fn hmac<const BLOCK_SIZE: usize, const OUT_SIZE: usize>(
key: &[u8],
data: &[u8],
hash_fn: fn(&[u8]) -> [u8; OUT_SIZE],
) -> [u8; OUT_SIZE] {
let mut key_block = [0u8; BLOCK_SIZE];
if key.len() > BLOCK_SIZE {
let hashed_key = hash_fn(key);
key_block[..OUT_SIZE].copy_from_slice(&hashed_key);
} else {
key_block[..key.len()].copy_from_slice(key);
}
let mut i_key_pad = [0u8; BLOCK_SIZE];
for i in 0..BLOCK_SIZE {
i_key_pad[i] = key_block[i] ^ 0x36;
}
let mut inner_msg = Vec::with_capacity(BLOCK_SIZE + data.len());
inner_msg.extend_from_slice(&i_key_pad);
inner_msg.extend_from_slice(data);
let inner_hash = hash_fn(&inner_msg);
let mut o_key_pad = [0u8; BLOCK_SIZE];
for i in 0..BLOCK_SIZE {
o_key_pad[i] = key_block[i] ^ 0x5c;
}
let mut outer_msg = Vec::with_capacity(BLOCK_SIZE + OUT_SIZE);
outer_msg.extend_from_slice(&o_key_pad);
outer_msg.extend_from_slice(&inner_hash);
hash_fn(&outer_msg)
}
fn sha256_wrapper(data: &[u8]) -> [u8; 32] {
sha256(data)
}
fn sha512_wrapper(data: &[u8]) -> [u8; 64] {
sha512(data)
}
pub fn sha256_hmac(key: &[u8], data: &[u8]) -> [u8; 32] {
hmac::<64, 32>(key, data, sha256_wrapper)
}
pub fn sha512_hmac(key: &[u8], data: &[u8]) -> [u8; 64] {
hmac::<128, 64>(key, data, sha512_wrapper)
}
pub fn pbkdf2_hmac_sha512(password: &[u8], salt: &[u8], iterations: u32, dk_len: usize) -> Vec<u8> {
let mut dk = Vec::with_capacity(dk_len);
let mut block = 1u32;
while dk.len() < dk_len {
let mut salt_block = Vec::with_capacity(salt.len() + 4);
salt_block.extend_from_slice(salt);
salt_block.extend_from_slice(&block.to_be_bytes());
let mut u = sha512_hmac(password, &salt_block);
let mut t = u;
for _ in 1..iterations {
u = sha512_hmac(password, &u);
for (ti, ui) in t.iter_mut().zip(u.iter()) {
*ti ^= *ui;
}
}
let remaining = dk_len - dk.len();
dk.extend_from_slice(&t[..remaining.min(64)]);
block += 1;
}
dk
}
const SHA1_IV: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
pub fn sha1(data: &[u8]) -> [u8; 20] {
let mut state = SHA1_IV;
let total_len = data.len();
let mut offset = 0;
while offset + 64 <= data.len() {
sha1_process_block(&mut state, &data[offset..offset + 64]);
offset += 64;
}
let remaining = &data[offset..];
let mut last_block = [0u8; 128];
let rem_len = remaining.len();
last_block[..rem_len].copy_from_slice(remaining);
last_block[rem_len] = 0x80;
let bit_len = (total_len as u64) * 8;
if rem_len + 1 + 8 <= 64 {
last_block[56..64].copy_from_slice(&bit_len.to_be_bytes());
sha1_process_block(&mut state, &last_block[..64]);
} else {
last_block[120..128].copy_from_slice(&bit_len.to_be_bytes());
sha1_process_block(&mut state, &last_block[..64]);
sha1_process_block(&mut state, &last_block[64..128]);
}
let mut output = [0u8; 20];
for (i, word) in state.iter().enumerate() {
output[i * 4..(i + 1) * 4].copy_from_slice(&word.to_be_bytes());
}
output
}
fn sha1_process_block(state: &mut [u32; 5], block: &[u8]) {
let mut w = [0u32; 80];
for i in 0..16 {
w[i] = u32::from_be_bytes([
block[i * 4],
block[i * 4 + 1],
block[i * 4 + 2],
block[i * 4 + 3],
]);
}
for i in 16..80 {
w[i] = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]).rotate_left(1);
}
let mut a = state[0];
let mut b = state[1];
let mut c = state[2];
let mut d = state[3];
let mut e = state[4];
for (i, &wi) in w.iter().enumerate() {
let (f, k) = if i <= 19 {
((b & c) | (!b & d), 0x5a827999u32)
} else if i <= 39 {
(b ^ c ^ d, 0x6ed9eba1u32)
} else if i <= 59 {
((b & c) | (b & d) | (c & d), 0x8f1bbcdcu32)
} else {
(b ^ c ^ d, 0xca62c1d6u32)
};
let temp = a
.rotate_left(5)
.wrapping_add(f)
.wrapping_add(e)
.wrapping_add(k)
.wrapping_add(wi);
e = d;
d = c;
c = b.rotate_left(30);
b = a;
a = temp;
}
state[0] = state[0].wrapping_add(a);
state[1] = state[1].wrapping_add(b);
state[2] = state[2].wrapping_add(c);
state[3] = state[3].wrapping_add(d);
state[4] = state[4].wrapping_add(e);
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
fn bytes_to_hex(bytes: &[u8]) -> String {
let mut hex = String::with_capacity(bytes.len() * 2);
for b in bytes {
hex.push_str(&format!("{:02x}", b));
}
hex
}
fn hex_to_bytes(hex: &str) -> Vec<u8> {
(0..hex.len())
.step_by(2)
.map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
.collect()
}
#[derive(Deserialize)]
struct Sha256Vector {
input: String,
expected: String,
#[allow(dead_code)]
source: String,
#[serde(default)]
r#type: Option<String>,
}
#[derive(Deserialize)]
struct Sha512Vector {
input: String,
expected: String,
#[allow(dead_code)]
source: String,
}
#[derive(Deserialize)]
struct Ripemd160Vector {
input: String,
expected: String,
#[allow(dead_code)]
source: String,
}
#[derive(Deserialize)]
struct HmacVector {
key: String,
data: String,
expected: String,
#[allow(dead_code)]
source: String,
#[allow(dead_code)]
test_case: u32,
}
#[test]
fn test_sha256_empty() {
let result = sha256(b"");
assert_eq!(
bytes_to_hex(&result),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
#[test]
fn test_sha256_abc() {
let result = sha256(b"abc");
assert_eq!(
bytes_to_hex(&result),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
);
}
#[test]
fn test_sha256_all_nist_vectors() {
let data = include_str!("../../test-vectors/sha256.json");
let vectors: Vec<Sha256Vector> = serde_json::from_str(data).unwrap();
for (i, v) in vectors.iter().enumerate() {
let is_double = v.r#type.as_deref() == Some("double");
let input = v.input.as_bytes();
let result = if is_double {
sha256d(input)
} else {
sha256(input)
};
assert_eq!(
bytes_to_hex(&result),
v.expected,
"SHA-256 vector {} failed (type={:?})",
i,
v.r#type
);
}
}
#[test]
fn test_sha256_long_input() {
let result = sha256(b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
assert_eq!(
bytes_to_hex(&result),
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
);
}
#[test]
fn test_sha256d_abc() {
let result = sha256d(b"abc");
assert_eq!(
bytes_to_hex(&result),
"4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358"
);
}
#[test]
fn test_hash256_is_sha256d() {
let data = b"test data for hash256";
assert_eq!(hash256(data), sha256d(data));
}
#[test]
fn test_sha512_empty() {
let result = sha512(b"");
assert_eq!(
bytes_to_hex(&result),
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
);
}
#[test]
fn test_sha512_abc() {
let result = sha512(b"abc");
assert_eq!(
bytes_to_hex(&result),
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
);
}
#[test]
fn test_sha512_all_nist_vectors() {
let data = include_str!("../../test-vectors/sha512.json");
let vectors: Vec<Sha512Vector> = serde_json::from_str(data).unwrap();
for (i, v) in vectors.iter().enumerate() {
let result = sha512(v.input.as_bytes());
assert_eq!(
bytes_to_hex(&result),
v.expected,
"SHA-512 vector {} failed",
i
);
}
}
#[test]
fn test_ripemd160_empty() {
let result = ripemd160(b"");
assert_eq!(
bytes_to_hex(&result),
"9c1185a5c5e9fc54612808977ee8f548b2258d31"
);
}
#[test]
fn test_ripemd160_abc() {
let result = ripemd160(b"abc");
assert_eq!(
bytes_to_hex(&result),
"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
);
}
#[test]
fn test_ripemd160_all_spec_vectors() {
let data = include_str!("../../test-vectors/ripemd160.json");
let vectors: Vec<Ripemd160Vector> = serde_json::from_str(data).unwrap();
for (i, v) in vectors.iter().enumerate() {
let result = ripemd160(v.input.as_bytes());
assert_eq!(
bytes_to_hex(&result),
v.expected,
"RIPEMD-160 vector {} failed (input={:?})",
i,
v.input
);
}
}
#[test]
fn test_hash160_is_ripemd160_of_sha256() {
let data = b"test data for hash160";
let expected = ripemd160(&sha256(data));
assert_eq!(hash160(data), expected);
}
#[test]
fn test_hash160_empty() {
let result = hash160(b"");
let sha_first = sha256(b"");
let expected = ripemd160(&sha_first);
assert_eq!(result, expected);
}
#[test]
fn test_hmac_sha256_rfc4231_vectors() {
let data = include_str!("../../test-vectors/hmac_sha256.json");
let vectors: Vec<HmacVector> = serde_json::from_str(data).unwrap();
for v in &vectors {
let key = hex_to_bytes(&v.key);
let msg = hex_to_bytes(&v.data);
let result = sha256_hmac(&key, &msg);
assert_eq!(
bytes_to_hex(&result),
v.expected,
"HMAC-SHA256 test case {} failed",
v.test_case
);
}
}
#[test]
fn test_hmac_sha512_rfc4231_vectors() {
let data = include_str!("../../test-vectors/hmac_sha512.json");
let vectors: Vec<HmacVector> = serde_json::from_str(data).unwrap();
for v in &vectors {
let key = hex_to_bytes(&v.key);
let msg = hex_to_bytes(&v.data);
let result = sha512_hmac(&key, &msg);
assert_eq!(
bytes_to_hex(&result),
v.expected,
"HMAC-SHA512 test case {} failed",
v.test_case
);
}
}
#[test]
fn test_sha1_empty() {
let result = sha1(b"");
assert_eq!(
bytes_to_hex(&result),
"da39a3ee5e6b4b0d3255bfef95601890afd80709"
);
}
#[test]
fn test_sha1_abc() {
let result = sha1(b"abc");
assert_eq!(
bytes_to_hex(&result),
"a9993e364706816aba3e25717850c26c9cd0d89d"
);
}
#[test]
fn test_sha1_longer_input() {
let result = sha1(b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
assert_eq!(
bytes_to_hex(&result),
"84983e441c3bd26ebaae4aa1f95129e5e54670f1"
);
}
#[test]
fn test_sha1_fox() {
let result = sha1(b"The quick brown fox jumps over the lazy dog");
assert_eq!(
bytes_to_hex(&result),
"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"
);
}
#[derive(Deserialize)]
struct Pbkdf2Vector {
password: String,
salt: String,
iterations: u32,
dk_len: usize,
expected: String,
}
#[test]
fn test_pbkdf2_hmac_sha512_vectors() {
let data = include_str!("../../test-vectors/pbkdf2_vectors.json");
let vectors: Vec<Pbkdf2Vector> = serde_json::from_str(data).unwrap();
for (i, v) in vectors.iter().enumerate() {
let password = hex_to_bytes(&v.password);
let salt = hex_to_bytes(&v.salt);
let result = pbkdf2_hmac_sha512(&password, &salt, v.iterations, v.dk_len);
assert_eq!(
bytes_to_hex(&result),
v.expected,
"PBKDF2 vector {} failed (iterations={}, dk_len={})",
i,
v.iterations,
v.dk_len
);
}
}
#[test]
fn test_vector_loading() {
let data = include_str!("../../test-vectors/sha256.json");
let vectors: Vec<Sha256Vector> = serde_json::from_str(data).unwrap();
assert!(
!vectors.is_empty(),
"SHA256 test vectors should not be empty"
);
assert!(vectors.len() >= 4, "Expected at least 4 SHA256 vectors");
}
}