From 18d81f52ec30e1320218b75e81d7c29f5451fa33 Mon Sep 17 00:00:00 2001 From: Thomas Coratger Date: Fri, 15 Mar 2024 11:59:17 +0100 Subject: [PATCH] refactor: simplify k generation following RFC 6979 --- Cargo.lock | 128 +++++++++++++++++++++++++-------- starknet-core/Cargo.toml | 2 +- starknet-crypto/Cargo.toml | 10 ++- starknet-crypto/src/rfc6979.rs | 71 +++++------------- 4 files changed, 121 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3922fa55..db4d39ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,13 +190,22 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.11.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "939c0e62efa052fb0b2db2c0f7c479ad32e364c192c3aab605a7641de265a1a7" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bs58" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "sha2", + "sha2 0.10.8", "tinyvec", ] @@ -291,7 +300,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "inout", ] @@ -334,11 +343,11 @@ checksum = "66c43ff7fd9ff522219058808a259e61423335767b1071d5b346de60d9219657" dependencies = [ "bs58", "coins-core", - "digest", - "hmac", + "digest 0.10.7", + "hmac 0.12.1", "k256", "serde", - "sha2", + "sha2 0.10.8", "thiserror", ] @@ -352,11 +361,11 @@ dependencies = [ "bech32", "bs58", "const-hex", - "digest", + "digest 0.10.7", "generic-array", "ripemd", "serde", - "sha2", + "sha2 0.10.8", "sha3", "thiserror", ] @@ -509,6 +518,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b8ce8218c97789f16356e7896b3714f26c2ee1079b79c0b7ae7064bb9089fa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "ctr" version = "0.9.2" @@ -623,9 +641,20 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.6", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.0-pre.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2e3d6615d99707295a9673e889bf363a04b2a466bd320c65a72536f7577379" +dependencies = [ + "block-buffer 0.11.0-rc.2", + "crypto-common 0.2.0-rc.1", "subtle", ] @@ -636,9 +665,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", - "rfc6979", + "rfc6979 0.4.0", "signature", "spki", ] @@ -657,7 +686,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", @@ -691,15 +720,15 @@ checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ "aes", "ctr", - "digest", + "digest 0.10.7", "hex", - "hmac", + "hmac 0.12.1", "pbkdf2", "rand", "scrypt", "serde", "serde_json", - "sha2", + "sha2 0.10.8", "sha3", "thiserror", "uuid", @@ -951,7 +980,16 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", +] + +[[package]] +name = "hmac" +version = "0.13.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4b1fb14e4df79f9406b434b60acef9f45c26c50062cccf1346c6103b8c47d58" +dependencies = [ + "digest 0.11.0-pre.9", ] [[package]] @@ -988,6 +1026,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.2.0-rc.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5a41e5b0754cae5aaf7915f1df1147ba8d316fc6e019cfcc00fbaba96d5e030" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "0.14.30" @@ -1174,7 +1221,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2", + "sha2 0.10.8", "signature", ] @@ -1195,7 +1242,7 @@ checksum = "7fb5d4f22241504f7c7b8d2c3a7d7835d7c07117f10bff2a7d96a9ef6ef217c3" dependencies = [ "lambdaworks-math", "serde", - "sha2", + "sha2 0.10.8", "sha3", ] @@ -1446,7 +1493,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -1684,7 +1731,17 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac", + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "rfc6979" +version = "0.5.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871ee76a3eee98b0f805e5d1caf26929f4565073c580c053a55f886fc15dea49" +dependencies = [ + "hmac 0.13.0-pre.4", "subtle", ] @@ -1709,7 +1766,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -1823,10 +1880,10 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" dependencies = [ - "hmac", + "hmac 0.12.1", "pbkdf2", "salsa20", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -1952,7 +2009,18 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "540c0893cce56cdbcfebcec191ec8e0f470dd1889b6e7a0b503e310a94a168f5" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.11.0-pre.9", ] [[package]] @@ -1961,7 +2029,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest", + "digest 0.10.7", "keccak", ] @@ -1986,7 +2054,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core", ] @@ -2108,21 +2176,19 @@ name = "starknet-crypto" version = "0.7.2" dependencies = [ "criterion", - "crypto-bigint", "hex", "hex-literal", - "hmac", "num-bigint", "num-integer", "num-traits", - "rfc6979", + "rfc6979 0.5.0-pre.4", "serde", "serde_json", - "sha2", + "sha2 0.11.0-pre.4", "starknet-curve", "starknet-types-core", + "subtle", "wasm-bindgen-test", - "zeroize", ] [[package]] diff --git a/starknet-core/Cargo.toml b/starknet-core/Cargo.toml index f3302ac2..fbcdc643 100644 --- a/starknet-core/Cargo.toml +++ b/starknet-core/Cargo.toml @@ -19,7 +19,7 @@ all-features = true [dependencies] starknet-crypto = { version = "0.7.2", path = "../starknet-crypto", default-features = false, features = ["alloc"] } base64 = { version = "0.21.0", default-features = false, features = ["alloc"] } -crypto-bigint = { version = "0.5.1", default-features = false } +crypto-bigint = { version = "0.5.1", default-features = false, features = ["generic-array"] } flate2 = { version = "1.0.25", optional = true } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } serde = { version = "1.0.160", default-features = false, features = ["derive"] } diff --git a/starknet-crypto/Cargo.toml b/starknet-crypto/Cargo.toml index b0989925..3fddd604 100644 --- a/starknet-crypto/Cargo.toml +++ b/starknet-crypto/Cargo.toml @@ -15,14 +15,13 @@ exclude = ["test-data/**"] [dependencies] starknet-curve = { version = "0.5.1", path = "../starknet-curve" } -crypto-bigint = { version = "0.5.1", default-features = false, features = ["generic-array", "zeroize"] } -hmac = { version = "0.12.1", default-features = false } num-bigint = { version = "0.4.3", default-features = false } num-integer = { version = "0.1.45", default-features = false } num-traits = { version = "0.2.18", default-features = false } -rfc6979 = { version = "0.4.0", default-features = false } -sha2 = { version = "0.10.6", default-features = false } -zeroize = { version = "1.6.0", default-features = false } +rfc6979 = { version = "0.5.0-pre.3", default-features = false } +subtle = { version = "2.6.1", default-features = false } +sha2 = { version = "0.11.0-pre.3", default-features = false } +hex-literal = { version = "0.4.1", default-features = false } hex = { version = "0.4.3", default-features = false, optional = true } starknet-types-core = { version = "0.1.6", default-features = false, features = ["curve", "hash"] } @@ -35,7 +34,6 @@ signature-display = ["dep:hex", "alloc"] [dev-dependencies] criterion = { version = "0.4.0", default-features = false } hex = "0.4.3" -hex-literal = "0.4.1" serde = { version = "1.0.160", features = ["derive"] } serde_json = "1.0.96" starknet-types-core = { version = "0.1.6", default-features = false, features = ["alloc"] } diff --git a/starknet-crypto/src/rfc6979.rs b/starknet-crypto/src/rfc6979.rs index 550040df..f873afe5 100644 --- a/starknet-crypto/src/rfc6979.rs +++ b/starknet-crypto/src/rfc6979.rs @@ -1,11 +1,7 @@ -use crypto_bigint::{ArrayEncoding, ByteArray, Integer, U256}; -use hmac::digest::Digest; -use sha2::digest::{crypto_common::BlockSizeUser, FixedOutputReset, HashMarker}; +use hex_literal::hex; use starknet_types_core::felt::Felt; -use zeroize::{Zeroize, Zeroizing}; -const EC_ORDER: U256 = - U256::from_be_hex("0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f"); +const EC_ORDER: [u8; 32] = hex!("0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f"); /// Deterministically generate ephemeral scalar `k` based on RFC 6979. /// @@ -15,61 +11,32 @@ const EC_ORDER: U256 = /// - `private_key`: Private key. /// - `seed`: Extra seed for additional entropy. pub fn generate_k(message_hash: &Felt, private_key: &Felt, seed: Option<&Felt>) -> Felt { - // The message hash padding as implemented in `cairo-lang` is not needed here. The hash is - // padded in `cairo-lang` only to make sure the lowest 4 bits won't get truncated, but here it's - // never getting truncated anyways. - let message_hash = U256::from_be_slice(&message_hash.to_bytes_be()).to_be_byte_array(); - let private_key = U256::from_be_slice(&private_key.to_bytes_be()); - - let seed_bytes = match seed { - Some(seed) => seed.to_bytes_be(), - None => [0u8; 32], - }; + // Convert seed to bytes + let seed_bytes = seed.map_or([0u8; 32], |s| s.to_bytes_be()); + // Find the index of the first non-zero byte in the seed let mut first_non_zero_index = 32; - for (ind, element) in seed_bytes.iter().enumerate() { - if *element != 0u8 { + for (ind, &element) in seed_bytes.iter().enumerate() { + if element != 0u8 { first_non_zero_index = ind; break; } } - let k = generate_k_shifted::( - &private_key, - &EC_ORDER, - &message_hash, - &seed_bytes[first_non_zero_index..], + // Convert GenericArray to [u8; 32] + let mut k_bytes = [0u8; 32]; + k_bytes.copy_from_slice( + rfc6979::generate_k::( + (&private_key.to_bytes_be()).into(), + &EC_ORDER.into(), + (&message_hash.to_bytes_be()).into(), + &seed_bytes[first_non_zero_index..], + ) + .as_slice(), ); - let mut buffer = [0u8; 32]; - buffer[..].copy_from_slice(&k.to_be_byte_array()[..]); - - Felt::from_bytes_be(&buffer) -} - -// Modified from upstream `rfc6979::generate_k` with a hard-coded right bit shift. The more -// idiomatic way of doing this seems to be to implement `U252` which handles bit truncation -// interally. -// TODO: change to use upstream `generate_k` directly. -#[inline] -fn generate_k_shifted(x: &I, n: &I, h: &ByteArray, data: &[u8]) -> Zeroizing -where - D: Default + Digest + BlockSizeUser + FixedOutputReset + HashMarker, - I: ArrayEncoding + Integer + Zeroize, -{ - let mut x = x.to_be_byte_array(); - let mut hmac_drbg = rfc6979::HmacDrbg::::new(&x, h, data); - x.zeroize(); - - loop { - let mut bytes = ByteArray::::default(); - hmac_drbg.fill_bytes(&mut bytes); - let k = I::from_be_byte_array(bytes) >> 4; - - if (!k.is_zero() & k.ct_lt(n)).into() { - return Zeroizing::new(k); - } - } + // Convert bytes to Felt + Felt::from_bytes_be(&k_bytes) } #[cfg(test)]