Subkey

Subkey is a public key cryptographic utility that is developed within Substrate itself. Its main feature is generating and inspecting key pairs, currently supporting these scheme:

  • sr25519: Schnorr signatures on the Ristretto group
  • ed25519: SHA-512 (SHA-2) on Curve25519
  • secp256k1: ECDSA signatures on secp256k1

All keys in Substrate based networks (like polkadot) use theSS58 address encoding format that is the primary user-facing way to interact with keys.

Subkey also allows restoring keys from mnemonics and raw seeds; signing and verifying signatures on a message; and signing and verifying signatures for encoded transactions.

Installation

Install with Cargo

You will need to have the Substrate build dependencies to install Subkey. Use the following two commands to install the dependencies and Subkey, respectively:

Command:

# Use the `--fast` flag to get the dependencies without needing to install the Substrate and Subkey binary
curl https://getsubstrate.io -sSf | bash -s -- --fast
# Install only `subkey`, at a specific version
cargo install --force subkey --git https://github.com/paritytech/substrate --version 2.0.1 --locked

Compiling with Cargo

If you already have the Substrate repository, you can build Subkey with:

Command:

# Run this in the Substrate working directory
cargo build -p subkey --release

This will generate the Subkey binary in ./target/release/subkey. Please be aware that the interface to Subkey may change between versions; the commands described below have all been tested with the version of Subkey specified by the cargo install command in the Install with Cargo section.

If you follow the steps in this section to compile Subkey with Cargo, the version of Subkey will depend on the branch or commit of Substrate that you have checked out.

Once installed, use the subkey -h command to see all the sub-commands and flags available. Use subkey <sub-command> -h to see help items for ech sub-command.

Inspecting keys

The inspect command recalculates a key pair's public key and public address given its secret seed. You most commonly inspect the key by the mnemonic phrase that is used to derive it:

Command:

subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very"

Output:

Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account:
  Secret seed:       0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849
  Public key (hex):  0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR
  Account ID:        0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  SS58 Address:      5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR

You can also use the secret seed directly, here the same result is seen for the secret shown above:

Command:

subkey inspect 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849

Output:

Secret Key URI `0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849` is account:
  Secret seed:       0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849
  Public key (hex):  0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR
  Account ID:        0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  SS58 Address:      5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR

Next in how to generate keys, we will also show you how to inspect more than a base seed.

Generating keys

Generate an sr25519 key by running:

Command:

subkey generate

Output:

Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account:
  Secret seed:       0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849
  Public key (hex):  0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR
  Account ID:        0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  SS58 Address:      5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR

We will use this seed as the example for the rest of this document.


For more security, use --words 24 (supports 12, 15, 18, 21, and 24):

Command:

subkey generate --words 24

Output:

Secret phrase `voice become refuse remove ordinary recall humble purity shock fetch open scale knee above axis blossom differ bamboo ski drip forest fade ill door` is account:
  Secret seed:       0xed26c8119b4872da9e5c2d4b679c82a7fbbabed22cb9f61d5fd4d7806ee5b014
  Public key (hex):  0x182a8385912e206910a11dfcfbadcc018d73ff3febe36f9eb85774e77591a314
  Public key (SS58): 5CcPdpUAhRvGjyxcpnL7emi7SruQ98eP7mC8cDNkjCKfXNZ7
  Account ID:        0x182a8385912e206910a11dfcfbadcc018d73ff3febe36f9eb85774e77591a314
  SS58 Address:      5CcPdpUAhRvGjyxcpnL7emi7SruQ98eP7mC8cDNkjCKfXNZ7

Use the --scheme option to generate an ed25519 key:

Command:

subkey generate --scheme ed25519

Output:

