HIP-222: Support ECDSA(secp256k1) keys
Author | Michael Tinker |
---|---|
Discussions-To | https://github.com/hashgraph/hedera-improvement-proposal/discussions/221 |
Status | Final ⓘ |
Needs Council Approval | Yes ⓘ |
Review period ends ⓘ | Mon, 29 Nov 2021 07:00:00 +0000 |
Type | Standards Track ⓘ |
Category | Service ⓘ |
Created | 2021-11-15 |
Updated | 2022-04-26 |
Release | v0.21.0 |
Table of Contents
Abstract
The only kind of public key that may currently appear in a Hedera key structure is a Ed25519 public key. It follows that users can only secure their transactions using Ed25519 signatures.
We propose to enable support for ECDSA(secp256k1) cryptography by,
- Extending the Hedera API protobufs with new fields for ECDSA(secp256k1) keys and signatures.
- Clearly documenting how users will populate these new protobuf fields.
- Updating the node software to support ECDSA(secp256k1) keys and signatures wherever their Ed25519 equivalents are currently supported.
There are three design proposals in this HIP that, while fairly standard, deserve emphasis:
- Public keys are to be given in their compressed 33-byte form.
- The signing algorithm is to be
keccak256
-with-ECDSA; that is, clients will sign the keccak256 hash of the bytes in theirSignedTrasaction#bodyBytes
field. - The signature bytes in the
SignaturePair
for a ECDSA(secp256k1) key are to be the raw 64-byte encoding of the(r, s)
values of the ECDSA signature.
Motivation
Some users might prefer to use ECDSA(secp256k1) keys as on the Bitcoin and Ethereum networks; for example, to simplify reuse of existing client code and tooling.
Rationale
The protobuf specification below is the only natural extension of the existing Hedera API protobufs. We propose using 33-byte
compressed public keys instead of uncompressed keys because the compressed form reduces both network usage and state size. We
propose using the keccak256
-with-ECDSA signing algorithm because this is standard on the Ethereum network.
User stories
- As a smart contract developer, I want to use existing tools that assume ECDSA(secp256k1) keys.
- As an owner of a Hedera account, I want to secure transactions involving my account with a ECDSA(secp256k1) key.
- As the creator of a Hedera token, I want the supply manager role to be controlled by a ECDSA(secp256k1) keys.
Specification
Only two protobuf changes are required. To the Key
message type, we need to extend the oneof key
with a new choice:
message Key {
oneof key {
...
/**
* Compressed ECDSA(secp256k1) public key bytes
*/
bytes ECDSA_secp256k1 = 7;
To the SignaturePair
message type, we need to extend the oneof signature
with a new choice:
message SignaturePair {
...
oneof signature {
...
/**
* The 64-byte ECDSA(secp256k1) signature of the keccak256 hash of the body bytes, with
* the (r, s) values of the signature concatenated in unsigned big-endian form.
*/
bytes ECDSA_secp256k1 = 6;
When a user is creating or updating a Hedera key structure to include a ECDSA(secp256k1) public key, they should set the bytes of the Key.ECDSA_secp256k1
field to the compressed form of the public key. (That is, the first byte should be 0x02
if the y
-coordinate of the key is even, and 0x03
if the y
-coordinate is odd; and the following 32 bytes should be the x
-coordinate as an unsigned 256-bit integer.)
For example, if the uncompressed public key of the user’s key pair is,
0x043232a86a9f267290db881b82547ae53eb4d7a917324a494e4f938a7092be4924e9c4e57a4469664ec57d4688a1c100945f8772308701739b86bc2745d2dbb0f6
Then the hex-encoded bytes of the Key.ECDSA_secp256k1
field should be,
0x023232a86a9f267290db881b82547ae53eb4d7a917324a494e4f938a7092be4924
When a user is providing an ECDSA(secp256k1) signature in a SignaturePair.ECDSA_secp256k1
field, it should be the 64-byte “raw” encoding of the (r, s)
values that result from from signing the keccak256 hash of the SignedTransaction.bodyBytes
from the top-level Transaction
with the relevant ECDSA(secp256k1) private key. (That is, the signature bytes should be the concatentation of the r
and s
values in unsigned big-endian form.)
For example, if the user is signing the keccak256 digest,
0x744c77a7af70b3a522009f0a963384eccfa77662a594d6e0247dfba095eb48d5
with the private key,
0x7f327369608f973b63ab29cfebd9de54ffc39cc060c1bdae9ba79bfb7ef5028c
Then the signature bytes should be,
0x60498ba4ae336e76924d8d047c9991f873ebd21ee6d8672681273d6633d8044a7ce0d3f0203587f085fcd3d5a9c3ba72cbf7eef5a4771cfb14415f01618cc831
Backwards Compatibility
This HIP does not make any breaking changes. Clients that continue to use Ed25519 keys and signatures will be unaffected.
Security Implications
If we observe a significant performance impact when verifying ECDSA(secp256k1) signatures compared to Ed25519 signatures, we will need to throttle transactions with ECDSA(secp256k1) signatures at a lower TPS.
How to Teach This
In one sentence: “Allow Hedera entities to be secured using ECDSA(secp256k1) keys and signatures.”
Reference Implementation
Ongoing.
- For protobufs changes, please follow this issue.
- For node software changes, please follow issues with the label “secp256k1”.
Rejected Ideas
No other designs seemed natural.
Open Issues
Signature verification is done through the Platform SDK, so the node software depends on the SDK being updated to also verify ECDSA(secp256k1) signatures with acceptable performance.
References
Copyright/license
This document is licensed under the Apache License, Version 2.0 – see LICENSE or (https://www.apache.org/licenses/LICENSE-2.0)
Citation
Please cite this document as: