Skip to content

Commit

Permalink
Add ES256K sign and verify test vectors (#104)
Browse files Browse the repository at this point in the history
Signed-off-by: Frank Hinek <[email protected]>
  • Loading branch information
frankhinek authored Jan 16, 2024
1 parent 455df9a commit 736eae6
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 0 deletions.
70 changes: 70 additions & 0 deletions web5-test-vectors/crypto_es256k/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# `ES256K` Test Vectors

This directory contains test vectors for the secp256k1 with SHA-256 signature scheme, which is a
part of the Elliptic Curve Digital Signature Algorithm (ECDSA) family of signature algorithms as
detailed in the Standards for Efficient Cryptography Group (SECG) publication
[SEC1](https://www.secg.org/sec1-v2.pdf).

The `ES256K` algorithm identifier is defined in
[RFC8812](https://datatracker.ietf.org/doc/html/rfc8812), which specifies the use of ECDSA with the
secp256k1 curve and the SHA-256 cryptographic hash function.

> [!IMPORTANT]
> All ECDSA signatures, regardless of the curve, are subject to signature malleability such that
> for every valid signature there is a "mirror" signature that's equally valid for the same message
> and public key. Read more
> [here](https://github.com/TBD54566975/web5-js/blob/f4e8194301be302889c031fb904425ff1a7b34aa/packages/crypto/src/primitives/secp256k1.ts#L75-L101)
> about the practical implications and mitigation techniques.
## `sign`

Sign test vectors are detailed in a [JSON file](./sign.json). It includes cases for testing the
signing operation with the secp256k1 curve and SHA-256 hash function.

### Input

The `input` for the sign operation is an object with the following properties:

| Property | Description |
| -------- | -------------------------------------------------------------------- |
| `key` | A JSON Web Key ([JWK][RFC7517]) object representing the private key. |
| `data` | The data to be signed, as a byte array in hexadecimal string format. |

### Output

The `output` is a hexadecimal string representing the signature byte array produced by the signing
operation.

### 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)

## `verify`

Verify test vectors are outlined in a [JSON file](./verify.json), encompassing both successful and unsuccessful signature verification cases.

### Input

The `input` for the verify operation includes:

| Property | Description |
| ----------- | -------------------------------------------------------------------------------- |
| `key` | An JSON Web Key ([JWK][RFC7517]) object representing the public key. |
| `signature` | The signature to verify, as a byte array in hexadecimal string format. |
| `data` | The original data that was signed, as a byte array in hexadecimal string format. |

### Output

The `output` is a boolean value indicating whether the signature verification was successful
(`true`) or not (`false`).

### Reference Implementations

Reference implementations for the verify operation can also be found in the following SDK
repositories:

- TypeScript: [`Secp256k1.verify()`](https://github.com/TBD54566975/web5-js/blob/44c38a116dec0b357ca15d807eb513f819341e50/packages/crypto/src/primitives/secp256k1.ts#L670-L724)

[RFC7517]: https://datatracker.ietf.org/doc/html/rfc7517
65 changes: 65 additions & 0 deletions web5-test-vectors/crypto_es256k/sign.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"description": "ES256K sign test vectors",
"vectors": [
{
"description": "always generates low-S form signatures",
"input": {
"data": "333435",
"key": {
"crv": "secp256k1",
"d": "lZqISvM7R1S7zBgZ5JjUuOppZuYKXuCbYWBkqgwX88c",
"kid": "JOeO0oJDLMaXibhJBpsHVvskK47qq0k8uaLozxTtNhk",
"kty": "EC",
"x": "npaD6WyM4AZIxwPmieND_gdnYuROitnyDfskXwpv-J0",
"y": "y5_uOFRRNOCWAJPD-Ly1ENJd908lWJ0-0KGnTwxWzNM"
}
},
"output": "95b9c99642a5765b4f5f4648671dbad2ad107f7507f1e538eb4ad365caf76a4d321db3e3682f5124d37c597b6f2b489171c6b7d90e82f67a87a7e4d8783f4d63",
"errors": false
},
{
"description": "error when given a public key",
"input": {
"data": "",
"key": {
"crv": "secp256k1",
"kid": "JOeO0oJDLMaXibhJBpsHVvskK47qq0k8uaLozxTtNhk",
"kty": "EC",
"x": "npaD6WyM4AZIxwPmieND_gdnYuROitnyDfskXwpv-J0",
"y": "y5_uOFRRNOCWAJPD-Ly1ENJd908lWJ0-0KGnTwxWzNM"
}
},
"errors": true
},
{
"description": "error with invalid private key == 0 (not on curve)",
"input": {
"data": "0000000000000000000000000000000000000000000000000000000000000001",
"key": {
"kty": "EC",
"crv": "secp256k1",
"d": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"x": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"y": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"kid": "bBw8BkYm7Aeo-e8Xzbc76irs8TtXtPxvCIZiUuuU-PY"
}
},
"errors": true
},
{
"description": "error with invalid private key >= G (not on curve)",
"input": {
"data": "0000000000000000000000000000000000000000000000000000000000000001",
"key": {
"kty": "EC",
"crv": "secp256k1",
"d": "__________________________________________8",
"x": "__________________________________________8",
"y": "__________________________________________8",
"kid": "W-Oix7HogMrpbP0tj98DA8McTn2MLUEo9LYlbfk3-lA"
}
},
"errors": true
}
]
}
132 changes: 132 additions & 0 deletions web5-test-vectors/crypto_es256k/verify.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{
"description": "ES256K verify test vectors",
"vectors": [
{
"description": "verifies the signature from Wycheproof test case 3",
"input": {
"data": "313233343030",
"key": {
"crv": "secp256k1",
"kid": "i8L_MOOCkkDoHKY1a8cXtZ2BSTLWzD29eiCUiR555ts",
"kty": "EC",
"x": "uDj_ROW8F3vyEYnQdmCC_J2EMiaIf8l2A3EQC37iCm8",
"y": "8MnXW_unsxpryhl0SW7rVt41cHGVXYPEsbraoLIYMuk"
},
"signature": "813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba"
},
"output": true,
"errors": false
},
{
"description": "verifies low-S form signatures",
"input": {
"data": "333435",
"key": {
"crv": "secp256k1",
"kid": "9l2x1L-iUvyCy4RuqJdoqe7h0IPnCVXPjTHhVYCuLAc",
"kty": "EC",
"x": "A2ZbCLhod3ltBQ4Mw0zjkcQZ7h7B1FQ3s56ZtWavonQ",
"y": "JBerPwkut8tONfAfcXhNEBERj7jejohqMfbbs2aMMZA"
},
"signature": "351757c538d0a13fa9473dabc259be82dba1bd8f44dcba71a7f222655429b4700608736ab97d0b31bae1a0c2cac4b35eeaf35f767f5ebdafdff042a68739dfb4"
},
"output": true,
"errors": false
},
{
"description": "verifies high-S form signatures",
"input": {
"data": "333435",
"key": {
"crv": "secp256k1",
"kid": "9l2x1L-iUvyCy4RuqJdoqe7h0IPnCVXPjTHhVYCuLAc",
"kty": "EC",
"x": "A2ZbCLhod3ltBQ4Mw0zjkcQZ7h7B1FQ3s56ZtWavonQ",
"y": "JBerPwkut8tONfAfcXhNEBERj7jejohqMfbbs2aMMZA"
},
"signature": "351757c538d0a13fa9473dabc259be82dba1bd8f44dcba71a7f222655429b470f9f78c954682f4ce451e5f3d353b4c9fcfbb7d702fe9e28bdfe21be648fc618d"
},
"output": true,
"errors": false
},
{
"description": "verification fails if the data was tampered with",
"input": {
"data": "0002030405060708",
"key": {
"kty": "EC",
"crv": "secp256k1",
"x": "fmCdLkmSfkAW0sKwrDegDsCcIKVUC_S6RBSGqrqNDzw",
"y": "qG4iddPl2ddQS4QRGloxXJDMwqT6cwHEFr9o0_aXp0s",
"kid": "yF4nEQmfgPjaZSudWp55n0oD486mWw2S0tG6G0Vs9ds"
},
"signature": "efcd2eb0df4137bf3993149b8dc0956aea9858c83c270ea0fcbf6fb8da77573d1e49798da017740b5e948a099cdc2abcda43421bc872c4ae1370de4661f9d879"
},
"output": false,
"errors": false
},
{
"description": "verification fails if the signature was tampered with",
"input": {
"data": "0102030405060708",
"key": {
"kty": "EC",
"crv": "secp256k1",
"x": "oFYWfw35gaUsuUKXTEfq9i0Rg8bJI8aautX7uUy-BlI",
"y": "CXnzACqBqCFvP5zEmolhFiuQJ7MFY6yiMDHKxiLv8SM",
"kid": "AkWUHqaYZCNM06UeEGCDKwYJD1fXNFqB4JOzmqFDTCQ"
},
"signature": "3ce28829b29db2fce5ab3fbc1dd6822dc29787e806573ded683003a80e4bca85221b4c5e39c43117bbadb63dccd3649223729c5b5847f74935cfd6d810584de6"
},
"output": false,
"errors": false
},
{
"description": "verification fails if the public key is not associated with the signing key",
"input": {
"data": "0102030405060708",
"key": {
"kty": "EC",
"crv": "secp256k1",
"x": "rZumJRfoU39x5arLh3g6geDFnikLRpCsTneNOvWeAXw",
"y": "ACJk2iPQZinwFT6MeGEwu29jFxuvqjlEXA7jbaSYNx8",
"kid": "J15CEGRafTv4gR3jr3zaWqsO5txEzcxICDBhJO-bkRw"
},
"signature": "006b365af98e60c9dd89884391bc2d41aa078586a899e7fff07104683a3195ec323589cf5050a4d485a2e6c281561f378dd0a9663954236b5d20fd64519bcbe7"
},
"output": false,
"errors": false
},
{
"description": "error when given a private key",
"input": {
"data": "",
"key": {
"crv": "secp256k1",
"d": "lZqISvM7R1S7zBgZ5JjUuOppZuYKXuCbYWBkqgwX88c",
"kid": "JOeO0oJDLMaXibhJBpsHVvskK47qq0k8uaLozxTtNhk",
"kty": "EC",
"x": "npaD6WyM4AZIxwPmieND_gdnYuROitnyDfskXwpv-J0",
"y": "y5_uOFRRNOCWAJPD-Ly1ENJd908lWJ0-0KGnTwxWzNM"
},
"signature": "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"
},
"errors": true
},
{
"description": "error with invalid public key X > P (not on curve)",
"input": {
"data": "",
"key": {
"crv": "secp256k1",
"kid": "zrExdhAYVSioQSqh8uTqzc1GEpEKGBax6Q7J8UdBt0s",
"kty": "EC",
"x": "_____________________________________v___DA",
"y": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE"
},
"signature": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"
},
"errors": true
}
]
}

0 comments on commit 736eae6

Please sign in to comment.