Resources Sui Mysten Labs Tue Nov 08 2022

Cryptography in Sui: Wallet Specifications


Our Cryptography in Sui blog post series highlights the technologies that maintain secure transactions and usability on the Sui network. This series helps developers understand Sui’s security infrastructure and how to develop safe decentralized applications.

Sui follows wallet specifications widely accepted in the cryptocurrency industry, such as BIP-32 (and its variation, SLIP-0010), BIP-44, and BIP-39. These specifications have become common in the cryptocurrency industry as a means for users to manage account keys.

Currently, Sui accepts signed transactions using either Ed25519 or ECDSA Secp256k1. In Sui Wallet and SDKs, we provide a flexible interface to sign transactions with various signing schemes.

Let’s take a closer look at how exactly we apply these specifications.


Key Derivation Scheme

Sui follows BIP-32 for managing wallets that support the ECDSA Secp256k1 signing scheme.

BIP-32 defines the hierarchical deterministic wallet structure to logically associate a set of keys. Grouping keys in this manner reduces the overhead of keeping track of a large number of private keys for a user. This method also lets custodians issue distinct managed addresses for each user account under one source of control. 

Using BIP-32 decouples the private key derivation from the public key derivation, enabling the watch-only wallet use case, where a chain of public keys and its addresses can be derived, while the private key can be kept offline for signing.

Sui follows SLIP-0010 for managing wallets that support the Ed25519 (EdDSA) signing scheme.

We use SLIP-0010 because BIP-32 was originally designed for ECDSA with a prime-order group, whereas the Ed25519 curve is based on a group order of h × ℓ , where h is a small co-factor and ℓ is a 252-bit prime. It’s an advanced technical detail, but the Ed25519 signature standard applies bit-clamping on both the lower and higher bits of the private key which makes some of the BIP-32 modes incompatible with Ed25519. As a result, SLIP-0010 specifies to forbid deriving a new public key from an existing user’s public key. SLIP-0010 only supports the so-called “hardened” private parent key to private child key derivation.

 

Key Derivation Path

While BIP-32 specifies the levels of wallets in hierarchical structure, BIP-44 further defines the five levels of the derivation path with their exact meanings: m / purpose' / coin_type' / account' / change / address_index. In this structure, the slashes indicate new levels, or children, in the hierarchy. 

The purpose level is generally set to 44, corresponding to the BIP number. In Sui, however, the purpose level distinguishes different signing schemes: 44 is set for Ed25519 and 54 for ECDSA Secp256k1. While it is non-standard to set the purpose level to a value that is not 44, it is common to use the purpose field to distinguish different signing schemes. BIP-49 and BIP-84, for example, are used to identify script types in Bitcoin. We chose 54 to indicate ECDSA Secp256k1 because there is no existing BIP under 54, avoiding confusion with any Bitcoin standard.

The coin_type value is managed with a repository of all other cryptocurrencies. Both signature schemes use Sui’s registered coin_type, 784 (SUI on a telephone keypad).

phone-keypad.png

The account_index level is usually used for logically separating user accounts and creating specific account categories. Some common use cases include: 

  • Custodians manage multiple user accounts. 
  • Users designate accounts for specific purposes, such as donations, savings, and expenses.
     

To support multi-account, we recommend incrementing the account_index level starting at zero.

It is generally accepted that, while account-based currencies define only the first three levels, UTXO-based currencies add change and address level definitions. Because Sui’s object-oriented data model is neither UTXO nor account-based (it in fact combines both), it employs all five levels for maximum compatibility.

To summarize:

 

 

Derivation Path Form

Notes

Ed25519m/44'/784'/{account}'/{change}'/{address}'Each level of the derivation path is hardened.
ECDSA Secp256k1m/54'/784'/{account}'/{change}/{address}The first three levels are hardened.


Mnemonics Support
 

Once we defined the deterministic way to derive the master key from a seed, BIP-39 is introduced to make the seed more human-readable and memorizable using mnemonics. Sui accepts 12, 15, 18, 21, and 24 words from the BIP-39 wordlist that is properly checksummed, corresponding to 128, 160, 192, 224, and 256 bits of entropy.

 

Key Management in Sui

Sui supports key-pair generation and associated mnemonics through its Typescript SDK and command line interface (CLI). The SDK provides additional functionality, including transaction signing and RPC integration.

Here we demonstrate how to:

  • Derive a key-pair from mnemonic
  • Get its address
  • Use it to sign a serialized typed transaction (or any data)
  • Execute against the RPC provider

 

