-
Notifications
You must be signed in to change notification settings - Fork 5
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
Add ES256K sign and verify test vectors #104
Conversation
Signed-off-by: Frank Hinek <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love the detailed docs!
### Reference Implementations | ||
|
||
Reference implementations for the sign operation can be found in the following SDK repositories: | ||
|
||
- TypeScript: [`Secp256k1.sign()`](https://github.com/TBD54566975/web5-js/blob/44c38a116dec0b357ca15d807eb513f819341e50/packages/crypto/src/primitives/secp256k1.ts#L547-L595) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused by this reference after reading the PR description here.
Both the sign
and verify
references are simply Secp256k1.sign()
or Secp256k1.verify()
. But in the same token, this PR description has a note with the following opening line:
This test vector was intentionally named ES256K and not Secp256k1 as it tests the sign and verify operations of a concrete implementation of the ECDSA algorithm with the secp256k1 curve and SHA-256 hash function.
Does this mean that the implementation of secp256k1
does an ES256K
signature by default? Why isn't it passed in as a parameter to the reference implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow up to clarify this part of the note:
There are other non-signature algorithms (e.g., ECDH, ECIES, etc.) that the secp256k1 curve can be used with and other hash functions (e.g., SHA-384 or SHA-512) that can be used with ECDSA+secp256k1. There are even other signature algorithms (e.g., Schnorr) that can use both secp256k1 and SHA-256.
How does Secp256k1.sign()
or Secp256k1.verify()
differentiate between the different algorithms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good questions @amika-sq
Does this mean that the implementation of secp256k1 does an ES256K signature by default? Why isn't it passed in as a parameter to the reference implementation?
How does Secp256k1.sign() or Secp256k1.verify() differentiate between the different algorithms?
The test vector doesn't dictate how the implementation is constructed at that level of granularity. There are slight differences in implementation design (e.g., method signatures, return values, error handling, etc.) across the SDKs, largely due to idiomatic differences (which team consensus has viewed as a positive for dev ex).
Instead, the test vector validates that an implementation of ECDSA + secp256k1 + SHA-256 produces the expected output given the input. For example, the following data (hex string) and private key:
{
"data": "333435",
"key": {
"crv": "secp256k1",
"d": "lZqISvM7R1S7zBgZ5JjUuOppZuYKXuCbYWBkqgwX88c",
"kid": "JOeO0oJDLMaXibhJBpsHVvskK47qq0k8uaLozxTtNhk",
"kty": "EC",
"x": "npaD6WyM4AZIxwPmieND_gdnYuROitnyDfskXwpv-J0",
"y": "y5_uOFRRNOCWAJPD-Ly1ENJd908lWJ0-0KGnTwxWzNM"
}
}
should result in a signature matching the hex string 95b9c99642a5765b4f5f4648671dbad2ad107f7507f1e538eb4ad365caf76a4d321db3e3682f5124d37c597b6f2b489171c6b7d90e82f67a87a7e4d8783f4d63
Whether or not a particular implementation provides an argument in sign
or verify
to specify the hash function or uses a Result<>
return type, this vector can be used without modification. It could also be used by an implementation of ECDSA that supports multiple elliptic curve and hash functions as it would only be used for testing in the secp256k1 + SHA-256 case (and we can add vectors for ES256
, ES384
, secp256k1+SHA-512, etc. if there's a practical reason to).
In general, the idea was to map the vector naming to the algorithm identifiers we're using, which are JOSE algorithm identifiers unless one does not exist.
This PR will:
sign
andverify
operationsweb5-js
, where they are currently being used.Note
This test vector was intentionally named
ES256K
and notSecp256k1
as it tests thesign
andverify
operations of a concrete implementation of the ECDSA algorithm with the secp256k1 curve and SHA-256 hash function.The
ES256K
algorithm identifier is defined in RFC8812, which specifies the use of ECDSA with the secp256k1 curve and the SHA-256 cryptographic hash function. This provides a succinct and unambiguous identifier for this combination of signature algorithm (ECDSA), curve (secp256k1), and hash function (SHA-256). The same algorithm identifiers are used broadly across JSON Object Signing and Encryption (JOSE) standards and when working with DIDs and VCs.There are other non-signature algorithms (e.g., ECDH, ECIES, etc.) that the secp256k1 curve can be used with and other hash functions (e.g., SHA-384 or SHA-512) that can be used with ECDSA+secp256k1. There are even other signature algorithms (e.g., Schnorr) that can use both secp256k1 and SHA-256.
closes #84