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

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

Closed
sleepdefic1t opened this issue Oct 13, 2022 · 1 comment
Closed

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

sleepdefic1t opened this issue Oct 13, 2022 · 1 comment
Labels
enhancement New feature or request

Comments

@sleepdefic1t
Copy link
Contributor

sleepdefic1t commented Oct 13, 2022

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., #50)

Solution

Add the following to rosetta-specifications:

  • ./models/CurveType.yaml - Secp256k1Bip340
  • ./models/SignatureType.yaml - SchnorrBip340

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

  • ./keys/keys.go - Key Import & Generation
  • ./keys/signer_bip340.go - Sign & Verify

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

  • Accept the import of any standard secp256k1 privateKey and drop the first byte (compression odd/even flag) of its associated publicKey per BIP-340 spec to extend backward compatibility.
    • This results in a 32-byte publicKey vs. secp256k1's 33-byte compressed publicKey.
    • No further tweaks need to be performed to an imported keyPair as the Sign/Verify scheme implicitly chooses the 'Y' coordinates that are a quadratic residue.

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

  • Explicitly choose the keyPair whose public key has a Y value that is a quadratic residue by negating the newly-generated privateKey when its associated public key is found to be 'odd' in its compressed form.

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 sleepdefic1t added the enhancement New feature or request label Oct 13, 2022
@sleepdefic1t
Copy link
Contributor Author

Discussion continued in #113

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

No branches or pull requests

1 participant