From c3695a08b0154170d8321c4b098cf32411a69993 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 25 Apr 2024 08:49:19 +0000 Subject: [PATCH 1/6] add variable size sha256 --- noir_stdlib/src/sha256.nr | 54 ++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index 8ca6808568d..6b49aa92979 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -17,19 +17,42 @@ fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { } // SHA-256 hash function pub fn digest(msg: [u8; N]) -> [u8; 32] { + sha256_var(msg, N) +} + +pub fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { + let mut out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes + + // Hash final padded block + state = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), state); + + // Return final hash as byte array + for j in 0..8 { + let h_bytes = (state[7 - j] as Field).to_le_bytes(4); + for k in 0..4 { + out_h[31 - 4*j - k] = h_bytes[k]; + } + } + + out_h +} + +// Variable size SHA-256 hash +pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { let mut msg_block: [u8; 64] = [0; 64]; let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value - let mut out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes let mut i: u64 = 0; // Message byte pointer for k in 0..N { - // Populate msg_block - msg_block[i] = msg[k]; - i = i + 1; - if i == 64 { - // Enough to hash block - h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); + if k < message_size { + // Populate msg_block + msg_block[i] = msg[k]; + i = i + 1; + if i == 64 { + // Enough to hash block + h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); - i = 0; + i = 0; + } } } // Pad the rest such that we have a [u32; 2] block at the end representing the length @@ -53,7 +76,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { i = 0; } - let len = 8 * msg.len(); + let len = 8 * message_size; let len_bytes = (len as Field).to_le_bytes(8); for _i in 0..64 { // In any case, fill blocks up with zeros until the last 64 (i.e. until i = 56). @@ -67,16 +90,5 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { i += 8; } } - // Hash final padded block - h = crate::hash::sha256_compression(msg_u8_to_u32(msg_block), h); - - // Return final hash as byte array - for j in 0..8 { - let h_bytes = (h[7 - j] as Field).to_le_bytes(4); - for k in 0..4 { - out_h[31 - 4*j - k] = h_bytes[k]; - } - } - - out_h + hash_final_block(msg_block, h) } From 53fc7a8f5b34a4447cd4c4886883af8871799cb3 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 25 Apr 2024 08:53:35 +0000 Subject: [PATCH 2/6] update documentation --- .../noir/standard_library/cryptographic_primitives/hashes.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index 7329880c7a7..111caa28ebd 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -13,6 +13,7 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## sha256 Given an array of bytes, returns the resulting sha256 hash. +Specify a message_size to hash only the first `message_size` bytes of the input. #include_code sha256 noir_stdlib/src/hash.nr rust @@ -21,10 +22,11 @@ example: ```rust fn main() { let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); + let hash = std::sha256::sha256_var(x, 4); } ``` + ## blake2s From 82aca5badb259a886c7804c5be89b3839daeb449 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 25 Apr 2024 12:21:28 +0000 Subject: [PATCH 3/6] code review --- noir_stdlib/src/sha256.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index 6b49aa92979..d856043fcfa 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -20,7 +20,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { sha256_var(msg, N) } -pub fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { +fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { let mut out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes // Hash final padded block From 5e80e6629b7bfb31b7fef26919c4130b2892e2d3 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 25 Apr 2024 12:40:38 +0000 Subject: [PATCH 4/6] Code review --- noir_stdlib/src/hash.nr | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 26a9fa6c2c0..6beabb1c7eb 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -4,12 +4,14 @@ mod poseidon2; use crate::default::Default; use crate::uint128::U128; +use crate::sha256::{digest, sha256_var}; -#[foreign(sha256)] // docs:start:sha256 pub fn sha256(input: [u8; N]) -> [u8; 32] // docs:end:sha256 -{} +{ + sha256_var(input, N) +} #[foreign(blake2s)] // docs:start:blake2s From 8d4bb3ee5ffab9eefb579dbe3ecce72c20fd4511 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 25 Apr 2024 12:46:28 +0000 Subject: [PATCH 5/6] adding test snippet in docs --- .../noir/standard_library/cryptographic_primitives/hashes.mdx | 1 + test_programs/execution_success/sha256/src/main.nr | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index 111caa28ebd..efa52b2c3f2 100644 --- a/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -18,6 +18,7 @@ Specify a message_size to hash only the first `message_size` bytes of the input. #include_code sha256 noir_stdlib/src/hash.nr rust example: +#include_code sha256_var test_programs/execution_success/sha256/src/main.nr rust ```rust fn main() { diff --git a/test_programs/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr index fd5340e2384..d4240ded8b3 100644 --- a/test_programs/execution_success/sha256/src/main.nr +++ b/test_programs/execution_success/sha256/src/main.nr @@ -14,6 +14,8 @@ use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program - let digest = std::hash::sha256([x as u8]); + // docs:start:sha256_var + let digest = std::hash::sha256_var([x as u8], 1); + // docs:end:sha256_var assert(digest == result); } From 2a99d557ab2cfc9b3abed9e00edcce4f663fc879 Mon Sep 17 00:00:00 2001 From: guipublic Date: Thu, 25 Apr 2024 13:03:39 +0000 Subject: [PATCH 6/6] restore foreign call to sha256 --- noir_stdlib/src/hash.nr | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 6beabb1c7eb..ef1cb0889d7 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -6,12 +6,11 @@ use crate::default::Default; use crate::uint128::U128; use crate::sha256::{digest, sha256_var}; +#[foreign(sha256)] // docs:start:sha256 pub fn sha256(input: [u8; N]) -> [u8; 32] // docs:end:sha256 -{ - sha256_var(input, N) -} +{} #[foreign(blake2s)] // docs:start:blake2s