bech32 addrs:
modified: Getting-Started-with-MMGen.md bech32 addrs, password generation: modified: Recovering-Your-Keys-Without-the-MMGen-Software.md
parent
45e2207e5b
commit
a059bfaa03
2 changed files with 113 additions and 64 deletions
|
|
@ -155,7 +155,7 @@ overestimated.
|
|||
|
||||
#### <a name='a_ga'>Generate addresses (offline computer)</a>
|
||||
|
||||
Now generate ten Segwit addresses with your just-created wallet:
|
||||
Now generate ten Segwit-P2SH addresses with your just-created wallet:
|
||||
|
||||
$ mmgen-addrgen --type=segwit 1-10
|
||||
...
|
||||
|
|
@ -178,17 +178,22 @@ Now generate ten Segwit addresses with your just-created wallet:
|
|||
Note that the address range ‘1-10’ specified on the command line is included in
|
||||
the resulting filename.
|
||||
|
||||
MMGen currently supports three address types: legacy uncompressed, compressed
|
||||
P2PKH and Segwit, denoted by the respective code letters ‘L’, ‘C’ and ‘S’. For
|
||||
backwards compatibility, legacy addresses are generated by default. To generate
|
||||
compressed addresses, specify `--type=compressed` on the command line.
|
||||
MMGen currently supports four Bitcoin address types: ‘legacy’ (uncompressed
|
||||
P2PKH), ‘compressed’ (compressed P2PKH), ‘segwit’ (P2SH-P2WPKH) and ‘bech32’
|
||||
(native Segwit), denoted by the code letters ‘L’, ‘C’, ‘S’ and ‘B’ respectively.
|
||||
Address types can be referred to either in full or by code letter. To generate
|
||||
Bech32 addresses, for example, you can specify either `--type=bech32` or
|
||||
`--type=B` on the command line.
|
||||
|
||||
Legacy addresses are of interest only for existing pre-Segwit MMGen
|
||||
installations, and it's unlikely you'll wish to generate them. Compressed
|
||||
addresses are the preferred choice for Bitcoin Cash (BCH) wallets, since Bitcoin
|
||||
Cash doesn't support Segwit.
|
||||
For backwards compatibility, legacy addresses are generated by default, but this
|
||||
is probably not what you want unless you have a very old MMGen installation
|
||||
created before compressed address support was added. Most new users will wish
|
||||
to generate either Segwit-P2SH (‘S’) or Bech32 (‘B’) addresses instead. For
|
||||
BCH, which lacks Segwit support, compressed (‘C’) addresses are the best choice.
|
||||
|
||||
# legacy uncompressed
|
||||
Generation examples for various address types:
|
||||
|
||||
# legacy (uncompressed P2PKH)
|
||||
$ mmgen-addrgen 1-10
|
||||
...
|
||||
$ cat '89ABCDEF[1-10].addrs'
|
||||
|
|
@ -204,6 +209,14 @@ Cash doesn't support Segwit.
|
|||
1 13jbRxWjswXtaDzLBJDboMcIe6nLohFb9M
|
||||
...
|
||||
|
||||
# Bech32 (native Segwit)
|
||||
$ mmgen-addrgen --type=bech32 1-10
|
||||
...
|
||||
$ cat '89ABCDEF-B[1-10].addrs'
|
||||
89ABCDEF BECH32 {
|
||||
1 bc1q9c9273thh3xh86lk6z34raejz6j2s8ytgyb7my
|
||||
...
|
||||
|
||||
Note that for non-legacy address types the code letter is included in the
|
||||
filename.
|
||||
|
||||
|
|
@ -279,8 +292,10 @@ addresses where the funds are stored in a separate file to use during signing.*
|
|||
|
||||
Note that each address has a unique ID (the ‘MMGen ID’) consisting of a Seed ID,
|
||||
address type code letter, and index. Addresses of different types may be
|
||||
imported into the same tracking wallet; since they're generated from different
|
||||
sub-seeds you needn't worry about key reuse.
|
||||
imported into the same tracking wallet, and since they're generated from different
|
||||
sub-seeds you needn't worry about key reuse. For example, the addresses
|
||||
`89ABCDEF:S:1` and `89ABCDEF:B:1` are cryptographically distinct: no one but the
|
||||
wallet's owner can see that they were generated from the same seed.
|
||||
|
||||
Now that your addresses are being tracked, you may go ahead and send some BTC to
|
||||
them over the Bitcoin network. If you send 0.1, 0.2, 0.3 and 0.4 BTC
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@
|
|||
|
||||
* <a href='#a_i'>Introduction</a>
|
||||
* <a href='#a_rs'>Obtaining the binary seed</a>
|
||||
* <a href='#a_ss'>Convert the seed to binary (legacy addresses)</a>
|
||||
* <a href='#a_cs'>Scramble the seed and save to binary (compressed addresses, Segwit addresses and passwords)</a>
|
||||
* <a href='#a_ss'>Convert the seed to binary (legacy uncompressed addresses)</a>
|
||||
* <a href='#a_cs'>Scramble the seed and save to binary (non-legacy and altcoin addresses and passwords)</a>
|
||||
* <a href='#a_gk'>Generating the keys</a>
|
||||
* <a href='#a_cr'>Checking the result (optional, address example)</a>
|
||||
* <a href='#a_hpw'>Converting the hex value to a password (password example)</a>
|
||||
* <a href='#a_hw'>Hex to WIF by hand</a>
|
||||
* <a href='#a_bcu'>Base-conversion utility</a>
|
||||
* <a href='#a_mh'>Converting an MMGen mnemonic to hexadecimal format</a>
|
||||
|
||||
#### <a name='a_i'>Introduction</a>
|
||||
|
|
@ -48,8 +51,9 @@ case too:
|
|||
3 37wM8hwt69qwH7hZHAMn6RVdc8vMuM1CwJ
|
||||
}
|
||||
|
||||
Keys for MMGen's compressed ('C') addresses are generated in a similar way as
|
||||
Segwit ones, as you'll see below, so we won't consider that case separately.
|
||||
Keys for compressed ('C'), Bech32 (‘B’) and altcoin addresses, as well as
|
||||
passwords, are generated in a way analogous to Segwit keys, so for them you’ll
|
||||
proceed as with the Segwit case.
|
||||
|
||||
Here's the seed itself in mmhex format, which you've stored in some safe place (on
|
||||
paper in a safe-deposit box, for example):
|
||||
|
|
@ -66,7 +70,7 @@ into Bitcoin Core or some other wallet.
|
|||
We'll solve this task using standard command-line utilities available on any
|
||||
Linux or other Unix-like system.
|
||||
|
||||
> #### <a name='a_ss'>Convert the seed to binary (legacy addresses)</a>
|
||||
> #### <a name='a_ss'>Convert the seed to binary (legacy uncompressed addresses)</a>
|
||||
|
||||
> For the legacy addresses, we begin by converting the seed to binary form and
|
||||
> storing it in a file. For that we use 'xxd', a handy tool for converting binary
|
||||
|
|
@ -75,7 +79,7 @@ Linux or other Unix-like system.
|
|||
|
||||
$ echo 456d7f5f1c4bfe3bc916b87560ae6a3e | xxd -r -p > myseed.bin
|
||||
|
||||
> #### <a name='a_cs'>Scramble the seed and save to binary (compressed addresses, Segwit addresses and passwords)</a>
|
||||
> #### <a name='a_cs'>Scramble the seed and save to binary (non-legacy and altcoin addresses and passwords)</a>
|
||||
|
||||
> Other address types and passwords are generated by first “scrambling” the
|
||||
> seed with a unique identifier, or “scramble string”, using the HMAC-SHA256
|
||||
|
|
@ -84,39 +88,46 @@ Linux or other Unix-like system.
|
|||
|
||||
> Our first task then is to find out the correct scramble string for our coin
|
||||
> and address type (or password). For BTC and BTC fork coins, the string will
|
||||
> be simply the address type: 'compressed' or 'segwit'. For Bitcoin-derived
|
||||
> be simply the address type: `compressed` or `segwit`. For Bitcoin-derived
|
||||
> altcoins, the string is the coin symbol and address type separated by a colon,
|
||||
> e.g. 'ltc:legacy'. The strings for non-Bitcoin-derived altcoins are irregular
|
||||
> e.g. `ltc:legacy`. The strings for non-Bitcoin-derived altcoins are irregular
|
||||
> and are listed in the table below. For passwords, the string is the password
|
||||
> format, e.g. 'b58'; the password length, e.g. '20'; and the password ID
|
||||
> string, e.g. 'alice@fubar.io', all separated by colons:
|
||||
> format, e.g. `b58`; the password length, e.g. `20`; and the password ID
|
||||
> string, e.g. `alice@fubar.io`, all separated by colons:
|
||||
|
||||
> | Coin+Addrtype / Passwd type+length+ID | | | Scramble String |
|
||||
> |:----------------------------------------|-|-|:-------------------------|
|
||||
> | BTC compressed | | | `compressed` |
|
||||
> | BTC Segwit | | | `segwit` |
|
||||
> | LTC legacy | | | `ltc:legacy` |
|
||||
> | LTC compressed | | | `ltc:compressed` |
|
||||
> | LTC Segwit | | | `ltc:segwit` |
|
||||
> | DASH legacy | | | `dash:legacy` |
|
||||
> | DASH compressed | | | `dash:compressed` |
|
||||
> | ETH | | | `eth` |
|
||||
> | ETC | | | `etc` |
|
||||
> | XMR | | | `xmr:monero` |
|
||||
> | ZEC-T | | | `zec:legacy` |
|
||||
> | ZEC-Z | | | `zec:zcash_z` |
|
||||
> | Base58 passwords for Alice's email acct.| | | `b58:20:alice@fubar.io` |
|
||||
> | Same as above, half-length passwords | | | `b58:10:alice@fubar.io` |
|
||||
> | Same as above, Base32 passwords | | | `b32:24:alice@fubar.io` |
|
||||
> | Hex seed for Alice's PGP key | | | `hex:64:alice@gnupg` |
|
||||
> | Coin + Address type | Scramble String |
|
||||
> |:-----------------------------------------|:-------------------------|
|
||||
> | BTC/BCH compressed | `compressed` |
|
||||
> | BTC Segwit-P2SH | `segwit` |
|
||||
> | BTC native Segwit (Bech32) | `bech32` |
|
||||
> | LTC legacy | `ltc:legacy` |
|
||||
> | LTC compressed | `ltc:compressed` |
|
||||
> | LTC Segwit | `ltc:segwit` |
|
||||
> | DASH legacy | `dash:legacy` |
|
||||
> | DASH compressed | `dash:compressed` |
|
||||
> | ETH | `eth` |
|
||||
> | ETC | `etc` |
|
||||
> | XMR | `xmr:monero` |
|
||||
> | ZEC-T | `zec:legacy` |
|
||||
> | ZEC-Z | `zec:zcash_z` |
|
||||
|
||||
> | Password type | Scramble String |
|
||||
> |:-----------------------------------------|:-------------------------|
|
||||
> | Base58 passwords for Alice's email acct. | `b58:20:alice@fubar.io` |
|
||||
> | Same as above, half-length passwords | `b58:10:alice@fubar.io` |
|
||||
> | Same as above, default Base32 passwords | `b32:24:alice@fubar.io` |
|
||||
> | Hex seed for Alice's PGP key | `hex:64:alice@gnupg` |
|
||||
|
||||
> Once we've determined the correct string, we scramble our seed with it as
|
||||
> follows using the `openssl` utility, which is included by default on all
|
||||
> Unix-based systems:
|
||||
> follows using the `openssl` utility available by default on any Unix-based
|
||||
> system:
|
||||
|
||||
# E.g. for LTC Segwit addresses:
|
||||
$ echo -n 'ltc:segwit' | openssl dgst -r -sha256 -mac hmac -macopt hexkey:456d7f5f1c4bfe3bc916b87560ae6a3e | xxd -r -p > scrambled-round0.bin
|
||||
|
||||
# E.g. for default-format passwords for Alice's email account:
|
||||
$ echo -n 'b58:20:alice@fubar.io' | openssl dgst -r -sha256 -mac hmac -macopt hexkey:456d7f5f1c4bfe3bc916b87560ae6a3e | xxd -r -p > scrambled-round0.bin
|
||||
|
||||
> Now add the ten rounds of sha256:
|
||||
|
||||
$ for i in 0 1 2 3 4 5 6 7 8 9; do
|
||||
|
|
@ -124,7 +135,7 @@ Linux or other Unix-like system.
|
|||
done
|
||||
$ mv scrambled-round10.bin myseed.bin
|
||||
|
||||
#### <a name='a_gk'>Generating the keys</a>
|
||||
#### <a name='a_gk'>Generating the keys</a>
|
||||
|
||||
The MMGen key-generating algorithm uses a chain of SHA-512 hashes with double
|
||||
SHA-256 branches to generate the keys from which each address is derived. To
|
||||
|
|
@ -136,14 +147,18 @@ save it in binary form:
|
|||
A double SHA-256 hash of the first link gives us the key of our first address:
|
||||
|
||||
$ sha256sum link1.bin | xxd -r -p | sha256sum
|
||||
05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36 -
|
||||
05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
|
||||
|
||||
Or, in the Segwit case:
|
||||
# or, for the Segwit example:
|
||||
b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0
|
||||
|
||||
b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0 -
|
||||
# or, for the password example:
|
||||
bd60b8ba034bbb40498667ee600bc0cc0b99eb19164e8d412a48f16da4e00d6b
|
||||
|
||||
With 'mmgen-tool', we can easily generate the WIF key and address from this
|
||||
hexadecimal key and see that it's correct:
|
||||
> #### <a name='a_cr'>Checking the result (optional, address example)</a>
|
||||
|
||||
> With 'mmgen-tool', we can easily generate the WIF key and address from this
|
||||
> hexadecimal key and see that it's correct:
|
||||
|
||||
$ mmgen-tool hex2wif 05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
|
||||
5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
|
||||
|
|
@ -151,7 +166,7 @@ hexadecimal key and see that it's correct:
|
|||
$ mmgen-tool wif2addr 5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
|
||||
1JVi3qcNcjMM7cTR7y9ihKUG1yDLpKRJfL # matches FE3C6545:L:1 above
|
||||
|
||||
Or, in the Segwit case:
|
||||
> Or, for the Segwit example:
|
||||
|
||||
$ mmgen-tool hex2wif b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0 compressed=1
|
||||
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F
|
||||
|
|
@ -160,24 +175,41 @@ Or, in the Segwit case:
|
|||
$ mmgen-tool wif2addr L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F segwit=1
|
||||
3LpkKqtGkcCukRrgEFWyCajSApioiEWeTw # matches FE3C6545:S:1 above
|
||||
|
||||
But since we're trying to do this without the MMGen software, we need to find
|
||||
some other way to do the hex-to-WIF conversion. We could use one of many
|
||||
key-manipulation tools available on the Internet, such as [this one][01], or
|
||||
[this one][02]. Or we can do it ourselves: that will be covered in the next
|
||||
section.
|
||||
> But since we're trying to do this without the MMGen software, we need to find
|
||||
> some other way to do the hex-to-WIF conversion. We could use one of many
|
||||
> key-manipulation tools available on the Internet, such as [this one][01], or
|
||||
> [this one][02]. Or we can do it ourselves: that will be covered in the next
|
||||
> section.
|
||||
|
||||
Meanwhile, let's finish generating hex keys for the rest of our addresses. To
|
||||
get the next key, we generate the next link in the chain from the first link and
|
||||
take its double SHA-256 hash, just as we did for the first one:
|
||||
Meanwhile, let's finish generating hex keys for the rest of our addresses (or
|
||||
passwords). To get the next key, we generate the next link in the chain from
|
||||
the first link and take its double SHA-256 hash, just as we did for the first
|
||||
one:
|
||||
|
||||
$ sha512sum link1.bin | xxd -r -p > link2.bin
|
||||
$ sha256sum link2.bin | xxd -r -p | sha256sum
|
||||
5db8fe3c8b52ccc98deab5afae780b6fbe56629e7ee1c6ed826fc2d6a81fb144 - (uncompressed example)
|
||||
42f1b998f0f9b7b27b5d0b92ffa8c1c6b96d7202789c41b6e6a6a402e318a04d - (Segwit example)
|
||||
5db8fe3c8b52ccc98deab5afae780b6fbe56629e7ee1c6ed826fc2d6a81fb144 (uncompressed example)
|
||||
42f1b998f0f9b7b27b5d0b92ffa8c1c6b96d7202789c41b6e6a6a402e318a04d (Segwit example)
|
||||
9b59cec2e5d4f2a74f0d4eb2400efcf854f5a893bef0e9bf1ee83f72ca1118c3 (password example)
|
||||
|
||||
And so on and so forth, until we've generated all the keys we need: three, in our case.
|
||||
|
||||
#### <a name='a_hw'>Hex to WIF by hand</a>
|
||||
> #### <a name='a_hpw'>Converting the hex value to a password (password example)</a>
|
||||
|
||||
> If it's passwords we're generating, we must now convert our hex key to the
|
||||
> desired password format. This example uses the default base-58, 20-character
|
||||
> format and the key we generated above using the ID string `alice@fubar.io`.
|
||||
> We can convert the key to base 58 using our homemade `hex2b58.py` utility (see
|
||||
> <a href='#a_bcu'>Base-conversion utility</a> below):
|
||||
|
||||
$ ./hex2b58.py bd60b8ba034bbb40498667ee600bc0cc0b99eb19164e8d412a48f16da4e00d6b
|
||||
DkFbZk2fDKQ7C55ASHQjhwcCdTsCiRq4ZLMMD5WQVAvv
|
||||
|
||||
> The password is just the last 20 characters of the output:
|
||||
|
||||
dTsCiRq4ZLMMD5WQVAvv
|
||||
|
||||
#### <a name='a_hw'>Hex to WIF by hand</a>
|
||||
|
||||
Since we've chosen to convert our hex keys to WIF format manually, we have a bit
|
||||
of work ahead of us. Let's begin with our just-generated key #1 from seed
|
||||
|
|
@ -264,8 +296,10 @@ clearer:
|
|||
|
||||
result = numtob58(num)
|
||||
|
||||
Adapting our code a bit and putting it in a file gives us have a handy
|
||||
conversion utility we can use for any key:
|
||||
> #### <a name='a_bcu'>Base-conversion utility</a>
|
||||
|
||||
> Adapting our code a bit and putting it in a file gives us have a handy
|
||||
> conversion utility we can use for any key:
|
||||
|
||||
$ cat hex2b58.py
|
||||
#!/usr/bin/env python
|
||||
|
|
@ -281,7 +315,7 @@ conversion utility we can use for any key:
|
|||
$ hex2b58.py 80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a00189bba812
|
||||
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F
|
||||
|
||||
#### <a name='a_mh'>Converting an MMGen mnemonic to hexadecimal format</a>
|
||||
#### <a name='a_mh'>Converting an MMGen mnemonic to hexadecimal format</a>
|
||||
|
||||
Our familiar base-10 system uses a series of ten symbols known as digits to
|
||||
represent numbers from zero to nine:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue