|
13 | 13 | //! assert!(hash == [0x185f8db3, 0x2271fe25, 0xf561a6fc, 0x938b2e26, 0x4306ec30, 0x4eda5180, |
14 | 14 | //! 0x7d17648, 0x26381969]); |
15 | 15 | //! ``` |
| 16 | +#[feature("byte-span")] |
| 17 | +use core::byte_array::ToByteSpanTrait; |
| 18 | +#[feature("bounded-int-utils")] |
| 19 | +use core::internal::bounded_int::upcast; |
16 | 20 | use starknet::SyscallResultTrait; |
17 | 21 |
|
18 | 22 | /// A handle to the state of a SHA-256 hash. |
@@ -82,29 +86,30 @@ pub fn compute_sha256_u32_array( |
82 | 86 | /// ``` |
83 | 87 | pub fn compute_sha256_byte_array(arr: @ByteArray) -> [u32; 8] { |
84 | 88 | let mut word_arr = array![]; |
85 | | - let len = arr.len(); |
86 | | - let rem = len % 4; |
87 | | - let mut index = 0; |
88 | | - let rounded_len = len - rem; |
89 | | - while index != rounded_len { |
90 | | - let word = arr.at(index + 3).unwrap().into() |
91 | | - + arr.at(index + 2).unwrap().into() * 0x100 |
92 | | - + arr.at(index + 1).unwrap().into() * 0x10000 |
93 | | - + arr.at(index).unwrap().into() * 0x1000000; |
94 | | - word_arr.append(word); |
95 | | - index = index + 4; |
96 | | - } |
| 89 | + let mut iter = arr.span().into_iter(); |
97 | 90 |
|
98 | | - let last = match rem { |
99 | | - 0 => 0, |
100 | | - 1 => arr.at(len - 1).unwrap().into(), |
101 | | - 2 => arr.at(len - 1).unwrap().into() + arr.at(len - 2).unwrap().into() * 0x100, |
102 | | - _ => arr.at(len - 1).unwrap().into() |
103 | | - + arr.at(len - 2).unwrap().into() * 0x100 |
104 | | - + arr.at(len - 3).unwrap().into() * 0x10000, |
| 91 | + // Process bytes from the iterator in chunks of 4. |
| 92 | + let (last_word, last_word_len): (u32, u32) = loop { |
| 93 | + let Some(b0) = iter.next() else { |
| 94 | + break (0, 0); |
| 95 | + }; |
| 96 | + let Some(b1) = iter.next() else { |
| 97 | + break (upcast(b0), 1); |
| 98 | + }; |
| 99 | + let b0_b1 = conversions::u8_shift_append_byte(b0, b1); |
| 100 | + let Some(b2) = iter.next() else { |
| 101 | + break (upcast(b0_b1), 2); |
| 102 | + }; |
| 103 | + let b0_b1_b2 = conversions::u16_shift_append_byte(b0_b1, b2); |
| 104 | + let Some(b3) = iter.next() else { |
| 105 | + break (upcast(b0_b1_b2), 3); |
| 106 | + }; |
| 107 | + |
| 108 | + let word = upcast(conversions::u24_shift_append_byte(b0_b1_b2, b3)); |
| 109 | + word_arr.append(word); |
105 | 110 | }; |
106 | 111 |
|
107 | | - compute_sha256_u32_array(word_arr, last, rem.into()) |
| 112 | + compute_sha256_u32_array(word_arr, last_word, last_word_len) |
108 | 113 | } |
109 | 114 |
|
110 | 115 | /// Adds padding to the input array according to the SHA-256 specification. |
@@ -208,3 +213,44 @@ fn append_zeros(ref arr: Array<u32>, count: felt252) { |
208 | 213 | } |
209 | 214 | arr.append(0); |
210 | 215 | } |
| 216 | + |
| 217 | +mod conversions { |
| 218 | + #[feature("bounded-int-utils")] |
| 219 | + use core::internal::bounded_int::{self, AddHelper, BoundedInt, MulHelper, UnitInt}; |
| 220 | + |
| 221 | + const POW_2_8_TYPED: UnitInt<0x100> = 0x100; |
| 222 | + |
| 223 | + impl U8Shift of MulHelper<u8, UnitInt<0x100>> { |
| 224 | + type Result = BoundedInt<0, 0xFF00>; |
| 225 | + } |
| 226 | + impl U8ShiftAddU8 of AddHelper<U8Shift::Result, u8> { |
| 227 | + type Result = BoundedInt<0, 0xFFFF>; |
| 228 | + } |
| 229 | + impl U16Shift of MulHelper<U8ShiftAddU8::Result, UnitInt<0x100>> { |
| 230 | + type Result = BoundedInt<0, 0xFFFF00>; |
| 231 | + } |
| 232 | + impl U16ShiftAddU8 of AddHelper<U16Shift::Result, u8> { |
| 233 | + type Result = BoundedInt<0, 0xFFFFFF>; |
| 234 | + } |
| 235 | + impl U24Shift of MulHelper<U16ShiftAddU8::Result, UnitInt<0x100>> { |
| 236 | + type Result = BoundedInt<0, 0xFFFFFF00>; |
| 237 | + } |
| 238 | + impl U24ShiftAddU8 of AddHelper<U24Shift::Result, u8> { |
| 239 | + type Result = BoundedInt<0, 0xFFFFFFFF>; |
| 240 | + } |
| 241 | + |
| 242 | + /// Shifts a u8 left by 8 bits and appends a byte. |
| 243 | + pub fn u8_shift_append_byte(word: u8, byte: u8) -> U8ShiftAddU8::Result { |
| 244 | + bounded_int::add(bounded_int::mul(word, POW_2_8_TYPED), byte) |
| 245 | + } |
| 246 | + |
| 247 | + /// Shifts a 16-bit value left by 8 bits and appends a byte. |
| 248 | + pub fn u16_shift_append_byte(word: U8ShiftAddU8::Result, byte: u8) -> U16ShiftAddU8::Result { |
| 249 | + bounded_int::add(bounded_int::mul(word, POW_2_8_TYPED), byte) |
| 250 | + } |
| 251 | + |
| 252 | + /// Shifts a 24-bit value left by 8 bits and appends a byte. |
| 253 | + pub fn u24_shift_append_byte(word: U16ShiftAddU8::Result, byte: u8) -> U24ShiftAddU8::Result { |
| 254 | + bounded_int::add(bounded_int::mul(word, POW_2_8_TYPED), byte) |
| 255 | + } |
| 256 | +} |
0 commit comments