Last active
April 5, 2024 00:31
-
-
Save alpinevm/2dadf7f9d748d734c396f91f724fcf66 to your computer and use it in GitHub Desktop.
BoundedVec mod of sha256 (noir v0.26.0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Implementation of SHA-256 mapping a byte array of variable length to | |
| // 32 bytes. | |
| use dep::std::hash; | |
| // Convert 64-byte array to array of 16 u32s | |
| fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { | |
| let mut msg32: [u32; 16] = [0; 16]; | |
| for i in 0..16 { | |
| for j in 0..4 { | |
| msg32[15 - i] = (msg32[15 - i] << 8) + msg[64 - 4*(i + 1) + j] as u32; | |
| } | |
| } | |
| msg32 | |
| } | |
| // SHA-256 hash function | |
| unconstrained pub fn digest<N>(msg: BoundedVec<u8, N>) -> [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 { | |
| if k < msg.len() { | |
| // Populate msg_block | |
| msg_block[i as Field] = msg.get(k); | |
| i = i + 1; | |
| if i == 64 { | |
| // Enough to hash block | |
| h = hash::sha256_compression(msg_u8_to_u32(msg_block), h); | |
| i = 0; | |
| } | |
| } else { | |
| break; | |
| } | |
| } | |
| // Pad the rest such that we have a [u32; 2] block at the end representing the length | |
| // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). | |
| msg_block[i as Field] = 1 << 7; | |
| i = i + 1; | |
| // If i >= 57, there aren't enough bits in the current message block to accomplish this, so | |
| // the 1 and 0s fill up the current block, which we then compress accordingly. | |
| if i >= 57 { | |
| // Not enough bits (64) to store length. Fill up with zeros. | |
| if i < 64 { | |
| for _i in 57..64 { | |
| if i <= 63 { | |
| msg_block[i as Field] = 0; | |
| i += 1; | |
| } | |
| } | |
| } | |
| h = hash::sha256_compression(msg_u8_to_u32(msg_block), h); | |
| i = 0; | |
| } | |
| for _i in 0..64 { | |
| // In any case, fill blocks up with zeros until the last 64 (i.e. until i = 56). | |
| if i < 56 { | |
| msg_block[i as Field] = 0; | |
| i = i + 1; | |
| } else if i < 64 { | |
| let mut len = 8 * msg.len(); | |
| for j in 0..8 { | |
| msg_block[63 - j] = len as u8; | |
| len >>= 8; | |
| } | |
| i += 8; | |
| } | |
| } | |
| // Hash final padded block | |
| h = hash::sha256_compression(msg_u8_to_u32(msg_block), h); | |
| // Return final hash as byte array | |
| for j in 0..8 { | |
| for k in 0..4 { | |
| out_h[31 - 4*j - k] = h[7 - j] as u8; | |
| h[7-j] >>= 8; | |
| } | |
| } | |
| out_h | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment