1616#[feature(" byte-span" )]
1717use core :: byte_array :: ToByteSpanTrait ;
1818#[feature(" bounded-int-utils" )]
19- use core :: internal :: bounded_int :: upcast;
19+ use core :: internal :: bounded_int :: { BoundedInt , downcast, upcast} ;
2020use starknet :: SyscallResultTrait ;
2121
2222/// A handle to the state of a SHA-256 hash.
@@ -36,17 +36,29 @@ const SHA256_INITIAL_STATE: [u32; 8] = [
3636 0x6a09e667 , 0xbb67ae85 , 0x3c6ef372 , 0xa54ff53a , 0x510e527f , 0x9b05688c , 0x1f83d9ab , 0x5be0cd19 ,
3737];
3838
39- /// Computes the SHA-256 hash of an array of 32-bit words.
39+ /// Computes the SHA-256 hash of an input provided as 32-bit words, with optional trailing bytes.
40+ ///
41+ /// # Note
42+ ///
43+ /// For better type safety, consider using `compute_sha256_u32_array_safe` when
44+ /// `last_input_num_bytes` is guaranteed to be in the range 0..=3.
4045///
4146/// # Arguments
4247///
43- /// * `input` - An array of `u32` values to hash
44- /// * `last_input_word` - The final word when input is not word-aligned
45- /// * `last_input_num_bytes` - Number of bytes in the last input word (must be less than 4)
48+ /// * `input` - The main input, expressed as an array of `u32` words.
49+ /// * `last_input_word` - A partial final word containing any remaining bytes when the input is not
50+ /// word-aligned.
51+ /// * `last_input_num_bytes` - The number of valid bytes in `last_input_word`. Must be in the range
52+ /// 0..=3.
53+ ///
54+ /// # Panics
55+ ///
56+ /// * If `last_input_num_bytes` is greater than 3.
4657///
4758/// # Returns
4859///
49- /// * The SHA-256 hash of the `input array` + `last_input_word` as big endian
60+ /// * The SHA-256 hash of `input` followed by the `last_input_num_bytes` most significant bytes of
61+ /// `last_input_word`, interpreted in big-endian order.
5062///
5163/// # Examples
5264///
@@ -59,6 +71,39 @@ const SHA256_INITIAL_STATE: [u32; 8] = [
5971/// ```
6072pub fn compute_sha256_u32_array (
6173 mut input : Array <u32 >, last_input_word : u32 , last_input_num_bytes : u32 ,
74+ ) -> [u32 ; 8 ] {
75+ let last_input_num_bytes = downcast (last_input_num_bytes ). expect (' `last_input_num_bytes` > 3' );
76+ compute_sha256_u32_array_safe (input , last_input_word , last_input_num_bytes )
77+ }
78+
79+ /// A type representing a bounded integer in the range `0..=3`.
80+ pub type u2 = BoundedInt <0 , 3 >;
81+
82+ /// Computes the SHA-256 hash of an input provided as 32-bit words, with optional trailing bytes.
83+ ///
84+ /// # Arguments
85+ ///
86+ /// * `input` - The main input, expressed as an array of `u32` words.
87+ /// * `last_input_word` - A partial final word containing any remaining bytes when the input is not
88+ /// word-aligned.
89+ /// * `last_input_num_bytes` - The number of valid bytes in `last_input_word`.
90+ ///
91+ /// # Returns
92+ ///
93+ /// * The SHA-256 hash of `input` followed by the `last_input_num_bytes` most significant bytes of
94+ /// `last_input_word`, interpreted in big-endian order.
95+ ///
96+ /// # Examples
97+ ///
98+ /// ```
99+ /// use core::sha256::compute_sha256_u32_array_safe;
100+ ///
101+ /// let hash = compute_sha256_u32_array_safe(array![0x68656c6c], 0x6f, 1);
102+ /// assert!(hash == [0x2cf24dba, 0x5fb0a30e, 0x26e83b2a, 0xc5b9e29e, 0x1b161e5c, 0x1fa7425e,
103+ /// 0x73043362, 0x938b9824]);
104+ /// ```
105+ pub fn compute_sha256_u32_array_safe (
106+ mut input : Array <u32 >, last_input_word : u32 , last_input_num_bytes : u2 ,
62107) -> [u32 ; 8 ] {
63108 add_sha256_padding (ref input , last_input_word , last_input_num_bytes );
64109
@@ -107,7 +152,7 @@ pub fn compute_sha256_byte_array(arr: @ByteArray) -> [u32; 8] {
107152 word_arr . append (upcast (conversions :: shift_append_byte (b0_b1_b2 , b3 )));
108153 };
109154
110- compute_sha256_u32_array (word_arr , last_word , last_word_len )
155+ compute_sha256_u32_array_safe (word_arr , last_word , last_word_len )
111156}
112157
113158/// Adds padding to the input array according to the SHA-256 specification.
@@ -121,9 +166,10 @@ pub fn compute_sha256_byte_array(arr: @ByteArray) -> [u32; 8] {
121166///
122167/// # Arguments
123168/// * `arr` - Array to pad (modified in place)
124- /// * `last_input_word` - Final word for non-word-aligned inputs
125- /// * `last_input_num_bytes` - Number of valid bytes in last_input_word
126- fn add_sha256_padding (ref arr : Array <u32 >, last_input_word : u32 , last_input_num_bytes : u32 ) {
169+ /// * `last_input_word` - A partial final word containing any remaining bytes when the input is not
170+ /// word-aligned.
171+ /// * `last_input_num_bytes` - The number of valid bytes in `last_input_word`.
172+ fn add_sha256_padding (ref arr : Array <u32 >, last_input_word : u32 , last_input_num_bytes : u2 ) {
127173 let bitlen = conversions :: bitlen (arr . len (), last_input_num_bytes );
128174 arr . append (conversions :: to_last_word (last_input_word , last_input_num_bytes ));
129175 // Now writing the length in bits, at the end of a block.
@@ -173,6 +219,7 @@ mod conversions {
173219 use core :: internal :: bounded_int :: {
174220 self, AddHelper , BoundedInt , DivRemHelper , MulHelper , UnitInt ,
175221 };
222+ use super :: u2;
176223
177224 impl U8Shift of MulHelper <u8 , UnitInt <0x100 >> {
178225 type Result = BoundedInt <0 , 0xFF00>;
@@ -234,7 +281,7 @@ mod conversions {
234281 }
235282
236283 /// Returns the last word to append to the input `u32` array given the last word input.
237- pub fn to_last_word (word : u32 , len : u32 ) -> u32 {
284+ pub fn to_last_word (word : u32 , len : u2 ) -> u32 {
238285 let shift : BoundedInt <0 , 0x800000 > = match len {
239286 0 => { return 0x80000000 ; },
240287 1 => 0x800000 ,
@@ -253,17 +300,17 @@ mod conversions {
253300 type Result = BoundedInt <0 , 0x1FFFFFFFE0>;
254301 }
255302
256- impl WordBitLen of MulHelper <u32 , UnitInt <8 >> {
257- type Result = BoundedInt <0 , 0x7FFFFFFF8 >;
303+ impl WordBitLen of MulHelper <u2 , UnitInt <8 >> {
304+ type Result = BoundedInt <0 , 0x18 >;
258305 }
259306
260- impl FullBitLen of AddHelper <BoundedInt <0 , 0x1FFFFFFFE0>, BoundedInt <0 , 0x7FFFFFFF8 >> {
261- type Result = BoundedInt <0 , { 0x1FFFFFFFE0 + 0x7FFFFFFF8 }>;
307+ impl FullBitLen of AddHelper <BoundedInt <0 , 0x1FFFFFFFE0>, BoundedInt <0 , 0x18 >> {
308+ type Result = BoundedInt <0 , { 0x1FFFFFFFE0 + 0x18 }>;
262309 }
263310
264311 /// Returns the bit length of the input message, given the length of the representation u32
265312 /// array and last word bytes.
266- pub fn bitlen (arr_len : u32 , last_word_bytes : u32 ) -> u32 {
313+ pub fn bitlen (arr_len : u32 , last_word_bytes : u2 ) -> u32 {
267314 let arr_bits = bounded_int :: mul :: <_ , _ , ArrBitLen >(arr_len , 32 );
268315 let last_word_bits = bounded_int :: mul :: <_ , _ , WordBitLen >(last_word_bytes , 8 );
269316 bounded_int :: downcast (bounded_int :: add :: <_ , _ , FullBitLen >(arr_bits , last_word_bits ))
0 commit comments