Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(crypto): CRP-2579 Add support for derivation to ecdsa_secp256r1 crate #1730

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

randombit
Copy link
Contributor

In order to remove the dependency on the internal threshold ECDSA protocol implementation from ic-crypto-utils-canister-threshold-sig we have to have derivation available in the 3 signature utility crates.

…crate

In order to remove the dependency on the internal threshold ECDSA
protocol implementation from ic-crypto-utils-canister-threshold-sig we
have to have derivation available in the 3 signature utility crates.
@randombit randombit requested a review from a team as a code owner September 27, 2024 20:44
@github-actions github-actions bot added the feat label Sep 27, 2024
Copy link
Member

@fspreiss fspreiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @randombit! Looks good to me! Find some minor comments below.

) -> (Self, [u8; 32]) {
use p256::NonZeroScalar;

let public_key: AffinePoint = self.key.verifying_key().as_affine().clone();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clippy has a comment here:

error: using `clone` on type `AffinePoint<NistP256>` which implements the `Copy` trait
   --> rs/crypto/ecdsa_secp256r1/src/lib.rs:473:39
    |
473 |         let public_key: AffinePoint = self.key.verifying_key().as_affine().clone();
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*self.key.verifying_key().as_affine()`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy
    = note: `-D clippy::clone-on-copy` implied by `-D clippy::all`
    = help: to override `-D clippy::all` add `#[allow(clippy::clone_on_copy)]`

Comment on lines +443 to +447
/// As long as each index of the derivation path is a 4-byte input with the highest
/// bit cleared, this derivation scheme matches SLIP-10
///
/// See <https://internetcomputer.org/docs/current/references/ic-interface-spec#ic-ecdsa_public_key>
/// for details on the derivation scheme.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The given URL actually doesn't give any details on the derivation scheme for curves different from secp256k1. How about creating a ticket to improve this (e.g., to mention SLIP-10)?

Comment on lines +51 to +52
/// Create a BIP32-style derivation path
pub fn new_bip32(bip32: &[u32]) -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It this intentionally called new_bip32, given that BIP32 isn't defined for secp256r1? IIUC, the derivation is done as per SLIP10, but given that SLIP10 is a generalization of BIP32, it might make sense to call it new_bip32 nevertheless.

NonZeroScalar::new(derived_scalar).expect("Derivation always produces non-zero sum");

let derived_key = Self {
key: p256::SecretKey::from(nz_ds).into(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems we can also go directly: p256::ecdsa::SigningKey::from(nz_ds)

@@ -374,7 +554,7 @@ impl PublicKey {
/// valid signature, then (r,-s) is also valid. To avoid this malleability,
/// some systems require that s be "normalized" to the smallest value.
///
/// This normalization is quite common on secp256k1, but is virtually
/// This normalization is quite common on secp256r1, but is virtually
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this change intentional? The text now says: "normalization is common on r1, but is unknown for r1".

Comment on lines +609 to +612
key: p256::PublicKey::from(
p256::PublicKey::from_affine(pt).expect("Derived point is valid"),
)
.into(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems one conversion layer is to itself, so it should be obsolete. Also, how about being explicit (instead of doing into). As a result, I suggest we do

            key: p256::ecdsa::VerifyingKey::from(
                p256::PublicKey::from_affine(pt).expect("Derived point is valid"),
            ),

assert!(derived_pk.verify_signature(&msg, &derived_sig));
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some key derivations, we also have a test private_derivation_also_works_for_derived_keys: would that be applicable here as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants