Skip to content

Commit

Permalink
crypto: ser/de update and use nonrecoverable sig for secp256k1/r1 (My…
Browse files Browse the repository at this point in the history
…stenLabs#7423)

## What Changed

- For CLI and SDK, a ECDSA k1 and r1 signature is produced using the
nonrecoverable form. This means the signature is 64 bytes instead of 65.
- The signature verification in sui also uses the nonrecoverable option.
A valid signature should have 64 bytes.
- For wallet, since only Ed25519 is supported, the secp256k1 change
should not affect.
- Also exposes secp256k1_verify and secp256k1_verify_recoverable API in
move.
- Ser/de of public keys and signatures now uses the most compact
serialization with ToFromBytes.

## What Do You Need To Do
- If you are using SDK to produce a Secp256k1 signature, no change is
needed as long as you are using the latest version.
- If you are using something else to produce a signature, your old
signature will not be considered valid. You should just need to remove
the last byte (65->64 bytes) to make it a valid signature again.

Next:
- r1 verify and verify_recoverable added in
MystenLabs#7773
  • Loading branch information
joyqvq authored Jan 30, 2023
1 parent 7753ad8 commit 21781ba
Show file tree
Hide file tree
Showing 19 changed files with 350 additions and 135 deletions.
5 changes: 5 additions & 0 deletions .changeset/wicked-cats-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@mysten/sui.js": minor
---

Secp256k1 signs 64-bytes signature [r, s] instead of [r, s, v] with recovery id
91 changes: 67 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ move-prover-boogie-backend = { git = "https://github.com/move-language/move", re
move-stackless-bytecode = { git = "https://github.com/move-language/move", rev = "3b20af5ef98b368a9bf405e9b39362443c964946" }
move-symbol-pool = { git = "https://github.com/move-language/move", rev = "3b20af5ef98b368a9bf405e9b39362443c964946" }

fastcrypto = { git = "https://github.com/MystenLabs/fastcrypto", rev = "f451422b7f15e75e055a1830cbe5d1547fa87b74" }
fastcrypto-zkp = { git = "https://github.com/MystenLabs/fastcrypto", rev = "f451422b7f15e75e055a1830cbe5d1547fa87b74", package = "fastcrypto-zkp" }
fastcrypto-tbls = { git = "https://github.com/MystenLabs/fastcrypto", rev = "f451422b7f15e75e055a1830cbe5d1547fa87b74", package = "fastcrypto-tbls" }
fastcrypto = { git = "https://github.com/MystenLabs/fastcrypto", rev = "235211dc8195590f5353d38135f5ee51a267521e" }
fastcrypto-zkp = { git = "https://github.com/MystenLabs/fastcrypto", rev = "235211dc8195590f5353d38135f5ee51a267521e", package = "fastcrypto-zkp" }
fastcrypto-tbls = { git = "https://github.com/MystenLabs/fastcrypto", rev = "235211dc8195590f5353d38135f5ee51a267521e", package = "fastcrypto-tbls" }

# anemo dependencies
anemo = { git = "https://github.com/mystenlabs/anemo.git", rev = "0e0ef7054082a6f5a8921688e3d568761bc3be21" }
Expand Down
4 changes: 3 additions & 1 deletion apps/wallet/src/background/keyring/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export class Account {
async sign(data: Base64DataBuffer): Promise<SignaturePubkeyPair> {
return {
signatureScheme: this.#keypair.getKeyScheme(),
signature: this.#keypair.signData(data),
// TODO(joyqvq): Remove once 0.25.0 is released.
// This is fine to hardcode useRecoverable = false because wallet does not support Secp256k1. Ed25519 does not use this parameter.
signature: this.#keypair.signData(data, false),
pubKey: this.#keypair.getPublicKey(),
};
}
Expand Down
39 changes: 36 additions & 3 deletions crates/sui-framework/docs/ecdsa_k1.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- [Function `decompress_pubkey`](#0x2_ecdsa_k1_decompress_pubkey)
- [Function `keccak256`](#0x2_ecdsa_k1_keccak256)
- [Function `secp256k1_verify`](#0x2_ecdsa_k1_secp256k1_verify)
- [Function `secp256k1_verify_recoverable`](#0x2_ecdsa_k1_secp256k1_verify_recoverable)


<pre><code></code></pre>
Expand Down Expand Up @@ -126,9 +127,10 @@ Hash the input bytes using keccak256 and returns 32 bytes.

## Function `secp256k1_verify`

@param signature: A 65-bytes signature in form (r, s, v) that is signed using
Secp256k1. Reference implementation on signature generation using RFC6979:
https://github.com/MystenLabs/narwhal/blob/5d6f6df8ccee94446ff88786c0dbbc98be7cfc09/crypto/src/secp256k1.rs
@param signature: A 64-bytes signature in form (r, s) that is signed using
Secp256k1. This is an non-recoverable signature without recovery id.
Reference implementation on signature generation using RFC6979:
https://github.com/MystenLabs/fastcrypto/blob/74aec4886e62122a5b769464c2bea5f803cf8ecc/fastcrypto/src/secp256k1/mod.rs#L193

@param public_key: The public key to verify the signature against
@param hashed_msg: The hashed 32-bytes message, same as what the signature is signed against.
Expand All @@ -150,4 +152,35 @@ If the signature is valid to the pubkey and hashed message, return true. Else fa



</details>

<a name="0x2_ecdsa_k1_secp256k1_verify_recoverable"></a>

## Function `secp256k1_verify_recoverable`

@param signature: A 65-bytes signature in form (r, s, v) that is signed using
Secp256k1. This is an recoverable signature with recovery id denoted as v.
Reference implementation on signature generation using RFC6979:
https://github.com/MystenLabs/fastcrypto/blob/74aec4886e62122a5b769464c2bea5f803cf8ecc/fastcrypto/src/secp256k1/mod.rs#L193

@param public_key: The public key to verify the signature against
@param hashed_msg: The hashed 32-bytes message, same as what the signature is signed against.

If the signature is valid to the pubkey and hashed message, return true. Else false.


<pre><code><b>public</b> <b>fun</b> <a href="ecdsa_k1.md#0x2_ecdsa_k1_secp256k1_verify_recoverable">secp256k1_verify_recoverable</a>(signature: &<a href="">vector</a>&lt;u8&gt;, public_key: &<a href="">vector</a>&lt;u8&gt;, hashed_msg: &<a href="">vector</a>&lt;u8&gt;): bool
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>native</b> <b>fun</b> <a href="ecdsa_k1.md#0x2_ecdsa_k1_secp256k1_verify_recoverable">secp256k1_verify_recoverable</a>(signature: &<a href="">vector</a>&lt;u8&gt;, public_key: &<a href="">vector</a>&lt;u8&gt;, hashed_msg: &<a href="">vector</a>&lt;u8&gt;): bool;
</code></pre>



</details>
18 changes: 15 additions & 3 deletions crates/sui-framework/sources/crypto/ecdsa_k1.move
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,25 @@ module sui::ecdsa_k1 {
/// Hash the input bytes using keccak256 and returns 32 bytes.
public native fun keccak256(data: &vector<u8>): vector<u8>;

/// @param signature: A 65-bytes signature in form (r, s, v) that is signed using
/// Secp256k1. Reference implementation on signature generation using RFC6979:
/// https://github.com/MystenLabs/narwhal/blob/5d6f6df8ccee94446ff88786c0dbbc98be7cfc09/crypto/src/secp256k1.rs
/// @param signature: A 64-bytes signature in form (r, s) that is signed using
/// Secp256k1. This is an non-recoverable signature without recovery id.
/// Reference implementation on signature generation using RFC6979:
/// https://github.com/MystenLabs/fastcrypto/blob/74aec4886e62122a5b769464c2bea5f803cf8ecc/fastcrypto/src/secp256k1/mod.rs#L193
///
/// @param public_key: The public key to verify the signature against
/// @param hashed_msg: The hashed 32-bytes message, same as what the signature is signed against.
///
/// If the signature is valid to the pubkey and hashed message, return true. Else false.
public native fun secp256k1_verify(signature: &vector<u8>, public_key: &vector<u8>, hashed_msg: &vector<u8>): bool;

/// @param signature: A 65-bytes signature in form (r, s, v) that is signed using
/// Secp256k1. This is an recoverable signature with recovery id denoted as v.
/// Reference implementation on signature generation using RFC6979:
/// https://github.com/MystenLabs/fastcrypto/blob/74aec4886e62122a5b769464c2bea5f803cf8ecc/fastcrypto/src/secp256k1/mod.rs#L193
///
/// @param public_key: The public key to verify the signature against
/// @param hashed_msg: The hashed 32-bytes message, same as what the signature is signed against.
///
/// If the signature is valid to the pubkey and hashed message, return true. Else false.
public native fun secp256k1_verify_recoverable(signature: &vector<u8>, public_key: &vector<u8>, hashed_msg: &vector<u8>): bool;
}
Loading

0 comments on commit 21781ba

Please sign in to comment.