coinbase / mesh-specifications

Specification files for the Mesh Blockchain Standard
Apache License 2.0
327 stars 93 forks source link

[Prop] Add Support for BIP-340 Schnorr #112

Closed sleepdefic1t closed 2 years ago

sleepdefic1t commented 2 years ago

Bitcoin's BIP-340 Schnorr signature scheme is a secp256k1 curve variant not directly supported by Rosetta.

The primary outward distinction between the Ecdsa/Secp256k1 scheme and BIP-340 is the use of x-only 32-byte publicKeys and 64-byte ([R,s]) signatures.

BIP-340's underlying Sign/Verify scheme also internally encodes the signing keyPairs' signature and public point as its variants whose 'Y' coordinates are a quadratic residue ('even'). (see more here: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#design)

Benefits

BIP-340 provides greater (provable) security than ECDSA/secp256k1-based schemes and offers signature non-malleability and linearity. Signing also makes use of "tagged hashes" to mitigate things like related-key attacks, which accordingly "...increases robustness in multi-user settings."

While this proposal to introduce BIP-340 does not include multisignature support, this would be a likely precondition to doing so. (e.g., https://github.com/coinbase/rosetta-specifications/issues/50)

Solution

Add the following to rosetta-specifications:

Once approved and released, implement the following in rosetta-sdk-go including any relevant tests:

It should be mentioned that the new CurveType is necessary due to BIP-340's requirement of 32-byte/x-only keys while the existing rosetta-sdk-go key interface extends no such ability under the existing Secp256k1 curve.

CurveType

rosetta-specifications

# CurveType.yaml

description: |
  CurveType is the type of cryptographic curve associated with a PublicKey.
  * secp256k1: SEC compressed - `33 bytes` (https://secg.org/sec1-v2.pdf#subsubsection.2.3.3)
+ * secp256k1_bip340: x-only - `32 bytes`  (implicitly even `Y` coord. Secp256k1 compressed keys may be repurposed by dropping the first byte. (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#Public_Key_Generation))
  * secp256r1: SEC compressed - `33 bytes` (https://secg.org/sec1-v2.pdf#subsubsection.2.3.3)
  * edwards25519: `y (255-bits) || x-sign-bit (1-bit)` - `32 bytes` (https://ed25519.cr.yp.to/ed25519-20110926.pdf)
  * tweedle: 1st pk : Fq.t (32 bytes) || 2nd pk : Fq.t (32 bytes) (https://github.com/CodaProtocol/coda/blob/develop/rfcs/0038-rosetta-construction-api.md#marshal-keys)
  * pallas: `x (255 bits) || y-parity-bit (1-bit) - 32 bytes` (https://github.com/zcash/pasta)
type: string
enum:
  - secp256k1
+ - secp256k1_bip340
  - secp256r1
  - edwards25519
  - tweedle
  - pallas

rosetta-sdk-go Key Import

The above would be implemented in rosetta-sdk-go in the file ./keys/keys.go and add the import of the following package:

  • "github.com/btcsuite/btcd/btcec/v2"

*note that github.com/btcsuite/btcd packages are already used by rosetta-sdk-go.

rosetta-sdk-go Key Generation

The above would be implemented in rosetta-sdk-go in the file ./keys/keys.go and add the import of the following package:

  • "github.com/btcsuite/btcd/btcec/v2"

*note that github.com/btcsuite/btcd packages are already used by rosetta-sdk-go.

References

SignatureType

rosetta-specifications

# SignatureType.yaml

description: |
  SignatureType is the type of a cryptographic signature.
  * ecdsa: `r (32-bytes) || s (32-bytes)` - `64 bytes`
  * ecdsa_recovery: `r (32-bytes) || s (32-bytes) || v (1-byte)` - `65 bytes`
  * ed25519: `R (32-byte) || s (32-bytes)` - `64 bytes`
  * schnorr_1: `r (32-bytes) || s (32-bytes)` - `64 bytes`  (schnorr signature implemented by Zilliqa where both `r` and `s` are scalars encoded as `32-bytes` values, most significant byte first.)
+ * schnorr_bip340: `r (32-bytes) || s (32-bytes)` - `64 bytes`  (sig = (bytes(R) || bytes((k + ed) mod n) where `r` is the `X` coordinate of a point `R` whose `Y` coordinate is even, most significant bytes first.)
  * schnorr_poseidon: `r (32-bytes) || s (32-bytes)` where s = Hash(1st pk || 2nd pk || r) - `64 bytes`  (schnorr signature w/ Poseidon hash function implemented by O(1) Labs where both `r` and `s` are scalars encoded as `32-bytes` values, least significant byte first. https://github.com/CodaProtocol/signer-reference/blob/master/schnorr.ml )
type: string
enum:
  - ecdsa
  - ecdsa_recovery
  - ed25519
  - schnorr_1
+ - schnorr_bip340
  - schnorr_poseidon

rosetta-sdk-go Sign & Verify

The above would be implemented in rosetta-sdk-go as the file ./keys/signer_bip340.go and make use of the following import packages:

  • "github.com/btcsuite/btcd/btcec/v2"
  • "github.com/btcsuite/btcd/btcec/v2/schnorr"

*note that github.com/btcsuite/btcd packages are already used by rosetta-sdk-go.

Backwards Compatible

Key Imports: Yes
Everything Else: n/a

sleepdefic1t commented 2 years ago

Discussion continued in #113