Secret phrase `voice become refuse remove ordinary recall humble purity shock fetch open scale knee above axis blossom differ bamboo ski drip forest fade ill door` is account:
  Secret seed:       0xed26c8119b4872da9e5c2d4b679c82a7fbbabed22cb9f61d5fd4d7806ee5b014
  Public key (hex):  0x182a8385912e206910a11dfcfbadcc018d73ff3febe36f9eb85774e77591a314
  Public key (SS58): 5CcPdpUAhRvGjyxcpnL7emi7SruQ98eP7mC8cDNkjCKfXNZ7
  Account ID:        0x182a8385912e206910a11dfcfbadcc018d73ff3febe36f9eb85774e77591a314
  SS58 Address:      5CcPdpUAhRvGjyxcpnL7emi7SruQ98eP7mC8cDNkjCKfXNZ7

The output gives us the following information about our key:

  • Secret phrase (aka "mnemonic phrase") - A series of English words that encodes the seed in a more human-friendly way. Mnemonic phrases were first introduced in Bitcoin (see BIP39) and make it much easier to write down your key by hand.
  • Secret Seed (aka "Private Key" or "Raw Seed") - The minimum necessary information to restore the key pair. All other information is calculated from the seed.
  • Public Key (hex) - The public half of the cryptographic key pair in hexadecimal.
  • Public Key (SS58) - The public half of the cryptographic key pair in SS58 encoding.
  • Account ID - Alias for the Public Key in hexadecimal.
  • SS58 Address (aka "Public Address") - An SS58-encoded address based on the public key.

You can also create a vanity address, meaning an address that contains a specified sub-string. But you will not receive a mnemonic phrase for this address.

Command:

subkey vanity --pattern dan

Output:

Generating key containing pattern 'dan'
best: 189 == top: 189
Secret Key URI `0xf58706b2057633b6d634d9cc54e8e9e8f11246290c0bbef934129978ede6439b` is account:
  Secret seed:       0xf58706b2057633b6d634d9cc54e8e9e8f11246290c0bbef934129978ede6439b
  Public key (hex):  0xca043bd23428eb023d59f4b7eb37416b343fc719a3c89c5256071b4f39d73130
  Public key (SS58): 5GdandXEVW1ER8cxW6uQgpjpyuEbZ3s2ED3ZU15LfrGdQhhz
  Account ID:        0xca043bd23428eb023d59f4b7eb37416b343fc719a3c89c5256071b4f39d73130
  SS58 Address:      5GdandXEVW1ER8cxW6uQgpjpyuEbZ3s2ED3ZU15LfrGdQhhz

Notice the SS58 Address5GdandXEVW1ER8cxW6uQgpjpyuEbZ3s2ED3ZU15LfrGdQhhz contains the string dan.

Example seed

We will use the seed generated above to illustrate different HD key derivation paths and passwords:

caution juice atom organ advance problem want pledge someone senior holiday very

Command:

subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very"

Output:

Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account:
  Secret seed:       0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849
  Public key (hex):  0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR
  Account ID:        0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  SS58 Address:      5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR

Specify network address format

Subkey encodes the address depending on the network. You can use the --network flag to change this. See subkey <inspect/generate> -n for supported networks.

Let's say you want to use the same private key on the Kusama network. Use --network to get your address formatted for Kusama. Notice that the public key is the same, but the address has a different format. Here we use the example seed:

Command:

subkey inspect --network kusama "caution juice atom organ advance problem want pledge someone senior holiday very"

Output:

Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account:
  Secret seed:       0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849
  Public key (hex):  0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  Public key (SS58): HRkCrbmke2XeabJ5fxJdgXWpBRPkXWfWHY8eTeCKwDdf4k6
  Account ID:        0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746
  SS58 Address:      HRkCrbmke2XeabJ5fxJdgXWpBRPkXWfWHY8eTeCKwDdf4k6

HD key derivation

Backup your passwords and derivation paths!

Remember that passwords and derivation paths are just as important to backup as the seed itself! See the Combine derivation paths and passwords for more information.

Subkey supports hard and soft hierarchical deterministic (HD) key derivation compliant with BIP32. HD keys allow you to have a master seed and define a tree with a key pair at each leaf. The tree has a similar structure to a filesystem and can have any depth you want.

