SilentDragonPaper is a paper wallet generator that can run completely offline.
You can run it on an air-gapped computer to generate your shielded z-addresses, which will allow you to keep your keys completely offline.
*Example:*
![screenshot](hushpaperwallet.png?raw=true)
![screenshot](SilentDragonPaper.png?raw=true)
# Download
hushpaperwallet is available as pre-built binaries from our [release page](https://github.com/MyHush/hushpaperwallet/releases). Download the zip file for your platform, extract it and run the `./hushpaperwallet` binary.
## Download
# Generating wallets
To generate a Hush paper wallet, simply run `./hushpaperwallet`
### Binary installation
SilentDragonPaper is available as pre-built binaries from our [release page](https://git.hush.is/hush/SilentDragonPaper/releases). Download the zip file for your platform, extract it and run the `./SilentDragonPaper` binary.
You'll be asked to type some random characters that will add entropy to the random number generator. Run with `--help` to see all options
### Source code installation
If you decide to compile from source, then first use git to get the source code as follows:
Then choose one of these two source compilation options to build the SilentDragonPaper CLI.
#### Recommended Option : Compile using "embedded" rust
## Saving as PDFs
To generate a Hush paper wallet and save it as a PDF, run
Here we do not need a system installed Rust to compile. The build.sh script pulls Rust version 1.48 down for us and builds with it.
```
./hushpaperwallet -z 3 --format pdf hushpaper-output.pdf
cd SilentDragonPaper
./build.sh
```
This will generate 3 shielded z-addresses and their corresponding private keys, and save them in a PDF file called `hushpaper-output.pdf`
#### Advanced Option : Compile using system installed rust
## Vanity Addresses
SilentDragonPaper is built with Rust. To compile from source, you must [install Rust 1.48](https://www.rust-lang.org/tools/install).
Older versions of Rust may work, newer versions will not.
You can generate a "vanity address" (that is, an address starting with a given prefix) by specifying a `--vanity` argument with the prefix you want.
```
cd SilentDragonPaper/cli
cargo build --release
```
Note that generating vanity addresses with a prefix longer than 4-5 characters is computationally expensive. You can run it on multiple CPUs on your computer by specifying the `--threads` option.
# Compiling from Source
#### Compiled binary location
The completed binary is available in the `cli/target/release` folder.
hushpaperwallet is built with rust. To compile from source, you [install Rust](https://www.rust-lang.org/tools/install).
## Usage Instructions
Checkout the hushpaperwallet repository and build the CLI
### Generating wallets
To generate a Hush paper wallet, simply run `./SilentDragonPaper` or `./target/release/SilentDragonPaper` or `./cli/target/release/SilentDragonPaper` depending on method you used to install.
You'll be asked to type some random characters that will add entropy to the random number generator. Run with `--help` to see all options
### Saving as PDFs
To generate a Hush paper wallet and save it as a PDF, run:
The binary is available in the `target/release` folder.
This will generate 3 shielded z-addresses and their corresponding private keys, and save them in a PDF file called `sdp.pdf`
### Vanity Addresses
You can generate a "vanity address" (that is, an address starting with a given prefix) by specifying a `--vanity` argument with the prefix you want.
Note that generating vanity addresses with a prefix longer than 4-5 characters is computationally expensive. You can run it on multiple CPUs on your computer by specifying the `--threads` option.
## Ensuring Security
When generating paper wallets that will store large amounts of crypto, please take special care to ensure the keys are generated and kept completely offline.
1. `hushpaperwallet` supports ARMv8 (Raspberry Pi 3+). You can put one in a Faraday cage along with a printer, and print out the PDFs securely.
2. Please ensure you supply random entropy when you run `hushpaperwallet`. Your entropy is mixed in with system-provided entropy to generate keys
1. `SilentDragonPaper` supports ARMv8 (Raspberry Pi 3+). You can put one in a Faraday cage along with a printer, and print out the PDFs securely.
2. Please ensure you supply random entropy when you run `SilentDragonPaper`. Your entropy is mixed in with system-provided entropy to generate keys
3. If you can, run with `unshare`, which will disable all network interfaces to a process, providing you with an additional layer of safety. (See next section)
4. After you've generated the keys, you can tear off the Address potion of the wallet and take it to your online computer/phone to send the address funds. Please always keep the private key offline.
5. When you're ready to spend the cold storage keys, import the private key into a full node, then don't re-use the key again.
### Run without network
If you are running a newish version of Linux, you can be doubly sure that the process is not contacting the network by running hushpaperwallet without the network namespace.
If you are running a newish version of Linux, you can be doubly sure that the process is not contacting the network by running SilentDragonPaper without the network namespace.
`unshare -n` runs the process without a network interface which means you can be sure that your data is not being sent across the network.
## Help options
```
USAGE:
hushpaperwallet [FLAGS] [OPTIONS] [output]
SilentDragonPaper [FLAGS] [OPTIONS] [output]
FLAGS:
-h, --help Prints help information
-n, --nohd Don't reuse HD keys. Normally, hushpaperwallet will use the same HD key to derive multiple
-n, --nohd Don't reuse HD keys. Normally, SilentDragonPaper will use the same HD key to derive multiple
addresses. This flag will use a new seed for each address
--testnet Generate Testnet addresses
-V, --version Prints version information
OPTIONS:
@ -84,22 +121,28 @@ OPTIONS:
-t, --taddrs <t_addresses> Numbe rof T addresses to generate [default: 0]
--threads <threads> Number of threads to use for the vanity address generator. Set this to the number of
CPUs you have [default: 1]
--vanity <vanity> Generate a vanity address with the given prefix
--vanity <vanity> Generate a vanity address with the given prefix.
Note that ['b', 'i', 'o', '1'] are not allowed in addresses.
-z, --zaddrs <z_addresses> Number of Z addresses (Sapling) to generate [default: 1]
ARGS:
<output> Name of output file.
```
## Support
For support join us on [Telegram Support](https://hush.is/telegram_support), or our [Main Telegram](https://hush.is/telegram) or tweet at [@MyHushTeam](https://twitter.com/MyHushTeam), or toot at our [Mastodon](https://fosstodon.org/@myhushteam), or [file an issue](https://git.hush.is/hush/SilentDragonPaper/issues).
## Copyright
Released under the GNU Public License Version 3.
Released under the [GNU Public License Version 3](https://www.gnu.org/licenses/gpl-3.0.en.html) or later.
.about("A command line Hush paper wallet generator")
.arg(Arg::with_name("format")
@ -24,7 +24,7 @@ fn main() {
.arg(Arg::with_name("nohd")
.short("n")
.long("nohd")
.help("Don't reuse HD keys. Normally, hushpaperwallet will use the same HD key to derive multiple addresses. This flag will use a new seed for each address"))
.help("Don't reuse HD keys. Normally, SilentDragonPaper will use the same HD key to derive multiple addresses. This flag will use a new seed for each address"))
.arg(Arg::with_name("output")
.short("o")
.long("output")
@ -37,7 +37,7 @@ fn main() {
.help("Provide additional entropy to the random number generator. Any random string, containing 32-64 characters"))
.arg(Arg::with_name("vanity_prefix")
.long("vanity")
.help("Generate a vanity address with the given prefix")
.help("Generate a vanity address with the given prefix. Note that ['b', 'i', 'o', '1'] are not allowed in addresses.")
.takes_value(true))
.arg(Arg::with_name("threads")
.long("threads")
@ -47,7 +47,7 @@ fn main() {
.arg(Arg::with_name("t_addresses")
.short("t")
.long("taddrs")
.help("Numbe rof T addresses to generate")
.help("Number of t-addresses to generate")
.takes_value(true)
.default_value("0")
.validator(|i:String|matchi.parse::<i32>(){
@ -57,7 +57,7 @@ fn main() {
.arg(Arg::with_name("z_addresses")
.short("z")
.long("zaddrs")
.help("Number of Z addresses (Sapling) to generate")
.help("Number of z-addresses (Sapling) to generate")
.takes_value(true)
.default_value("1")
.validator(|i:String|matchi.parse::<i32>(){
@ -78,16 +78,6 @@ fn main() {
return;
}
// Get the filename and output format
letfilename=matches.value_of("output");
letformat=matches.value_of("format").unwrap();
// Writing to PDF requires a filename
ifformat=="pdf"&&filename.is_none(){
eprintln!("Need an output file name when writing to PDF");