feat(alg): impl sha2
This commit is contained in:
parent
11677d8fe0
commit
bb81a7dd49
6 changed files with 371 additions and 38 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -15,8 +15,10 @@ dependencies = [
|
|||
name = "algorithms"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"assert_hex",
|
||||
"criterion",
|
||||
"iai",
|
||||
"pretty_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -28,6 +30,12 @@ dependencies = [
|
|||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_hex"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7010f1430f0fc8ca80bdb5e5d074db68776a2e268ec6cf80b53712d3ea4bca7"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -282,6 +290,12 @@ dependencies = [
|
|||
"defmt 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
|
@ -517,6 +531,16 @@ dependencies = [
|
|||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
|
@ -1002,3 +1026,9 @@ name = "windows_x86_64_msvc"
|
|||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
|
|
@ -6,8 +6,10 @@ edition = "2024"
|
|||
[dependencies]
|
||||
|
||||
[dev-dependencies]
|
||||
assert_hex = "0.4.1"
|
||||
criterion = "0.3"
|
||||
iai = "0.1.1"
|
||||
pretty_assertions = "1.4.1"
|
||||
|
||||
[[bench]]
|
||||
name = "crc32bench"
|
||||
|
@ -16,3 +18,8 @@ harness = false
|
|||
[[bench]]
|
||||
name = "crc32bench_iai"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
default = []
|
||||
std = []
|
||||
show_internals = ["std"]
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
#include <threads.h>
|
||||
|
||||
#ifdef TEST
|
||||
// #define SHOW_INTERNALS
|
||||
|
||||
#define SHOW_INTERNALS
|
||||
#endif // TEST
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
|
@ -48,7 +47,8 @@ static uint32_t addTemp = 0;
|
|||
#define SHA256_ROTL(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits))))
|
||||
#define SHA256_ROTR(bits, word) (((word) >> (bits)) | ((word) << (32 - (bits))))
|
||||
|
||||
/* Define the SHA SIGMA and sigma macros */
|
||||
/* Define the SHA SIGMA and sigma macros, yes these have the same name and are
|
||||
* different */
|
||||
#define SHA256_SIGMA0(word) \
|
||||
(SHA256_ROTR(2, word) ^ SHA256_ROTR(13, word) ^ SHA256_ROTR(22, word))
|
||||
#define SHA256_SIGMA1(word) \
|
||||
|
@ -168,9 +168,7 @@ static void sha2_256_process_message_block(SHA2Context *context) {
|
|||
#ifdef SHOW_INTERNALS
|
||||
TRACE("DONE:\t")
|
||||
dump_alphabet;
|
||||
#endif // SHOW_INTERNALS
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
TRACE("Intermediate hash before we add the working variables:\n");
|
||||
for (int o = 0; o < SHA2_256_HashParts; o++) {
|
||||
TRACE("\t%d:\t%032b\n", o, context->intermediate_hash[o]);
|
||||
|
@ -254,14 +252,7 @@ static void sha2_256_pad_message(SHA2Context *context, uint8_t pad_byte) {
|
|||
}
|
||||
|
||||
static void sha2_256_finalize(SHA2Context *context, uint8_t pad_byte) {
|
||||
size_t i;
|
||||
sha2_256_pad_message(context, pad_byte);
|
||||
/* message may be sensitive, so clear it out */
|
||||
for (i = 0; i < SHA2_256_BlockSize; ++i)
|
||||
context->message_block[i] = 0;
|
||||
context->length_high = 0; /* and clear length */
|
||||
context->length_low = 0;
|
||||
context->computed = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@ use super::super::sha2::{DIGEST256_EMPTY, Digest256, SHA2_256_BLOCK_SIZE};
|
|||
#[allow(unused)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub enum SHA2Result {
|
||||
pub enum SHA2Outcome {
|
||||
shaSuccess = 0,
|
||||
shaNull, /* Null pointer parameter */
|
||||
shaInputTooLong, /* input data too long */
|
||||
|
@ -50,45 +50,48 @@ impl Default for Sha2_256Context {
|
|||
mod ffi {
|
||||
use super::*;
|
||||
unsafe extern "C" {
|
||||
pub fn sha2_256_oneshot(data: *const u8, len: usize, digest: *mut Digest256) -> SHA2Result;
|
||||
pub fn sha2_256_reset(context: *mut Sha2_256Context) -> SHA2Result;
|
||||
pub fn sha2_256_oneshot(data: *const u8, len: usize, digest: *mut Digest256)
|
||||
-> SHA2Outcome;
|
||||
pub fn sha2_256_reset(context: *mut Sha2_256Context) -> SHA2Outcome;
|
||||
pub fn sha2_256_input(
|
||||
context: *mut Sha2_256Context,
|
||||
data: *const u8,
|
||||
len: usize,
|
||||
) -> SHA2Result;
|
||||
pub fn sha2_256_result(context: *mut Sha2_256Context, digest: *mut Digest256)
|
||||
-> SHA2Result;
|
||||
) -> SHA2Outcome;
|
||||
pub fn sha2_256_result(
|
||||
context: *mut Sha2_256Context,
|
||||
digest: *mut Digest256,
|
||||
) -> SHA2Outcome;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Result> {
|
||||
pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Outcome> {
|
||||
let mut digest: Digest256 = DIGEST256_EMPTY;
|
||||
let res =
|
||||
unsafe { ffi::sha2_256_oneshot(ref_to_ptr(data), data.len(), ref_to_ptr_mut(&mut digest)) };
|
||||
to_res(digest, res)
|
||||
}
|
||||
|
||||
pub fn sha2_256_reset(context: &mut Sha2_256Context) -> Result<(), SHA2Result> {
|
||||
pub fn sha2_256_reset(context: &mut Sha2_256Context) -> Result<(), SHA2Outcome> {
|
||||
let res = unsafe { ffi::sha2_256_reset(ref_to_ptr_mut(context)) };
|
||||
to_res((), res)
|
||||
}
|
||||
|
||||
pub fn sha2_256_input(context: &mut Sha2_256Context, data: &[u8]) -> Result<(), SHA2Result> {
|
||||
pub fn sha2_256_input(context: &mut Sha2_256Context, data: &[u8]) -> Result<(), SHA2Outcome> {
|
||||
let res = unsafe { ffi::sha2_256_input(ref_to_ptr_mut(context), ref_to_ptr(data), data.len()) };
|
||||
to_res((), res)
|
||||
}
|
||||
|
||||
pub fn sha2_256_result(context: &mut Sha2_256Context) -> Result<Digest256, SHA2Result> {
|
||||
pub fn sha2_256_result(context: &mut Sha2_256Context) -> Result<Digest256, SHA2Outcome> {
|
||||
let mut digest: Digest256 = DIGEST256_EMPTY;
|
||||
let res = unsafe { ffi::sha2_256_result(ref_to_ptr_mut(context), ref_to_ptr_mut(&mut digest)) };
|
||||
to_res(digest, res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn to_res<T>(if_ok: T, res: SHA2Result) -> Result<T, SHA2Result> {
|
||||
if res == SHA2Result::shaSuccess {
|
||||
pub(crate) fn to_res<T>(if_ok: T, res: SHA2Outcome) -> Result<T, SHA2Outcome> {
|
||||
if res == SHA2Outcome::shaSuccess {
|
||||
Ok(if_ok)
|
||||
} else {
|
||||
Err(res)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::hash::ffi::SHA2Result;
|
||||
use crate::hash::ffi::SHA2Outcome;
|
||||
|
||||
pub const SHA2_256_HASH_BITS: usize = 256;
|
||||
pub const SHA2_256_HASH_BYTES: usize = SHA2_256_HASH_BITS / 8;
|
||||
|
@ -8,19 +8,48 @@ pub const SHA2_256_BLOCK_SIZE: usize = 2 * SHA2_256_HASH_BYTES;
|
|||
pub type Digest256 = [u32; SHA2_256_HASH_PARTS];
|
||||
pub(crate) const DIGEST256_EMPTY: Digest256 = [0; SHA2_256_HASH_PARTS];
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||
pub struct SHA2_256Context {
|
||||
macro_rules! show_internals {
|
||||
($block:block) => {
|
||||
#[cfg(feature = "show_internals")]
|
||||
$block
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Hash)]
|
||||
pub struct Sha2_256Context {
|
||||
intermediate_hash: Digest256,
|
||||
block: [u8; SHA2_256_BLOCK_SIZE],
|
||||
block_idx: usize,
|
||||
length_low: usize,
|
||||
length_high: usize,
|
||||
}
|
||||
|
||||
impl SHA2_256Context {
|
||||
impl Sha2_256Context {
|
||||
const K: [u32; SHA2_256_BLOCK_SIZE] = [
|
||||
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 H: [u32; SHA2_256_HASH_PARTS] = [
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
|
||||
0x5be0cd19,
|
||||
];
|
||||
const PAD_BYTE: u8 = 0x80;
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
intermediate_hash: Default::default(),
|
||||
intermediate_hash: Self::H,
|
||||
block: [0; SHA2_256_BLOCK_SIZE],
|
||||
block_idx: Default::default(),
|
||||
length_low: Default::default(),
|
||||
length_high: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,28 +57,293 @@ impl SHA2_256Context {
|
|||
*self = Self::new();
|
||||
}
|
||||
|
||||
pub fn input(&mut self, data: &[u8]) -> Result<(), SHA2Result> {
|
||||
todo!()
|
||||
pub fn input(&mut self, data: &[u8]) -> Result<(), SHA2Outcome> {
|
||||
if data.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
for byte in data {
|
||||
self.block[self.block_idx] = *byte;
|
||||
self.block_idx += 1;
|
||||
if self.add_length(8).is_ok() && self.block_idx == SHA2_256_BLOCK_SIZE {
|
||||
self.process_block();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn finish(self) -> Result<Digest256, SHA2Result> {
|
||||
todo!()
|
||||
pub fn finish(mut self) -> Result<Digest256, SHA2Outcome> {
|
||||
self.finalize();
|
||||
Ok(self.intermediate_hash)
|
||||
}
|
||||
|
||||
// BUG: false values at end?
|
||||
fn process_block(&mut self) {
|
||||
show_internals!({
|
||||
self.show_internal_state("start processing");
|
||||
});
|
||||
|
||||
let mut w = [0; SHA2_256_BLOCK_SIZE];
|
||||
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for t in 0..16 {
|
||||
let t4 = t * 4;
|
||||
w[t] = ((self.block[t4] as u32) << 24)
|
||||
| ((self.block[t4 + 1] as u32) << 16)
|
||||
| ((self.block[t4 + 2] as u32) << 8)
|
||||
| (self.block[t4 + 3] as u32);
|
||||
}
|
||||
|
||||
for t in 16..SHA2_256_BLOCK_SIZE {
|
||||
w[t] = Self::sha256_sigma1_1(w[t - 2])
|
||||
.wrapping_add(w[t - 7])
|
||||
.wrapping_add(Self::sha256_sigma0_1(w[t - 15]))
|
||||
.wrapping_add(w[t - 16]);
|
||||
}
|
||||
|
||||
show_internals!({
|
||||
for (i, w) in w.iter().enumerate() {
|
||||
println!("w[{i}]:\t{w:032b}")
|
||||
}
|
||||
});
|
||||
|
||||
let mut a = self.intermediate_hash[0];
|
||||
let mut b = self.intermediate_hash[1];
|
||||
let mut c = self.intermediate_hash[2];
|
||||
let mut d = self.intermediate_hash[3];
|
||||
let mut e = self.intermediate_hash[4];
|
||||
let mut f = self.intermediate_hash[5];
|
||||
let mut g = self.intermediate_hash[6];
|
||||
let mut h = self.intermediate_hash[7];
|
||||
|
||||
show_internals!({
|
||||
println!("A:\t{a:032b}");
|
||||
println!("B:\t{b:032b}");
|
||||
println!("C:\t{c:032b}");
|
||||
println!("D:\t{d:032b}");
|
||||
println!("E:\t{e:032b}");
|
||||
println!("F:\t{f:032b}");
|
||||
println!("G:\t{g:032b}");
|
||||
println!("H:\t{h:032b}");
|
||||
});
|
||||
|
||||
let mut temp1;
|
||||
let mut temp2;
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for t in 0..SHA2_256_BLOCK_SIZE {
|
||||
show_internals!({
|
||||
println!("Iter {t}");
|
||||
});
|
||||
|
||||
// BUG: the alphabet values are not being changed correctly?
|
||||
temp1 = h
|
||||
.wrapping_add(Self::sha256_sigma1_0(e))
|
||||
.wrapping_add(Self::sha_ch(e, f, g))
|
||||
.wrapping_add(Self::K[t])
|
||||
.wrapping_add(w[t]);
|
||||
temp2 = Self::sha256_sigma0_0(a).wrapping_add(Self::sha_maj(a, b, c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d.wrapping_add(temp1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = temp1.wrapping_add(temp2);
|
||||
|
||||
show_internals!({
|
||||
println!("A:\t{a:032b} {a:08x}");
|
||||
println!("B:\t{b:032b} {b:08x}");
|
||||
println!("C:\t{c:032b} {c:08x}");
|
||||
println!("D:\t{d:032b} {d:08x}");
|
||||
println!("E:\t{e:032b} {e:08x}");
|
||||
println!("F:\t{f:032b} {f:08x}");
|
||||
println!("G:\t{g:032b} {g:08x}");
|
||||
println!("H:\t{h:032b} {h:08x}");
|
||||
for (i, h) in self.intermediate_hash.iter().enumerate() {
|
||||
println!("h[{i}]:\t{h:032b} {h:08x}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
show_internals!({
|
||||
self.show_internal_state("assigning intermediate_hash");
|
||||
});
|
||||
|
||||
self.intermediate_hash[0] = self.intermediate_hash[0].wrapping_add(a);
|
||||
self.intermediate_hash[1] = self.intermediate_hash[1].wrapping_add(b);
|
||||
self.intermediate_hash[2] = self.intermediate_hash[2].wrapping_add(c);
|
||||
self.intermediate_hash[3] = self.intermediate_hash[3].wrapping_add(d);
|
||||
self.intermediate_hash[4] = self.intermediate_hash[4].wrapping_add(e);
|
||||
self.intermediate_hash[5] = self.intermediate_hash[5].wrapping_add(f);
|
||||
self.intermediate_hash[6] = self.intermediate_hash[6].wrapping_add(g);
|
||||
self.intermediate_hash[7] = self.intermediate_hash[7].wrapping_add(h);
|
||||
|
||||
self.block_idx = 0;
|
||||
|
||||
// BUG: something is weird with these hash values, they are almost right?
|
||||
show_internals!({
|
||||
self.show_internal_state("processing end");
|
||||
for (i, h) in self.intermediate_hash.iter().enumerate() {
|
||||
println!("h[{i}]:\t{h:032b}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn add_length(&mut self, len: usize) -> Result<(), SHA2Outcome> {
|
||||
let add_temp = self.length_low;
|
||||
|
||||
// Update length_low and check for overflow
|
||||
self.length_low = self.length_low.wrapping_add(len);
|
||||
if self.length_low < add_temp {
|
||||
// Overflow occurred, increment length_high
|
||||
self.length_high = self.length_high.wrapping_add(1);
|
||||
if self.length_high == 0 {
|
||||
return Err(SHA2Outcome::shaInputTooLong);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SHA2_256Context {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn finalize(&mut self) {
|
||||
self.pad_block();
|
||||
}
|
||||
|
||||
fn pad_block(&mut self) {
|
||||
if self.block_idx >= (SHA2_256_BLOCK_SIZE - 8) {
|
||||
self.block[self.block_idx] = Self::PAD_BYTE;
|
||||
self.block_idx += 1;
|
||||
while self.block_idx < SHA2_256_BLOCK_SIZE {
|
||||
self.block[self.block_idx] = 0;
|
||||
self.block_idx += 1;
|
||||
}
|
||||
self.process_block();
|
||||
} else {
|
||||
self.block[self.block_idx] = Self::PAD_BYTE;
|
||||
self.block_idx += 1;
|
||||
}
|
||||
|
||||
while self.block_idx < (SHA2_256_BLOCK_SIZE - 8) {
|
||||
self.block[self.block_idx] = 0;
|
||||
self.block_idx += 1;
|
||||
}
|
||||
|
||||
self.block[56] = (self.length_high >> 24) as u8;
|
||||
self.block[57] = (self.length_high >> 16) as u8;
|
||||
self.block[58] = (self.length_high >> 8) as u8;
|
||||
self.block[59] = (self.length_high) as u8;
|
||||
self.block[60] = (self.length_low >> 24) as u8;
|
||||
self.block[61] = (self.length_low >> 16) as u8;
|
||||
self.block[62] = (self.length_low >> 8) as u8;
|
||||
self.block[63] = (self.length_low) as u8;
|
||||
|
||||
self.process_block();
|
||||
}
|
||||
|
||||
#[cfg(feature = "show_internals")]
|
||||
fn show_internal_state(&self, msg: impl core::fmt::Display) {
|
||||
println!("{msg}\n{self:#x?}")
|
||||
}
|
||||
}
|
||||
|
||||
/// internal functions for SHA2 process_block
|
||||
impl Sha2_256Context {
|
||||
#[inline]
|
||||
fn sha256_shr(bits: u32, word: u32) -> u32 {
|
||||
word >> bits
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sha256_rotr(bits: u32, word: u32) -> u32 {
|
||||
u32::rotate_right(word, bits)
|
||||
}
|
||||
|
||||
fn sha256_sigma0_0(word: u32) -> u32 {
|
||||
Self::sha256_rotr(2, word) ^ Self::sha256_rotr(13, word) ^ Self::sha256_shr(22, word)
|
||||
}
|
||||
|
||||
fn sha256_sigma1_0(word: u32) -> u32 {
|
||||
Self::sha256_rotr(6, word) ^ Self::sha256_rotr(11, word) ^ Self::sha256_shr(25, word)
|
||||
}
|
||||
|
||||
fn sha256_sigma0_1(word: u32) -> u32 {
|
||||
Self::sha256_rotr(7, word) ^ Self::sha256_rotr(18, word) ^ Self::sha256_shr(3, word)
|
||||
}
|
||||
|
||||
fn sha256_sigma1_1(word: u32) -> u32 {
|
||||
Self::sha256_rotr(17, word) ^ Self::sha256_rotr(19, word) ^ Self::sha256_shr(10, word)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sha_ch(x: u32, y: u32, z: u32) -> u32 {
|
||||
(x & (y ^ z)) ^ z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sha_maj(x: u32, y: u32, z: u32) -> u32 {
|
||||
(x & (y | z)) | (y & z)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Sha2_256Context {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Result> {
|
||||
todo!()
|
||||
pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Outcome> {
|
||||
let mut ctx = Sha2_256Context::default();
|
||||
ctx.input(data)?;
|
||||
ctx.finish()
|
||||
}
|
||||
|
||||
#[cfg(feature = "show_internals")]
|
||||
#[allow(unused)]
|
||||
mod debug {
|
||||
use super::*;
|
||||
|
||||
struct InlineArrHex2<'a, T: core::fmt::Debug + core::fmt::LowerHex>(&'a [T]);
|
||||
|
||||
impl<'a, T> core::fmt::Debug for InlineArrHex2<'a, T>
|
||||
where
|
||||
T: core::fmt::Debug + core::fmt::LowerHex,
|
||||
{
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "[\n")?;
|
||||
for (i, t) in self.0.iter().enumerate() {
|
||||
write!(f, "0x{t:02x}")?;
|
||||
if i < self.0.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
if i % 8 == 7 && i < self.0.len() - 1 {
|
||||
writeln!(f)?;
|
||||
}
|
||||
}
|
||||
write!(f, "\n]")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Sha2_256Context {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("Sha2_256Context")
|
||||
.field("intermediate_hash", &InlineArrHex2(&self.intermediate_hash))
|
||||
.field("block", &InlineArrHex2(&self.block))
|
||||
.field("block_idx", &self.block_idx)
|
||||
.field("length_low", &self.length_low)
|
||||
.field("length_high", &self.length_high)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "show_internals")]
|
||||
use debug::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use assert_hex::*;
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
|
||||
const TEST_VALUES: &[(&str, Digest256)] = &[
|
||||
(
|
||||
|
@ -70,8 +364,16 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_check() {
|
||||
let mut dig;
|
||||
for (input, expected_output) in TEST_VALUES.iter().copied() {
|
||||
assert_eq!(sha2_256_oneshot(input.as_bytes()), Ok(expected_output))
|
||||
dig = sha2_256_oneshot(input.as_bytes()).unwrap();
|
||||
println!(
|
||||
"Binary of first seg matches: {}\n{:032b}\n{:032b}",
|
||||
dig[0] == expected_output[0],
|
||||
dig[0],
|
||||
expected_output[0]
|
||||
);
|
||||
assert_eq_hex!(dig, expected_output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//! Many thanks to the [crc-catalogue](https://reveng.sourceforge.io/crc-catalogue/) for providing
|
||||
//! an overview over the various algorithms with test vectors and examples.
|
||||
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
#![cfg_attr(not(any(test, feature = "std")), no_std)]
|
||||
|
||||
pub mod crc;
|
||||
pub mod hash;
|
||||
|
|
Loading…
Add table
Reference in a new issue