Skip to content

Commit c8abfa6

Browse files
author
Gilad Chase
committed
refactor(sha256): Compute ByteArray sha256 via iterator
1 parent 79f18d7 commit c8abfa6

File tree

1 file changed

+66
-20
lines changed

1 file changed

+66
-20
lines changed

corelib/src/sha256.cairo

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
//! assert!(hash == [0x185f8db3, 0x2271fe25, 0xf561a6fc, 0x938b2e26, 0x4306ec30, 0x4eda5180,
1414
//! 0x7d17648, 0x26381969]);
1515
//! ```
16+
#[feature("byte-span")]
17+
use core::byte_array::ToByteSpanTrait;
18+
#[feature("bounded-int-utils")]
19+
use core::internal::bounded_int::upcast;
1620
use starknet::SyscallResultTrait;
1721

1822
/// A handle to the state of a SHA-256 hash.
@@ -82,29 +86,30 @@ pub fn compute_sha256_u32_array(
8286
/// ```
8387
pub fn compute_sha256_byte_array(arr: @ByteArray) -> [u32; 8] {
8488
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();
9790

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);
105110
};
106111

107-
compute_sha256_u32_array(word_arr, last, rem.into())
112+
compute_sha256_u32_array(word_arr, last_word, last_word_len)
108113
}
109114

110115
/// 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) {
208213
}
209214
arr.append(0);
210215
}
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

Comments
 (0)