Skip to content

Commit

Permalink
Merge pull request #701 from near/dmd/sha3-kdf
Browse files Browse the repository at this point in the history
Migrate to sha3 for the KDF
  • Loading branch information
volovyks authored Jul 19, 2024
2 parents cbd2def + 13ea497 commit 3248deb
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

- Payload hash scalars are now big endian where previously they were little endian. In general this means that clients of the contract should no longer reverse their hashed payload before sending it to the MPC contract.
- The sha256 scalar used to derive the epsilon value is now big endian where previously it was little endian. In general this means clients should no longer reverse the bytes generated when hashing the epsilon derivation path. These new derivation paths will result in all testnet keys being lost.
- The KDF function now uses Sha3 instead of Sha2 when hashing "{EPSILON_DERIVATION_PREFIX}{predecessor_id},{path}"

1 change: 1 addition & 0 deletions chain-signatures/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions chain-signatures/crypto-shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ borsh = "1.3.0"
near-account-id = "1"
serde_json = "1"
near-sdk = { version = "5.2.1", features = ["unstable"] }
sha3 = "0.10.8"

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.12", features = ["custom"] }
Expand Down
4 changes: 2 additions & 2 deletions chain-signatures/crypto-shared/src/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use anyhow::Context;
use k256::{
ecdsa::{RecoveryId, Signature, VerifyingKey},
elliptic_curve::{point::AffineCoordinates, sec1::ToEncodedPoint, CurveArithmetic},
sha2::{Digest, Sha256},
Scalar, Secp256k1, SecretKey,
};
use near_account_id::AccountId;
use sha3::{Digest, Sha3_256};

// Constant prefix that ensures epsilon derivation values are used specifically for
// near-mpc-recovery with key derivation protocol vX.Y.Z.
Expand All @@ -20,7 +20,7 @@ pub fn derive_epsilon(predecessor_id: &AccountId, path: &str) -> Scalar {
// of the accound id in the trie key. We reuse the same constant to
// indicate the end of the account id in derivation path.
let derivation_path = format!("{EPSILON_DERIVATION_PREFIX}{},{}", predecessor_id, path);
let mut hasher = Sha256::new();
let mut hasher = Sha3_256::new();
hasher.update(derivation_path);
Scalar::from_bytes(&hasher.finalize())
}
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
cargo-watch
cargo-audit
sccache
toxiproxy

# TODO Add podman + docker image dependencies
# TODO Add AWS-CLI and dummy credentials
Expand Down
1 change: 1 addition & 0 deletions integration-tests/chain-signatures/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 17 additions & 16 deletions integration-tests/chain-signatures/tests/actions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ pub async fn single_signature_rogue_responder(

let mut mpc_pk_bytes = vec![0x04];
mpc_pk_bytes.extend_from_slice(&state.public_key.as_bytes()[1..]);

// Useful for populating the "signatures_havent_changed" test's hardcoded values
// dbg!(
// hex::encode(signature.big_r.to_encoded_point(true).to_bytes()),
// hex::encode(signature.s.to_bytes()),
// hex::encode(&mpc_pk_bytes),
// hex::encode(&payload_hash),
// account.id(),
// );
assert_signature(account.id(), &mpc_pk_bytes, &payload_hash, &signature).await;

Ok(())
Expand Down Expand Up @@ -347,23 +356,22 @@ pub async fn clear_toxics() -> anyhow::Result<()> {
Ok(())
}

// This test hardcodes the output of the signing process and checks that everything verifies as expected
// If you find yourself changing the constants in this test you are likely breaking backwards compatibility
#[tokio::test]
async fn test_signatures_verify() {
let big_r = "03d6d674dae94517646708cfde6e2e46a2e666e06b92eba19290eb0ca11d5e45dc";
let s = "2a5f2bff1b8e7da4257d480c5610d0d2c35426ee12abb87ff9c3141fe448ab27";
let mpc_key = "04cc5ed2a876b6fc54176bcde0805e469ac7eca43a97bfff90acd5babbef3a33b10d14fed35065a06a67b9a243169f33ab20bf9dab49cf6c1466a15349c011ca2b";
let account_id = "dev-20240717130550-33209224232133.test.near";
async fn signatures_havent_changed() {
let big_r = "03f13a99141ce0a4043a7c02afdec6d52f25c6b3de01967acc5cf4a3fa43801589";
let s = "39e5631fcc06ffccf8469a3cdcdce0651ebafd998a4280ebbf5dc24a749c98fb";
let mpc_key = "04b5695a882aeaf36bf3933e21911b5cbcceae7fd7cb424f3ea221c7e8d390aad4ad2c1a427faec960f22a5442739c0a04fd64ab7ce4c93980417bd3d1d8bc04ea";
let account_id = "dev-20240719125040-80075249096169.test.near";
let payload_hash: [u8; 32] =
hex::decode("7be9d96ac6895be4c59e59bb67c015f28cb94669657ddb00e8aa063f62e18031")
hex::decode("49f32740939bfdcbd8d1786075df7aca384381ec203975c3a6c1fd80acddcd4c")
.unwrap()
.try_into()
.unwrap();

let payload_hash_scalar = Scalar::from_bytes(&payload_hash);

println!("payload_hash: {payload_hash:?}");
println!("payload_hash_scallar: {payload_hash_scalar:#?}");

// Derive and convert user pk
let mpc_pk = hex::decode(mpc_key).unwrap();
let mpc_pk = EncodedPoint::from_bytes(mpc_pk).unwrap();
Expand Down Expand Up @@ -396,20 +404,13 @@ async fn test_signatures_verify() {

let signature = cait_sith::FullSignature::<Secp256k1> { big_r, s };

println!("R: {big_r:#?}");
println!("r: {r:#?}");
println!("y parity: {}", big_r_y_parity);
println!("s: {s:#?}");
println!("epsilon: {derivation_epsilon:#?}");

let multichain_sig = into_eth_sig(
&user_pk,
&signature.big_r,
&signature.s,
payload_hash_scalar,
)
.unwrap();
println!("{multichain_sig:#?}");

// Check signature using cait-sith tooling
let is_signature_valid_for_user_pk = signature.verify(&user_pk, &payload_hash_scalar);
Expand Down

0 comments on commit 3248deb

Please sign in to comment.