referrerpolicy=no-referrer-when-downgrade

subkey/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! # Subkey
20//!
21//! Subkey is a commandline utility included with Substrate. It allows generating and restoring keys
22//! for Substrate based chains such as Polkadot, Kusama and a growing number of parachains and
23//! Substrate based projects.
24
25//! `subkey` provides a few sub-commands to generate keys, check keys, sign messages, verify
26//! messages, etc...
27//!
28//! You can see the full list of commands with `subkey --help`. Most commands have additional help
29//! available with for instance `subkey generate --help` for the `generate` command.
30//!
31//! ## Safety first
32//!
33//! `subkey` does not need an internet connection to work. Indeed, for the best security, you should
34//! be using `subkey` on a machine that is **not connected** to the internet.
35//!
36//! `subkey` deals with **seeds** and **private keys**. Make sure to use `subkey` in a safe
37//! environment (ie. no one looking over your shoulder) and on a safe computer (ie. no one able to
38//! check your command history).
39//!
40//! If you save any output of `subkey` into a file, make sure to apply proper permissions and/or
41//! delete the file as soon as possible.
42//!
43//! ## Usage
44//!
45//! The following guide explains *some* of the `subkey` commands. For the full list and the most up
46//! to date documentation, make sure to check the integrated help with `subkey --help`.
47//!
48//! ### Install with Cargo
49//!
50//! You will need to have the Substrate build dependencies to install Subkey. Use the following two
51//! commands to install the dependencies and Subkey, respectively:
52//!
53//! Command:
54//!
55//! ```bash
56//! # Install only `subkey`, at a specific version of the subkey crate
57//! cargo install --force subkey --git https://github.com/paritytech/substrate --version <SET VERSION> --locked
58//! # If you run into issues building, you likely are missing deps defined in https://docs.substrate.io/install/
59//! ```
60//!
61//! ### Run in a container
62//!
63//! ```bash
64//! # Use `--pull=always` with the `latest` tag, or specify a version in a tag
65//! docker run -it --pull=always docker.io/parity/subkey:latest <command to subkey>
66//! ```
67//!
68//! ### Generate a random account
69//!
70//! Generating a new key is as simple as running:
71//!
72//! ```bash
73//! subkey generate
74//! ```
75//!
76//! The output looks similar to:
77//!
78//! ```text
79//! Secret phrase `hotel forest jar hover kite book view eight stuff angle legend defense` is account:
80//!   Secret seed:      0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d
81//!   Public key (hex): 0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515
82//!   Account ID:       0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515
83//!   SS58 Address:     5Hpm9fq3W3dQgwWpAwDS2ZHKAdnk86QRCu7iX4GnmDxycrte
84//! ```
85//!
86//! ---
87//! ☠️ DO NT RE-USE ANY OF THE SEEDS AND SECRETS FROM THIS PAGE ☠️.
88//!
89//! You can read more about security and risks in [SECURITY.md](./SECURITY.md) and in the [Polkadot Wiki](https://wiki.polkadot.network/learn/learn-accounts/#account-generation).
90//!
91//! ---
92//!
93//! The output above shows a **secret phrase** (also called **mnemonic phrase**) and the **secret
94//! seed** (also called **Private Key**). Those 2 secrets are the pieces of information you MUST
95//! keep safe and secret. All the other information below can be derived from those secrets.
96//!
97//! The output above also show the **public key** and the **Account ID**. Those are the independent
98//! from the network where you will use the key.
99//!
100//! The **SS58 address** (or **Public Address**) of a new account is a representation of the public
101//! keys of an account for a given network (for instance Kusama or Polkadot).
102//!
103//! You can read more about the [SS58 format in the Substrate Docs](https://docs.substrate.io/reference/address-formats/) and see the list of reserved prefixes in the [SS58 Registry](https://github.com/paritytech/ss58-registry).
104//!
105//! For instance, considering the previous seed
106//! `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d` the SS58 addresses are:
107//!
108//! - Polkadot: `16m4J167Mptt8UXL8aGSAi7U2FnPpPxZHPrCgMG9KJzVoFqM`
109//! - Kusama: `JLNozAv8QeLSbLFwe2UvWeKKE4yvmDbfGxTuiYkF2BUMx4M`
110//!
111//! ### Json output
112//!
113//! `subkey` can also generate the output as *json*. This is useful for automation.
114//!
115//! command:
116//!
117//! ```bash
118//! subkey generate --output-type json
119//! ```
120//!
121//! output:
122//!
123//! ```json
124//! {
125//!   "accountId": "0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515",
126//!   "publicKey": "0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515",
127//!   "secretPhrase": "hotel forest jar hover kite book view eight stuff angle legend defense",
128//!   "secretSeed": "0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d",
129//!   "ss58Address": "5Hpm9fq3W3dQgwWpAwDS2ZHKAdnk86QRCu7iX4GnmDxycrte"
130//! }
131//! ```
132//!
133//! So if you only want to get the `secretSeed` for instance, you can use:
134//!
135//! command:
136//!
137//! ```bash
138//! subkey generate --output-type json | jq -r .secretSeed
139//! ```
140//!
141//! output:
142//!
143//! ```text
144//! 0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d
145//! ```
146//!
147//! ### Additional user-defined password
148//!
149//! `subkey` supports an additional user-defined secret that will be appended to the seed. Let's see
150//! the following example:
151//!
152//! ```bash
153//! subkey generate --password extra_secret
154//! ```
155//!
156//! output:
157//!
158//! ```text
159//! Secret phrase `soup lyrics media market way crouch elevator put moon useful question wide` is account:
160//!   Secret seed:      0xe7cfd179d6537a676cb94bac3b5c5c9cb1550e846ac4541040d077dfbac2e7fd
161//!   Public key (hex): 0xf6a233c3e1de1a2ae0486100b460b3ce3d7231ddfe9dadabbd35ab968c70905d
162//!   Account ID:       0xf6a233c3e1de1a2ae0486100b460b3ce3d7231ddfe9dadabbd35ab968c70905d
163//!   SS58 Address:     5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC
164//! ```
165//!
166//! Using the `inspect` command (see more details below), we see that knowing only the **secret
167//! seed** is no longer sufficient to recover the account:
168//!
169//! ```bash
170//! subkey inspect "soup lyrics media market way crouch elevator put moon useful question wide"
171//! ```
172//!
173//! which recovers the account `5Fe4sqj2K4fRuzEGvToi4KATqZfiDU7TqynjXG6PZE2dxwyh` and not
174//! `5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC` as we expected. The additional user-defined
175//! **password** (`extra_secret` in our example) is now required to fully recover the account. Let's
176//! inspect the the previous mnemonic, this time passing also the required `password` as shown
177//! below:
178//!
179//! ```bash
180//! subkey inspect --password extra_secret "soup lyrics media market way crouch elevator put moon useful question wide"
181//! ```
182//!
183//! This time, we properly recovered `5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC`.
184//!
185//! ### Inspecting a key
186//!
187//! If you have *some data* about a key, `subkey inspect` will help you discover more information
188//! about it.
189//!
190//! If you have **secrets** that you would like to verify for instance, you can use:
191//!
192//! ```bash
193//! subkey inspect < mnemonic | seed >
194//! ```
195//!
196//! If you have only **public data**, you can see a subset of the information:
197//!
198//! ```bash
199//! subkey inspect --public < pubkey | address >
200//! ```
201//!
202//! **NOTE**: While you will be able to recover the secret seed from the mnemonic, the opposite is
203//! not possible.
204//!
205//! **NOTE**: For obvious reasons, the **secrets** cannot be recovered from passing **public data**
206//! such as `pubkey` or `address` as input.
207//!
208//! command:
209//!
210//! ```bash
211//! subkey inspect 0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d
212//! ```
213//!
214//! output:
215//!
216//! ```text
217//! Secret Key URI `0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d` is account:
218//!   Secret seed:      0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d
219//!   Public key (hex): 0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515
220//!   Account ID:       0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515
221//!   SS58 Address:     5Hpm9fq3W3dQgwWpAwDS2ZHKAdnk86QRCu7iX4GnmDxycrte
222//! ```
223//!
224//! ### Signing
225//!
226//! `subkey` allows using a **secret key** to sign a random message. The signature can then be
227//! verified by anyone using your **public key**:
228//!
229//! ```bash
230//! echo -n <msg> | subkey sign --suri <seed|mnemonic>
231//! ```
232//!
233//! example:
234//!
235//! ```text
236//! MESSAGE=hello
237//! SURI=0xa05c75731970cc7868a2fb7cb577353cd5b31f62dccced92c441acd8fee0c92d
238//! echo -n $MESSAGE | subkey sign --suri $SURI
239//! ```
240//!
241//! output:
242//!
243//! ```text
244//! 9201af3788ad4f986b800853c79da47155f2e08fde2070d866be4c27ab060466fea0623dc2b51f4392f4c61f25381a62848dd66c5d8217fae3858e469ebd668c
245//! ```
246//!
247//! **NOTE**: Each run of the `sign` command will yield a different output. While each signature is
248//! different, they are all valid.
249//!
250//! ### Verifying a signature
251//!
252//! Given a message, a signature and an address, `subkey` can verify whether the **message** has
253//! been digitally signed by the holder (or one of the holders) of the **private key** for the given
254//! **address**:
255//!
256//! ```bash
257//! echo -n <msg> | subkey verify <sig> <address>
258//! ```
259//!
260//! example:
261//!
262//! ```bash
263//! MESSAGE=hello
264//! URI=0xfec70cfbf1977c6965b5af10a4534a6a35d548eb14580594d0bc543286892515
265//! SIGNATURE=9201af3788ad4f986b800853c79da47155f2e08fde2070d866be4c27ab060466fea0623dc2b51f4392f4c61f25381a62848dd66c5d8217fae3858e469ebd668c
266//! echo -n $MESSAGE | subkey verify $SIGNATURE $URI
267//! ```
268//!
269//! output:
270//!
271//! ```text
272//! Signature verifies correctly.
273//! ```
274//!
275//! A failure looks like:
276//!
277//! ```text
278//! Error: SignatureInvalid
279//! ```
280//!
281//! ### Using the vanity generator
282//!
283//! You can use the included vanity generator to find a seed that provides an address which includes
284//! the desired pattern. Be warned, depending on your hardware this may take a while.
285//!
286//! command:
287//!
288//! ```bash
289//! subkey vanity --network polkadot --pattern bob
290//! ```
291//!
292//! output:
293//!
294//! ```text
295//! Generating key containing pattern 'bob'
296//! best: 190 == top: 189
297//! Secret Key URI `0x8c9a73097f235b84021a446bc2826a00c690ea0be3e0d81a84931cb4146d6691` is account:
298//!   Secret seed:      0x8c9a73097f235b84021a446bc2826a00c690ea0be3e0d81a84931cb4146d6691
299//!   Public key (hex): 0x1a8b32e95c1f571118ea0b84801264c3c70f823e320d099e5de31b9b1f18f843
300//!   Account ID:       0x1a8b32e95c1f571118ea0b84801264c3c70f823e320d099e5de31b9b1f18f843
301//!   SS58 Address:     1bobYxBPjZWRPbVo35aSwci1u5Zmq8P6J2jpa4kkudBZMqE
302//! ```
303//!
304//! `Bob` now got a nice address starting with their name:
305//! 1**bob**YxBPjZWRPbVo35aSwci1u5Zmq8P6J2jpa4kkudBZMqE.
306//!
307//! **Note**: While `Bob`, having a short name (3 chars), got a result rather quickly, it will take
308//! much longer for `Alice` who has a much longer name, thus the chances to generate a random
309//! address that contains the chain `alice` will be much smaller.
310
311use clap::Parser;
312use sc_cli::{
313	Error, GenerateCmd, GenerateKeyCmdCommon, InspectKeyCmd, InspectNodeKeyCmd, SignCmd, VanityCmd,
314	VerifyCmd,
315};
316
317#[derive(Debug, Parser)]
318#[command(
319	name = "subkey",
320	author = "Parity Team <admin@parity.io>",
321	about = "Utility for generating and restoring with Substrate keys",
322	version
323)]
324pub enum Subkey {
325	/// Generate a random node key, write it to a file or stdout and write the
326	/// corresponding peer-id to stderr
327	GenerateNodeKey(GenerateKeyCmdCommon),
328
329	/// Generate a random account
330	Generate(GenerateCmd),
331
332	/// Gets a public key and a SS58 address from the provided Secret URI
333	Inspect(InspectKeyCmd),
334
335	/// Load a node key from a file or stdin and print the corresponding peer-id
336	InspectNodeKey(InspectNodeKeyCmd),
337
338	/// Sign a message, with a given (secret) key.
339	Sign(SignCmd),
340
341	/// Generate a seed that provides a vanity address.
342	Vanity(VanityCmd),
343
344	/// Verify a signature for a message, provided on STDIN, with a given (public or secret) key.
345	Verify(VerifyCmd),
346}
347
348/// Run the subkey command, given the appropriate runtime.
349pub fn run() -> Result<(), Error> {
350	match Subkey::parse() {
351		Subkey::GenerateNodeKey(cmd) => cmd.run(),
352		Subkey::Generate(cmd) => cmd.run(),
353		Subkey::Inspect(cmd) => cmd.run(),
354		Subkey::InspectNodeKey(cmd) => cmd.run(),
355		Subkey::Vanity(cmd) => cmd.run(),
356		Subkey::Verify(cmd) => cmd.run(),
357		Subkey::Sign(cmd) => cmd.run(),
358	}
359}