Hard and soft key derivation both support:

  • parent private key + path ➔ child private key
  • parent private key + path ➔ child public key

Further, soft key derivation supports:

  • parent public key + path ➔ child public key

Hard key derivation

You can derive a hard key child using // after the mnemonic phrase:

Command:

subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very//polkadot//0"

Output:

Secret Key URI `caution juice atom organ advance problem want pledge someone senior holiday very//polkadot//0` is account:
  Secret seed:       0x056a6a4e203766ffbea3146967ef25e9daf677b14dc6f6ed8919b1983c9bebbc
  Public key (hex):  0x841226ea070c9577979ca2e854130fbe3253853c13c05943e09908312950275d
  Public key (SS58): 5F3sa2TJAWMqDhXG6jhV4N8ko9SxwGy8TpaNS1repo5EYjQX
  Account ID:        0x841226ea070c9577979ca2e854130fbe3253853c13c05943e09908312950275d
  SS58 Address:      5F3sa2TJAWMqDhXG6jhV4N8ko9SxwGy8TpaNS1repo5EYjQX

Soft key derivation

Likewise, you can derive a soft key child using a single / after the mnemonic phrase:

Command:

subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very/polkadot/0"

Output:

Secret Key URI `caution juice atom organ advance problem want pledge someone senior holiday very/polkadot/0` is account:
  Secret seed:       n/a
  Public key (hex):  0x94bec5342b23d74b8736c74ab1bf311182c62510d220313a424e63ea57172855
  Public key (SS58): 5FRjccB7s9fbMu4pwQhYng2quQnKYkCHXRUCMBRwL7Pzj8FX
  Account ID:        0x94bec5342b23d74b8736c74ab1bf311182c62510d220313a424e63ea57172855
  SS58 Address:      5FRjccB7s9fbMu4pwQhYng2quQnKYkCHXRUCMBRwL7Pzj8FX

Recall the root SS58 address from the example seed is, 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR. We can use that public address to derive the same child address as above using the seed.

Command:

subkey inspect "5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR/polkadot/0"

Output:

Public Key URI `5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR/polkadot/0` is account:
  Network ID/version: substrate
  Public key (hex):   0x94bec5342b23d74b8736c74ab1bf311182c62510d220313a424e63ea57172855
  Public key (SS58):  5FRjccB7s9fbMu4pwQhYng2quQnKYkCHXRUCMBRwL7Pzj8FX
  Account ID:         0x94bec5342b23d74b8736c74ab1bf311182c62510d220313a424e63ea57172855
  SS58 Address:       5FRjccB7s9fbMu4pwQhYng2quQnKYkCHXRUCMBRwL7Pzj8FX

Note that the two addresses here match. This is not the case in hard key derivation!

Password protected keys

Backup your passwords and derivation paths!

Remember that passwords and derivation paths are just as important to backup as the seed itself! See the Combine derivation paths and passwords for more information.

To generate a key that is password protected, use the --password <password> flag:

Command:

subkey generate --password "pencil laptop kitchen cutter"

Output:

Secret phrase `apology truck manage valve merge front idea imitate coconut poverty trap gas` is account:
  Secret seed:       0x2da5ddf709c8cd6c9727d347cd1e867234802d15ce51581d86bcb949bba7bcb5
  Public key (hex):  0xc8e06268df6173a32a859da4b9601d5e11b503206f9817ae1c101d2984826d19
  Public key (SS58): 5Gc66BfkkebMv3EvP8ThfpiGLng1EPtUiAQ71gzwpJosJqvo
  Account ID:        0xc8e06268df6173a32a859da4b9601d5e11b503206f9817ae1c101d2984826d19
  SS58 Address:      5Gc66BfkkebMv3EvP8ThfpiGLng1EPtUiAQ71gzwpJosJqvo

You can inspect password-protected keys either by passing the --password flag or using /// at the end of the mnemonic:

Command (--password flag):

subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" --password "pencil laptop kitchen cutter"

