Skip to content

Commit

Permalink
Adding new topics on signing, new Cryptography node in left nav (#9962)
Browse files Browse the repository at this point in the history
## Description 

Describe the changes or additions included in this PR.

## Test Plan 

How did you test the new or updated feature?

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

---------

Co-authored-by: ronny-mysten <118224482+ronny-mysten@users.noreply.github.com>
  • Loading branch information
randall-Mysten and ronny-mysten authored Mar 28, 2023
1 parent 1ed5b2c commit 6780cf6
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 3 deletions.
4 changes: 3 additions & 1 deletion doc/src/build/validator-node.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
---
title: Sui Validator nodes and staking
title: Sui Validator nodes
---

Learn how to set up, configure, and manage a Sui Validator node, including staking, reference gas price, and tallying rules.

## Requirements to run a validator on Sui

To run a Sui Validator, you must set up and configure a Sui Validator node. After you have a running node, you must have a minimum of 30 Million SUI in your staking pool to join the Validator set on the Sui network.
Expand Down
8 changes: 8 additions & 0 deletions doc/src/learn/cryptography/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: Sui Cryptography
---

Learn about cryptography in Sui:
* [Sui Intent Signing](../cryptography/sui-intent-signing.md)
* [Sui Offline Signing](../cryptography/sui-offline-signing.md)
* [Sui Multi-Signature](../cryptography/sui-multisig.md)
78 changes: 78 additions & 0 deletions doc/src/learn/cryptography/sui-intent-signing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
title: Sui Intent Signing
---

In Sui, an intent is a compact struct that serves as the domain separator for a message that a signature commits to. The data that the signature commits to is an intent message. All signatures in Sui must commit to an intent message, instead of the message itself.

## Motivation

In previous releases, Sui used a special `Signable` trait that attached the Rust struct name as a prefix to the serialized data. This is not ideal because it's:
* **Not compact:** The prefix `TransactionData::` is significantly larger than 1 byte.
* **Not user-friendly:** Non-Rust applications need to maintain a list of Rust-struct names.

The intent signing standard provides a compact domain separator to the data being signed for both user signatures and authority signatures. It has several benefits, including:

* The intent scope is replaced by an u8 representation instead of a Rust struct tag name string.
* In addition to the intent scope, other important domain separators can be committed as well (e.g. intent version, app id).
* The data itself no longer needs to implement the `Signable` trait, it just needs to implement `Serialize`.
* All signatures can adopt the same intent message structure, including both user signatures (only to commit to `TransactionData`) and authority signature (commits to all internal intent scopes such as `TransactionEffects`, `ProofOfPossession`, and `SenderSignedTransaction`).

## Structs

The `IntentMessage` struct consists of the intent and the serialized data value.

```rust
pub struct IntentMessage<T> {
pub intent: Intent,
pub value: T,
}
```

To create an intent struct, include the `IntentScope` (what the type of the message is), `IntentVersion` (what version the network supports), and `AppId` (what application that the signature refers to).

```rust
pub struct Intent {
scope: IntentScope,
version: IntentVersion,
app_id: AppId,
}
```

To see a detailed definition for each field, see each enum definition [in the source code](https://github.com/MystenLabs/sui/blob/0dc1a38f800fc2d8fabe11477fdef702058cf00d/crates/sui-types/src/intent.rs).

The serialization of an `Intent` is a 3-byte array where each field is represented by a byte.

The serialization of an `IntentMessage<T>` is the 3 bytes of the intent concatenated with the BCS serialized message.

## User Signature

To create a user signature, construct an intent message first, and create the signature over the BCS serialized value of the intent message (`intent || message`).

Here is an example in Rust:

```rust
let intent = Intent::default();
let intent_msg = IntentMessage::new(intent, data);
let signature = Signature::new_secure(&intent_msg, signer);
```

Here is an example in Typescript:

```typescript
const intentMessage = messageWithIntent(
IntentScope.TransactionData,
transactionBytes,
);
const signature = await this.signData(intentMessage);
```

## Authority Signature

The authority signature is created using the protocol key. The data that it commits to is also an intent message `intent || message`. See all available intent scopes [in the source code](https://github.com/MystenLabs/sui/blob/0dc1a38f800fc2d8fabe11477fdef702058cf00d/crates/sui-types/src/intent.rs#L66)

# Implementation

1. [Struct and enum definitions](https://github.com/MystenLabs/sui/blob/0dc1a38f800fc2d8fabe11477fdef702058cf00d/crates/sui-types/src/intent.rs)
2. [Test](https://github.com/MystenLabs/sui/blob/d009e82fa35bda4f2b3e7a86a9529d36c32a8159/crates/sui-types/src/unit_tests/intent_tests.rs)
3. User transaction intent signing [PR 1](https://github.com/MystenLabs/sui/pull/6445), [PR 2](https://github.com/MystenLabs/sui/pull/8321)
4. Authority intent signing [PR 1](https://github.com/MystenLabs/sui/pull/8154), [PR 2](https://github.com/MystenLabs/sui/pull/8726)
101 changes: 101 additions & 0 deletions doc/src/learn/cryptography/sui-multisig.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: Sui Multi-Signature
---

Sui supports `k` out of `n` multi-signature (multisig) transactions where `n <= 10`. A multisig transaction is one that requires more than one private key to authorize it. This topic demonstrate the workflow to create a multisig transaction in Sui, and then submit it using the Sui CLI against a local network. To learn how to set up a local network, see [Sui Local Network](../build/sui-local-network.md).

## Step 1: Add keys to Sui keystore

Use the following command to generate a Sui address and key for each supported key scheme and add it to the `sui.keystore`, then list the keys.

```shell
sui client new-address ed25519
sui client new-address secp256k1
sui client new-address secp256r1

sui keytool list
```

The response resembles the following, but displays actual addresses and keys:

```
Sui Address | Public Key (Base64) | Scheme
--------------------------------------------------------------------------
$ADDR_1 | $PK_1 | secp256r1
$ADDR_2 | $PK_2 | secp256k1
$ADDR_3 | $PK_3 | ed25519
```

## Step 2: Create a multisig address

To create a multisig address, input a list of public keys to use for the multisig address and list their corresponding weights.

```shell
sui keytool multi-sig-address --pks $PK_1 $PK_2 $PK_3 --weights 1 2 3 --threshold 3
Multisig address: $MULTISIG_ADDR
```

The response resembles the following:

```
Participating parties:
Sui Address | Public Key (Base64)| Weight
------------------------------------------
$ADDR_1 | $PK_1 | 1
$ADDR_2 | $PK_2 | 2
$ADDR_3 | $PK_3 | 3
```

## Step 3: Send objects to a multisig address

This example requests gas from a local network using the default URL following the guidance in [Sui Local Network](../build/sui-local-network.md).


```shell
curl --location --request POST 'http://127.0.0.1:9123/gas' --header 'Content-Type: application/json' --data-raw "{ \"FixedAmountRequest\": { \"recipient\": \"$MULTISIG_ADDR\" } }"
```

The response resembles the following:
```
{"transferred_gas_objects":[{"amount":200000,"id":"$OBJECT_ID", ...}]}
```

## Step 3: Serialize a transaction

This section demonstrates how to use an object that belongs to a multisig address and serialize a transfer to be signed. This can be any serialized transaction data where the sender is the multisig address.

```shell
sui client serialize-transfer-sui --to $$MULTISIG_ADDR --sui-coin-object-id $OBJECT_ID --gas-budget 1000

Raw tx_bytes to execute: $TX_BYTES
```

## Step 4: Sign the transaction with two keys

Use the following code sample to sign the transaction with two keys in `sui.keystore`. You can do this with other tools as long as you serialize it to `flag || sig || pk`.

```shell
sui keytool sign --address $ADDR_1 --data $TX_BYTES

Raw tx_bytes to execute: $TX_BYTES
Serialized signature (`flag || sig || pk` in Base64): $SIG_1

sui keytool sign --address $ADDR_2 --data $TX_BYTES

Raw tx_bytes to execute: $TX_BYTES
Serialized signature (`flag || sig || pk` in Base64): $SIG_2
```

## Step 5: Combine individual signatures into a multisig

This sample demonstrates how to combine the two signatures:
```shell
sui keytool multi-sig-combine-partial-sig --pks $PK_1 $PK_2 $PK_3 --weights 1 2 3 --threshold 3 --sigs $SIG_1 $SIG_2
```

## Step 6: Execute a transaction with multisig

This sample demonstrates how to execute a transaction using multisig:
```shell
sui client execute-signed-tx --tx-bytes $TX_BYTES --signature $SERIALIZED_MULTISIG
```
79 changes: 79 additions & 0 deletions doc/src/learn/cryptography/sui-offline-signing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: Offline Signing
---

Sui supports offline signing, which is signing transactions using a device not connected to a Sui network, or in a wallet implemented in a different programming language without relying on the Sui key store. The steps to implement offline signing include:

1. Serialize the data for signing.
1. Sign the serialized data. Put the serialized data in a location to sign (such as the wallet of your choice, or tools in other programming languages) and to produce a signature with the corresponding public key.
1. Execute the signed transaction.

## Serialize data for a transfer

You must serialize transaction data following [Binary Canonical Serialization](https://crates.io/crates/bcs) (BCS). It is supported in [other languages](https://github.com/zefchain/serde-reflection#language-interoperability).

The following example demonstrates how to to serialize data for a transfer using the Sui CLI. This returns serialized transaction data in Base64. Submit the raw transaction to execute as `tx_bytes`.

```shell
sui client serialize-transfer-sui --to $ADDRESS --sui-coin-object-id $OBJECT_ID --gas-budget 1000

Raw tx_bytes to execute: $TX_BYTES
```

## Sign the serialized data

You can sign the data using the device and programming language you choose. Sui accepts signatures for pure ed25519, ECDSA secp256k1, ECDSA secp256r1 and native multisig. To learn more about multisig, see [Sui Multi-Signature](sui-multisig.md).

The signature is committed to an intent message of the transaction data. To learn how to construct an intent message, see [Sui Intent signing](sui-intent_signing.md).

Before you pass it in to the signing API, you must first hash the intent message to 32 bytes using Blake2b. To be compatible with existing standards and hardware secure modules (HSMs), the signing algorithms perform additional hashing internally. For ECDSA Secp256k1 and Secp256r1, you must use SHA-2 SHA256 as the internal hash function. For pure Ed25519, you must use SHA-512.

Additional signature requirements:

An accepted ECDSA secp256k1 and secp256r1 signature must follow:
1. The internal hash used by ECDSA must be SHA256 [SHA-2](https://en.wikipedia.org/wiki/SHA-2) hash of the transaction data. We use SHA256 because it is supported by [Apple](https://developer.apple.com/forums/thread/89619), HSMs, and [cloud](https://developer.apple.com/forums/thread/89619), and it is widely adopted by [Bitcoin](https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm).
1. The signature must be of length 64 bytes in the form of `[r, s]` where the first 32 bytes are `r`, the second 32 bytes are `s`.
1. The `r` value can be between 0x1 and 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140 (inclusive).
1. The `s` value must be in the lower half of the curve order. If the signature is too high, convert it to a lower `s` according to [BIP-0062](https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures) with the corresponding curve orders using `order - s`. For secp256k1, the curve order is `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`. For secp256r1, the curve order is `0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551` defined in [Standards for Efficient Cryptography](https://secg.org/SEC2-Ver-1.0.pdf).
1. Ideally, the signature must be generated with deterministic nonce according to [RFC6979](https://www.rfc-editor.org/rfc/rfc6979).

An accepted pure ed25519 signature follows:
1. The signature must be produced according to [RFC 8032](https://www.rfc-editor.org/rfc/rfc8032.html#section-5.1.6). The internal hash used is SHA-512.
1. The signature must be valid according to [ZIP215](https://github.com/zcash/zips/blob/main/zip-0215.rst).

This example uses the `keytool` command to sign, using the ed25519 key corresponding to the provided address stored in `sui.keystore`. This commands outputs the signature, the public key, and the flag encoded in Base64. This command is backed by [fastcrypto](https://crates.io/crates/fastcrypto).

```shell
sui keytool sign --address $ADDRESS --data $TX_BYTES

Signer address: $ADDRESS
Raw tx_bytes to execute: $TX_BYTES
Intent: Intent { scope: TransactionData, version: V0, app_id: Sui }
Raw intent message: $INTENT_MSG
Digest to sign: $DIGEST
Serialized signature (`flag || sig || pk` in Base64): $SERIALIZED_SIG
```
To ensure the signature produced offline matches with Sui's validity rules for testing purposes, you can import the mnemonics to `sui.keystore` using `sui keytool import`. You can then sign with it using `sui keytool sign` and then compare the signature results. Additionally, you can find test vectors in `~/sui/sdk/typescript/test/e2e/raw-signer.test.ts`.
To verify a signature against the cryptography library backing Sui when debugging, see [sigs-cli](https://github.com/MystenLabs/fastcrypto/blob/4cf71bd8b3a373495beeb77ce81c27827516c218/fastcrypto-cli/src/sigs_cli.rs).
## Execute the signed transaction
After you obtain the serialized signature, you can submit it using the execution transaction command. This command takes `--tx-bytes` as the raw transaction bytes to execute (see output of `sui client serialize-transfer-sui`) and the serialized signature (Base64 encoded `flag || sig || pk`, see output of `sui keytool sign`). This executes the signed transaction and returns the certificate and transaction effects if successful.
```shell
sui client execute-signed-tx --tx-bytes $TX_BYTES --signatures $SERIALIZED_SIG
----- Certificate ----
Transaction Hash: $TX_ID
Transaction Signature: $SIGNSTURE
Signed Authorities Bitmap: RoaringBitmap<[0, 1, 3]>
Transaction Kind : Transfer SUI
Recipient : $ADDRESS
Amount: Full Balance
----- Transaction Effects ----
Status : Success
Mutated Objects:
- ID: $OBJECT_ID , Owner: Account Address ( $ADDRESS )
```
31 changes: 29 additions & 2 deletions doc/src/navconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"link": "doc-updates/sui-migration-guide"
},
{
"label": "Sui Breaking Changes",
"link": "doc-updates/sui-breaking-changes"
"label": "Sui Doc Updates",
"link": "doc-updates"
},
{
"label": "Sui Developer Forums",
Expand Down Expand Up @@ -104,6 +104,33 @@
}
]
},
{
"label": "Sui Cryptography",
"fileName": "learn/cryptography/index",
"title": "Sui Cryptography",
"items": [{
"label": "Sui Intent Signing",
"fileName": "learn/cryptography/"
},
{
"label": "Sui Gas Pricing",
"fileName": "learn/tokenomics/gas-pricing"
},
{
"label": "Sui Storage Fund",
"fileName": "learn/tokenomics/storage-fund"
},
{
"label": "Proof-of-Stake",
"fileName": "learn/tokenomics/proof-of-stake"
},
{
"label": "Tokenomics White Paper",
"link": "https://github.com/MystenLabs/sui/blob/main/doc/paper/tokenomics.pdf",
"external": true
}
]
},
{
"label": "Sui Exchange Integration Guide",
"fileName": "learn/exchange-integration-guide"
Expand Down

0 comments on commit 6780cf6

Please sign in to comment.