|
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. |
@@ -81,30 +85,29 @@ pub fn compute_sha256_u32_array( |
81 | 85 | /// 0x7d17648, 0x26381969]); |
82 | 86 | /// ``` |
83 | 87 | pub fn compute_sha256_byte_array(arr: @ByteArray) -> [u32; 8] { |
| 88 | + let mut iter = arr.span().into_iter(); |
84 | 89 | 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 | | - } |
97 | | - |
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, |
| 90 | + |
| 91 | + let (last_word, last_word_len) = loop { |
| 92 | + let Some(b0) = iter.next() else { |
| 93 | + break (0, 0); |
| 94 | + }; |
| 95 | + let Some(b1) = iter.next() else { |
| 96 | + break (upcast(b0), 1); |
| 97 | + }; |
| 98 | + let b0_b1 = conversions::shift_append_byte(b0, b1); |
| 99 | + let Some(b2) = iter.next() else { |
| 100 | + break (upcast(b0_b1), 2); |
| 101 | + }; |
| 102 | + let b0_b1_b2 = conversions::shift_append_byte(b0_b1, b2); |
| 103 | + let Some(b3) = iter.next() else { |
| 104 | + break (upcast(b0_b1_b2), 3); |
| 105 | + }; |
| 106 | + |
| 107 | + word_arr.append(upcast(conversions::shift_append_byte(b0_b1_b2, b3))); |
105 | 108 | }; |
106 | 109 |
|
107 | | - compute_sha256_u32_array(word_arr, last, rem.into()) |
| 110 | + compute_sha256_u32_array(word_arr, last_word, last_word_len) |
108 | 111 | } |
109 | 112 |
|
110 | 113 | /// Adds padding to the input array according to the SHA-256 specification. |
@@ -208,3 +211,48 @@ fn append_zeros(ref arr: Array<u32>, count: felt252) { |
208 | 211 | } |
209 | 212 | arr.append(0); |
210 | 213 | } |
| 214 | + |
| 215 | +mod conversions { |
| 216 | + #[feature("bounded-int-utils")] |
| 217 | + use core::internal::bounded_int::{self, AddHelper, BoundedInt, MulHelper, UnitInt}; |
| 218 | + |
| 219 | + impl U8Shift of MulHelper<u8, UnitInt<0x100>> { |
| 220 | + type Result = BoundedInt<0, 0xFF00>; |
| 221 | + } |
| 222 | + impl U8ShiftAddU8 of AddHelper<U8Shift::Result, u8> { |
| 223 | + type Result = BoundedInt<0, 0xFFFF>; |
| 224 | + } |
| 225 | + impl U16Shift of MulHelper<U8ShiftAddU8::Result, UnitInt<0x100>> { |
| 226 | + type Result = BoundedInt<0, 0xFFFF00>; |
| 227 | + } |
| 228 | + impl U16ShiftAddU8 of AddHelper<U16Shift::Result, u8> { |
| 229 | + type Result = BoundedInt<0, 0xFFFFFF>; |
| 230 | + } |
| 231 | + impl U24Shift of MulHelper<U16ShiftAddU8::Result, UnitInt<0x100>> { |
| 232 | + type Result = BoundedInt<0, 0xFFFFFF00>; |
| 233 | + } |
| 234 | + impl U24ShiftAddU8 of AddHelper<U24Shift::Result, u8> { |
| 235 | + type Result = BoundedInt<0, 0xFFFFFFFF>; |
| 236 | + } |
| 237 | + trait ShiftAppendByte<T, MulResult> { |
| 238 | + impl Mul: MulHelper<T, UnitInt<0x100>>; |
| 239 | + impl Add: AddHelper<MulResult, u8>; |
| 240 | + } |
| 241 | + |
| 242 | + // Blanket implementation for any type with appropriate helpers. |
| 243 | + impl ShiftAppendByteImpl< |
| 244 | + T, impl MH: MulHelper<T, UnitInt<0x100>>, impl AH: AddHelper<MH::Result, u8>, |
| 245 | + > of ShiftAppendByte<T, MH::Result> {} |
| 246 | + |
| 247 | + /// Shifts a word left by one byte position and appends a new byte. |
| 248 | + pub fn shift_append_byte< |
| 249 | + T, |
| 250 | + MulResult, |
| 251 | + impl SAB: ShiftAppendByte<T, MulResult>, |
| 252 | + +core::metaprogramming::TypeEqual<MulResult, SAB::Mul::Result>, |
| 253 | + >( |
| 254 | + word: T, byte: u8, |
| 255 | + ) -> SAB::Add::Result { |
| 256 | + bounded_int::add::<_, _, SAB::Add>(bounded_int::mul::<_, _, SAB::Mul>(word, 0x100), byte) |
| 257 | + } |
| 258 | +} |
0 commit comments