use crypto_bigint::{Uint, U1024, U512};
use crate::conversions;
pub fn string_to_encoding(s: &str) -> Vec<u8> {
s.as_bytes().into()
}
pub fn sha256_preprocessing(s: &str) -> Vec<U512> {
standard_preprocessing::<8, 1>(s)
}
pub fn sha512_preprocessing(s: &str) -> Vec<U1024> {
standard_preprocessing::<16, 2>(s)
}
pub fn standard_preprocessing<const BLOCK: usize, const SUFFIX: usize>(s: &str) -> Vec<Uint<BLOCK>> {
let bytes = string_to_encoding(s);
let l = 8 * bytes.len();
let mut l_vec = [0 as u64; SUFFIX];
l_vec[SUFFIX - 1] = l as u64;
let words = byte_padding(&bytes);
word_padding(&words, l_vec)
}
pub fn custom_preprocessing<const BLOCK: usize, const SUFFIX: usize>(bytes: Vec<u8>, suffix:[u64;SUFFIX]) -> Vec<Uint<BLOCK>> {
let words = byte_padding(&bytes);
word_padding(&words, suffix)
}
pub fn word_padding<const BSIZE: usize, const SUFFIX: usize>(
v: &Vec<u64>,
l: [u64; SUFFIX],
) -> Vec<Uint<BSIZE>> {
let mut blocks = Vec::new();
let mut block = [0u64; BSIZE];
let mut block_index = 0;
if SUFFIX > BSIZE {
panic!(
"Size SUFFIX:{} is larger than block size BSIZE: {}",
SUFFIX, BSIZE
);
}
for word in v.iter() {
block[block_index] = *word;
block_index += 1;
if block_index == BSIZE {
block_index = 0;
blocks.push(conversions::from_u64_words(&mut block));
}
}
let mut i = BSIZE - SUFFIX;
if i < block_index {
blocks.push(conversions::from_u64_words(&mut block));
}
for l_elem in l {
block[i] = l_elem;
i += 1;
}
blocks.push(conversions::from_u64_words(&mut block));
return blocks;
}
pub fn byte_padding(v: &Vec<u8>) -> Vec<u64> {
let mut words = Vec::new();
let mut word = [0; 8];
let mut byte_i = 0;
for u in v.iter() {
word[byte_i] = *u;
byte_i += 1;
if byte_i == 8 {
byte_i = 0;
words.push(bytes_to_u64(word));
word = [0; 8];
}
}
word[byte_i] = 0x80u8;
words.push(bytes_to_u64(word));
return words;
}
pub fn bytes_to_u64(v: [u8; 8]) -> u64 {
let mut res: u64 = 0;
for i in v.iter() {
res = res << 8;
res += *i as u64;
}
res
}