Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add variable size sha256 #4920

Merged
merged 7 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ 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

example:
#include_code sha256_var test_programs/execution_success/sha256/src/main.nr rust

```rust
fn main() {
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved
let x = [163, 117, 178, 149]; // some random bytes
let hash = std::hash::sha256(x);
let hash = std::sha256::sha256_var(x, 4);
}
```


<BlackBoxInfo />

## blake2s
Expand Down
1 change: 1 addition & 0 deletions noir_stdlib/src/hash.nr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod poseidon2;

use crate::default::Default;
use crate::uint128::U128;
use crate::sha256::{digest, sha256_var};

#[foreign(sha256)]
// docs:start:sha256
Expand Down
54 changes: 33 additions & 21 deletions noir_stdlib/src/sha256.nr
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,42 @@ fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] {
}
// SHA-256 hash function
pub fn digest<N>(msg: [u8; N]) -> [u8; 32] {
sha256_var(msg, N)
}

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<N>(msg: [u8; N], message_size: u64) -> [u8; 32] {
guipublic marked this conversation as resolved.
Show resolved Hide resolved
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
Expand All @@ -53,7 +76,7 @@ pub fn digest<N>(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).
Expand All @@ -67,16 +90,5 @@ pub fn digest<N>(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)
}
4 changes: 3 additions & 1 deletion test_programs/execution_success/sha256/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Loading