1
- use crypto_bigint:: { ArrayEncoding , ByteArray , Integer , U256 } ;
2
- use hmac:: digest:: Digest ;
3
- use sha2:: digest:: { crypto_common:: BlockSizeUser , FixedOutputReset , HashMarker } ;
4
- use zeroize:: { Zeroize , Zeroizing } ;
5
-
6
1
use crate :: FieldElement ;
2
+ use hex_literal:: hex;
7
3
8
- const EC_ORDER : U256 =
9
- U256 :: from_be_hex ( "0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f" ) ;
4
+ const EC_ORDER : [ u8 ; 32 ] = hex ! ( "0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f" ) ;
10
5
11
6
/// Deterministically generate ephemeral scalar `k` based on RFC 6979.
12
7
///
@@ -20,61 +15,32 @@ pub fn generate_k(
20
15
private_key : & FieldElement ,
21
16
seed : Option < & FieldElement > ,
22
17
) -> FieldElement {
23
- // The message hash padding as implemented in `cairo-lang` is not needed here. The hash is
24
- // padded in `cairo-lang` only to make sure the lowest 4 bits won't get truncated, but here it's
25
- // never getting truncated anyways.
26
- let message_hash = U256 :: from_be_slice ( & message_hash. to_bytes_be ( ) ) . to_be_byte_array ( ) ;
27
- let private_key = U256 :: from_be_slice ( & private_key. to_bytes_be ( ) ) ;
28
-
29
- let seed_bytes = match seed {
30
- Some ( seed) => seed. to_bytes_be ( ) ,
31
- None => [ 0u8 ; 32 ] ,
32
- } ;
18
+ // Convert seed to bytes
19
+ let seed_bytes = seed. map_or ( [ 0u8 ; 32 ] , |s| s. to_bytes_be ( ) ) ;
33
20
21
+ // Find the index of the first non-zero byte in the seed
34
22
let mut first_non_zero_index = 32 ;
35
- for ( ind, element) in seed_bytes. iter ( ) . enumerate ( ) {
36
- if * element != 0u8 {
23
+ for ( ind, & element) in seed_bytes. iter ( ) . enumerate ( ) {
24
+ if element != 0u8 {
37
25
first_non_zero_index = ind;
38
26
break ;
39
27
}
40
28
}
41
29
42
- let k = generate_k_shifted :: < sha2:: Sha256 , _ > (
43
- & private_key,
44
- & EC_ORDER ,
45
- & message_hash,
46
- & seed_bytes[ first_non_zero_index..] ,
30
+ // Convert GenericArray to [u8; 32]
31
+ let mut k_bytes = [ 0u8 ; 32 ] ;
32
+ k_bytes. copy_from_slice (
33
+ rfc6979:: generate_k :: < sha2:: Sha256 , rfc6979:: consts:: U32 > (
34
+ ( & private_key. to_bytes_be ( ) ) . into ( ) ,
35
+ & EC_ORDER . into ( ) ,
36
+ ( & message_hash. to_bytes_be ( ) ) . into ( ) ,
37
+ & seed_bytes[ first_non_zero_index..] ,
38
+ )
39
+ . as_slice ( ) ,
47
40
) ;
48
41
49
- let mut buffer = [ 0u8 ; 32 ] ;
50
- buffer[ ..] . copy_from_slice ( & k. to_be_byte_array ( ) [ ..] ) ;
51
-
52
- FieldElement :: from_bytes_be ( & buffer) . unwrap ( )
53
- }
54
-
55
- // Modified from upstream `rfc6979::generate_k` with a hard-coded right bit shift. The more
56
- // idiomatic way of doing this seems to be to implement `U252` which handles bit truncation
57
- // interally.
58
- // TODO: change to use upstream `generate_k` directly.
59
- #[ inline]
60
- fn generate_k_shifted < D , I > ( x : & I , n : & I , h : & ByteArray < I > , data : & [ u8 ] ) -> Zeroizing < I >
61
- where
62
- D : Default + Digest + BlockSizeUser + FixedOutputReset + HashMarker ,
63
- I : ArrayEncoding + Integer + Zeroize ,
64
- {
65
- let mut x = x. to_be_byte_array ( ) ;
66
- let mut hmac_drbg = rfc6979:: HmacDrbg :: < D > :: new ( & x, h, data) ;
67
- x. zeroize ( ) ;
68
-
69
- loop {
70
- let mut bytes = ByteArray :: < I > :: default ( ) ;
71
- hmac_drbg. fill_bytes ( & mut bytes) ;
72
- let k = I :: from_be_byte_array ( bytes) >> 4 ;
73
-
74
- if ( !k. is_zero ( ) & k. ct_lt ( n) ) . into ( ) {
75
- return Zeroizing :: new ( k) ;
76
- }
77
- }
42
+ // Convert bytes to FieldElement
43
+ FieldElement :: from_bytes_be ( & k_bytes) . unwrap ( )
78
44
}
79
45
80
46
#[ cfg( test) ]
0 commit comments