Output (--password flag):

Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account:
  Secret seed:       0xdfc5d5d5235a37fdc907ee1cb720299f96aeb02f9c7c2fcad7ee8c7bfbd2a4db
  Public key (hex):  0xdef8f78b123475265815b65a7c55e105e1ab185f4969954f68d92b7bb67a1045
  Public key (SS58): 5H74SqH1iQCWh5Gumyghh1WJMcmM6TdBHYSK7mKVJbv9NuSK
  Account ID:        0xdef8f78b123475265815b65a7c55e105e1ab185f4969954f68d92b7bb67a1045
  SS58 Address:      5H74SqH1iQCWh5Gumyghh1WJMcmM6TdBHYSK7mKVJbv9NuSK

Command (password with ///):

subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very///pencil laptop kitchen cutter"

Output (password with ///):

Secret Key URI `caution juice atom organ advance problem want pledge someone senior holiday very///pencil laptop kitchen cutter` is account:
  Secret seed:       0xdfc5d5d5235a37fdc907ee1cb720299f96aeb02f9c7c2fcad7ee8c7bfbd2a4db
  Public key (hex):  0xdef8f78b123475265815b65a7c55e105e1ab185f4969954f68d92b7bb67a1045
  Public key (SS58): 5H74SqH1iQCWh5Gumyghh1WJMcmM6TdBHYSK7mKVJbv9NuSK
  Account ID:        0xdef8f78b123475265815b65a7c55e105e1ab185f4969954f68d92b7bb67a1045
  SS58 Address:      5H74SqH1iQCWh5Gumyghh1WJMcmM6TdBHYSK7mKVJbv9NuSK

Take note that the --password flag does not report the password used, but the /// does. The output is identical otherwise.

Combine derivation paths and passwords

Backup your passwords and derivation paths!

Note that the "secret seed" is not password protected. Although it can still recover an account, the key pair that's derived is not the same account as recovered with any password! The same seed with different derivation paths passwords will derive different keys! The "Secret phrase" is not sufficient to recover a key pair! Keep your paths and passwords secure, as without it your key pair cannot be recovered!

You can mix and match hard and soft key paths (although it doesn't make much sense to have hard paths as children of soft paths). For example:

Command:

subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very//polkadot/0"

Output:

Secret Key URI `caution juice atom organ advance problem want pledge someone senior holiday very//polkadot/0` is account:
  Secret seed:       n/a
  Public key (hex):  0xd6f066a07b3ebb1572c00506c9dc86a64db63779e7791e7d37247f59e4bffc14
  Public key (SS58): 5GvXX2NpiR8qoeTUbdzTCmMtZgGrZxRoCJFEvfL1iaDjTFKb
  Account ID:        0xd6f066a07b3ebb1572c00506c9dc86a64db63779e7791e7d37247f59e4bffc14
  SS58 Address:      5GvXX2NpiR8qoeTUbdzTCmMtZgGrZxRoCJFEvfL1iaDjTFKb

The first level (//polkadot) is hard-derived, while the leaf (/0) is soft-derived.

To use key derivation with a password-protected key, add your password to the end:

Command:

# Mnemonic phrase + derivation path + password
subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very//polkadot/0///pencil laptop kitchen cutter"

Output:

Secret Key URI `caution juice atom organ advance problem want pledge someone senior holiday very//polkadot/0///pencil laptop kitchen cutter` is account:
  Secret seed:       n/a
  Public key (hex):  0xcaf1f5ec14b507b5c365c6528cc06de74a5615274694a0c895ed4109c0ff0d32
  Public key (SS58): 5GeoQa3nkeNmzZSfgBFuK3BkAggnTHcX3S1j94sffJYYphrP
  Account ID:        0xcaf1f5ec14b507b5c365c6528cc06de74a5615274694a0c895ed4109c0ff0d32
  SS58 Address:      5GeoQa3nkeNmzZSfgBFuK3BkAggnTHcX3S1j94sffJYYphrP

Notice that for soft-derived keys, you can use the hard-derived (with optional password) parent's public address to derive new public addresses:

Command:

# A soft-derived SS58-address for a *public address* with a hidden seed, hard derivation path, and password
subkey inspect "5GsbzysSK8TKahXBC7FpS2myx3nWehMyYU7q8CLrzZCjpKbM/0"

Output:

Public Key URI `5GsbzysSK8TKahXBC7FpS2myx3nWehMyYU7q8CLrzZCjpKbM/0` is account:
  Network ID/version: substrate
  Public key (hex):   0xcaf1f5ec14b507b5c365c6528cc06de74a5615274694a0c895ed4109c0ff0d32
  Public key (SS58):  5GeoQa3nkeNmzZSfgBFuK3BkAggnTHcX3S1j94sffJYYphrP
  Account ID:         0xcaf1f5ec14b507b5c365c6528cc06de74a5615274694a0c895ed4109c0ff0d32
  SS58 Address:       5GeoQa3nkeNmzZSfgBFuK3BkAggnTHcX3S1j94sffJYYphrP

Notice that the "SS58-address + derivation path" produces the same address as the "mnemonic phrase + derivation path + password". As such, you can reveal your parent public address and soft derivation paths without revealing your mnemonic phrase or password, retaining control of all derived addresses.

Signing and verifying messages

Signing

You can sign a message by passing the message to Subkey on STDIN. You can sign with either your seed or mnemonic phrase. We use the example raw seed and address here:

Command:

# Usage
# echo "msg" | subkey sign --suri <secret-seed>

# Example
echo "test message" | subkey sign --suri 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849

Output:

22f91b41ba12f8663ddce26bfc90dbfe6a51683fd3782ad679ab2a5fdbe7d44c2a119f22c74eea22555e5483eb7f42b828f189a38379d59c3b607d2461f0858e

Verifying

Although the signatures above are different, they both verify with the address:

Command:

# Usage
# echo "msg" | subkey verify <signature> <SS58-address>

# Example
echo "test message" | subkey verify 22f91b41ba12f8663ddce26bfc90dbfe6a51683fd3782ad679ab2a5fdbe7d44c2a119f22c74eea22555e5483eb7f42b828f189a38379d59c3b607d2461f0858e 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR

Output:

Signature verifies correctly.

echo appends a newline character to the end of strings. Therefore, if you verify a message that was signed elsewhere, e.g. Polkadot JS, then you will need to use echo -n to remove the newline character and verify the correct message.

Generating node keys

You can generate a node's libp2p key by the following:

Command:

# Usage
# subkey generate-node-key --file <output-file>

# Example
subkey generate-node-key --file node-key

Output:

12D3KooWAhzqC4xstZKkAVYge2Q9tAMcnFhNEabLejRNVoQWLHHC

The peer ID is displayed on screen and the actual key is saved in the <output-file>.

Well-known keys

The common seed used for all development accounts is:

bottom drive obey lake curtain smoke basket hold race lonely fit walk

Various development accounts are derived from this seed.

If you've worked with Substrate previously, you have likely encountered the ubiquitous accounts for Alice, Bob, and their friends. These keys are not at all private, but are useful for playing with Substrate without always generating new key pairs. You can inspect these "well-known" keys as well.

Command:

subkey inspect //Alice

Output:

Secret Key URI `//Alice` is account:
  Secret seed:      0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a
  Public key (hex): 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
  Account ID:       0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
  SS58 Address:     5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY

A mnemonic phrase is a secret group of words that can be used to uniquely generate a private key. In Subkey, there is a specific dev phrase used whenever a mnemonic phrase is omitted. //Alice for example is actually:

bottom drive obey lake curtain smoke basket hold race lonely fit walk//Alice

It is important remember that keys such as this are not secure, and should be deployed only for testing. In addition, anyone not using PolkadotJS or Subkey should note this information to properly generate the account.

Further resources

Last edit: on

Run into problems?
Let us Know