Feat/unified secp256k1 k256#7305
Open
rob-stacks wants to merge 12 commits into
Open
Conversation
5 tasks
Contributor
|
I added @benjamin-stacks as a reviewer since he's just been making changes in here. I'll review after he does a pass. 🙏 |
benjamin-stacks
left a comment
Contributor
There was a problem hiding this comment.
Just did an initial pass and pointed out a few things that we don't have to implement because they're already provided by those crates.
Will have a deeper look once develop with 30ee31d is merged into this branch.
Comment on lines
+267
to
+277
| fn is_low_s(sig: &K256Signature) -> bool { | ||
| // secp256k1 group order n divided by 2 (big-endian) | ||
| const HALF_ORDER: [u8; 32] = [ | ||
| 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 0xff, 0x5d, 0x57, 0x6e, 0x73, 0x57, 0xa4, 0x50, 0x1d, 0xdf, 0xe9, 0x2f, 0x46, 0x68, 0x1b, | ||
| 0x20, 0xa0, | ||
| ]; | ||
| // GenericArray<u8, U64> derefs to [u8] | ||
| let bytes = sig.to_bytes(); | ||
| bytes[32..64] <= HALF_ORDER[..] | ||
| } |
Contributor
There was a problem hiding this comment.
Suggested change
| fn is_low_s(sig: &K256Signature) -> bool { | |
| // secp256k1 group order n divided by 2 (big-endian) | |
| const HALF_ORDER: [u8; 32] = [ | |
| 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0x5d, 0x57, 0x6e, 0x73, 0x57, 0xa4, 0x50, 0x1d, 0xdf, 0xe9, 0x2f, 0x46, 0x68, 0x1b, | |
| 0x20, 0xa0, | |
| ]; | |
| // GenericArray<u8, U64> derefs to [u8] | |
| let bytes = sig.to_bytes(); | |
| bytes[32..64] <= HALF_ORDER[..] | |
| } | |
| fn is_low_s(sig: &K256Signature) -> bool { | |
| !bool::from(sig.s().is_high()) | |
| } |
Comment on lines
+545
to
+560
| fn negate_secp256k1_scalar(s: &[u8; 32]) -> [u8; 32] { | ||
| // secp256k1 group order n | ||
| const N: [u8; 32] = [ | ||
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
| 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, | ||
| 0xD0, 0x36, 0x41, 0x41, | ||
| ]; | ||
| let mut result = [0u8; 32]; | ||
| let mut borrow: i32 = 0; | ||
| for i in (0..32).rev() { | ||
| let diff = N[i] as i32 - s[i] as i32 - borrow; | ||
| result[i] = diff.rem_euclid(256) as u8; | ||
| borrow = if diff < 0 { 1 } else { 0 }; | ||
| } | ||
| result | ||
| } |
Contributor
There was a problem hiding this comment.
Suggested change
| fn negate_secp256k1_scalar(s: &[u8; 32]) -> [u8; 32] { | |
| // secp256k1 group order n | |
| const N: [u8; 32] = [ | |
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
| 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, | |
| 0xD0, 0x36, 0x41, 0x41, | |
| ]; | |
| let mut result = [0u8; 32]; | |
| let mut borrow: i32 = 0; | |
| for i in (0..32).rev() { | |
| let diff = N[i] as i32 - s[i] as i32 - borrow; | |
| result[i] = diff.rem_euclid(256) as u8; | |
| borrow = if diff < 0 { 1 } else { 0 }; | |
| } | |
| result | |
| } | |
| fn negate_secp256k1_scalar(s: &[u8; 32]) -> [u8; 32] { | |
| let s = NonZeroScalar::<Secp256k1>::try_from(&s[..]) | |
| .expect("s must be a non-zero value from the secp256k1 field"); | |
| s.negate().to_bytes().into() | |
| } |
Comment on lines
+138
to
+142
| pub fn to_der_signature(&self) -> Option<Vec<u8>> { | ||
| let (sig, _) = self.to_secp256k1_recoverable()?; | ||
| let bytes: [u8; 64] = sig.to_bytes().into(); | ||
| Some(secp256k1_der_encode(&bytes)) | ||
| } |
Contributor
There was a problem hiding this comment.
Suggested change
| pub fn to_der_signature(&self) -> Option<Vec<u8>> { | |
| let (sig, _) = self.to_secp256k1_recoverable()?; | |
| let bytes: [u8; 64] = sig.to_bytes().into(); | |
| Some(secp256k1_der_encode(&bytes)) | |
| } | |
| pub fn to_der_signature(&self) -> Option<Vec<u8>> { | |
| let (sig, _) = self.to_secp256k1_recoverable()?; | |
| Some(sig.to_der().to_vec()) | |
| } |
Since this functionality is provided by the ecdsa crate, we can avoid the custom implementation secp256k1_der_encode.
It looks like it was fun to implement though 😅 But I'd rather we reinvented as few wheels as possible.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This patch unifies the secp256k1 curve api to use the k256 crate (https://crates.io/crates/k256)
Additional unit tests have been added to ensure the whole api is covered
Applicable issues
Additional info (benefits, drawbacks, caveats)
Checklist
docs/property-testing.md)changelog.d/README.md)rpc/openapi.yamlfor RPC endpoints,event-dispatcher.mdfor new events)clarity-benchmarkingrepo