Typescript SDK
import { Ed25519Keypair, JsonRpcProvider, RawSigner } from '@mysten/sui.js';
const TEST_MNEMONICS = 'a 12-24 word mnemonics strings separated by space, from the wordlist';
// Create a keypair under Ed25519 scheme.
const keypair_ed25519 = Ed25519Keypair.deriveKeypair(TEST_MNEMONICS, "m/44'/784'/0'/0'/0'");
// Create a keypair under ECDSA secp256k1 scheme.
const keypair_secp256k1 = Secp256k1Keypair.deriveKeypair(TEST_MNEMONICS, "m/54'/784'/0'/0/0");
// Create a signer with the keypair with a provider.
const signer = new RawSigner(
 keypair_ed25519, // or use keypair_secp256k1 for ECDSA secp256k1
 new JsonRpcProvider('<https://gateway.devnet.sui.io:443>')
);
// Get the address.
const address = signer.getAddress();
console.log('address', address);
// Sign some random data.
const signData = new Base64DataBuffer(
 new TextEncoder().encode('hello world')
);
const { signature, pubKey } = await signer.signData(signData)
console.log('signature', signature);
// Sign a typed data, i.e. a transfer object.
const transferTxn = await signer.transferObject({
 objectId: '0x5015b016ab570df14c87649eda918e09e5cc61e0',
 gasBudget: 1000,
 recipient: '0xd84058cb73bdeabe123b56632713dcd65e1a6c92',
});
console.log('transferTxn', transferTxn);


Command Line Interface


# Import mnemonics to sui.keystore with a scheme and a derivation path. 
sui keytool import "SOME_MNEMONICS" ed25519 "m/44'/784'/0'/0'/0'" 
2022-09-13T20:34:31.672453Z  INFO sui::keytool: Key imported for address [SOME_ADDRESS]
sui keytool import "SOME_MNEMONICS" secp256k1 "m/54'/784'/0'/0/1"
2022-09-13T20:37:06.849647Z  INFO sui::keytool: Key imported for address [SOME_ADDRESS]
# Generate random mnemonics and save to sui.keystore with a scheme and a derivation path. 
sui client new-address ed25519 "m/54'/784'/0'/0'/1'"
Created new keypair for address with scheme Secp256k1: [SOME_ADDRESS]
Secret Recovery Phrase : [SOME_MNEMONICS]
sui client new-address secp256k1 "m/54'/784'/0'/0/1"
Created new keypair for address with scheme Secp256k1: [SOME_ADDRESS]
Secret Recovery Phrase : [SOME_MNEMONICS]
# Set the generated address to active in keystore.
sui client switch --address 0x8e2591958b19311ece3d748852f4693908be8b3c
# Get some gas objects.
sui client gas --address 0x8e2591958b19311ece3d748852f4693908be8b3c
                Object ID                  |  Gas Value
----------------------------------------------------------------------
0xba561fb82aa38075be60c0fad30e0c6b615c0f2e |  10000000
# Transfer an object to another address, signed with the active address in keystore. Success!
sui client transfer --gas-budget 1000 --to 0x1f7633037b5e185e162f51fca142fb6e8ebe50df --object-id 0xba561fb82aa38075be60c0fad30e0c6b615c0f2e
Transfer confirmed after 494589 us
----- Certificate ----
Transaction Hash: f4ntyDJrO7HfAiZtit1zprhqftyOj5nvpo+WitB5IEU=
Transaction Signature: AA==@G7ur/HpC3AuOmyeLBFtccptvstApuDEGChsHKzasF+JJvPg+B+jmRTvfkL8E2ACpW7DD4E83Hom8YOs2EzNXDw==@6TODHwm39WE6p+z1ulDzlbZdTA/i31ZHKIsAc5u7kNw=
Signed Authorities Bitmap: RoaringBitmap<[0, 1, 3]>
Transaction Kind : Transfer Object
Recipient : 0x1f7633037b5e185e162f51fca142fb6e8ebe50df
Object ID : 0xba561fb82aa38075be60c0fad30e0c6b615c0f2e
Version : SequenceNumber(2)
Object Digest : H60tIWie9FU/BfyYDmrMgrlltQA5A/4S5YP6lITbwqs=
----- Transaction Effects ----
Status : Success
Mutated Objects:
 - ID: 0xba561fb82aa38075be60c0fad30e0c6b615c0f2e , Owner: Account Address ( 0x1f7633037b5e185e162f51fca142fb6e8ebe50df )
 - ID: 0xbf8112a6abee9fd77fda6529aa0ec97fc735791a , Owner: Account Address ( 0x8e2591958b19311ece3d748852f4693908be8b3c )


State-of-the-Art Wallet Building

Wallets must be secure yet easy for their owners to access. We rely on industry standards to guide our design of user wallets, while remaining agile and flexible in exploring different signature schemes. 

In addition to the wallet specifications that we currently support, we are constantly innovating on wallet designs that make interacting with Sui safer and easier to use. We will soon share our design on wallet pre-approved transactions. Instead of signing transactions one at a time, Sui Wallet makes on-chain games practical, unlocking the full potential of fast execution on the Sui network.