Skip to content

Commit

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

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

4 comments on commit 21781ba

@vercel
Copy link

@vercel vercel bot commented on 21781ba Jan 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

wallet-adapter – ./sdk/wallet-adapter/example

sui-wallet-adapter.vercel.app
wallet-adapter-mysten-labs.vercel.app
wallet-adapter-git-main-mysten-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 21781ba Jan 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

frenemies – ./dapps/frenemies

frenemies-mysten-labs.vercel.app
frenemies.vercel.app
frenemies-git-main-mysten-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 21781ba Jan 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

explorer – ./apps/explorer

explorer-git-main-mysten-labs.vercel.app
explorer-topaz.vercel.app
explorer.sui.io
explorer-mysten-labs.vercel.app

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 Validators 500/s Owned Transactions Benchmark Results

Benchmark Report:
+-------------+-----+--------+---------------+---------------+---------------+
| duration(s) | tps | error% | latency (min) | latency (p50) | latency (p99) |
+============================================================================+
| 60          | 500 | 0      | 11            | 25            | 53            |
Stress Performance Report:
+-----------+-----+-----+
| metric    | p50 | p99 |
+=======================+
| cpu usage | 32  | 41  |

4 Validators 500/s Shared Transactions Benchmark Results

Benchmark Report:
+-------------+-----+--------+---------------+---------------+---------------+
| duration(s) | tps | error% | latency (min) | latency (p50) | latency (p99) |
+============================================================================+
| 60          | 495 | 0      | 14            | 453           | 865           |
Stress Performance Report:
+-----------+-----+-----+
| metric    | p50 | p99 |
+=======================+
| cpu usage | 33  | 42  |

20 Validators 50/s Owned Transactions Benchmark Results

Benchmark Report:
+-------------+-----+--------+---------------+---------------+---------------+
| duration(s) | tps | error% | latency (min) | latency (p50) | latency (p99) |
+============================================================================+
| 60          | 148 | 0      | 104           | 649           | 1193          |
Stress Performance Report:
+-----------+-----+-----+
| metric    | p50 | p99 |
+=======================+
| cpu usage | 72  | 85  |

20 Validators 50/s Shared Transactions Benchmark Results

Benchmark Report:
+-------------+-----+--------+---------------+---------------+---------------+
| duration(s) | tps | error% | latency (min) | latency (p50) | latency (p99) |
+============================================================================+
| 60          | 48  | 0      | 347           | 823           | 8127          |
Stress Performance Report:
+-----------+-----+-----+
| metric    | p50 | p99 |
+=======================+
| cpu usage | 60  | 85  |

Narwhal Benchmark Results

 SUMMARY:
-----------------------------------------
 + CONFIG:
 Faults: 0 node(s)
 Committee size: 4 node(s)
 Worker(s) per node: 1 worker(s)
 Collocate primary and workers: True
 Input rate: 50,000 tx/s
 Transaction size: 512 B
 Execution time: 57 s

 Header number of batches threshold: 32 digests
 Header maximum number of batches: 1,000 digests
 Max header delay: 2,000 ms
 GC depth: 50 round(s)
 Sync retry delay: 10,000 ms
 Sync retry nodes: 3 node(s)
 batch size: 500,000 B
 Max batch delay: 200 ms
 Max concurrent requests: 500,000 

 + RESULTS:
 Batch creation avg latency: 77 ms
 Header creation avg latency: 1,738 ms
 	Batch to header avg latency: 947 ms
 Header to certificate avg latency: 6 ms
 	Request vote outbound avg latency: 3 ms
 Certificate commit avg latency: 3,323 ms

 Consensus TPS: 49,712 tx/s
 Consensus BPS: 25,452,556 B/s
 Consensus latency: 3,424 ms

 End-to-end TPS: 48,003 tx/s
 End-to-end BPS: 24,577,650 B/s
 End-to-end latency: 4,411 ms
-----------------------------------------

Please sign in to comment.