├── slip-0039 ├── lagrange.png ├── secret_sharing_1.png ├── secret_sharing_2.png ├── secret_sharing_3.png ├── secret_sharing_4.png ├── test_wordlist.sh └── wordlist.txt ├── check.sh ├── markdownlint.json ├── .travis.yml ├── slip-0015 ├── 2_accountkey.py ├── 1_masterkey.py ├── 3_decrypt.py └── 4_encrypt.py ├── slip-0020.md ├── slip-0000.md ├── slip-0012.md ├── slip-0010 ├── test.py └── testvectors.py ├── slip-0017.md ├── slip-0077.md ├── slip-0013.md ├── README.md ├── slip-0048 └── testvectors.py ├── slip-0011.md ├── slip-0173.md ├── slip-0132.md ├── slip-0021.md ├── slip-0016.md ├── slip-0014.md ├── slip-0023.md ├── slip-0015.md ├── slip-0014 └── addresses.md ├── slip-0048.md ├── slip-0032.md ├── slip-0022.md ├── slip-0010.md ├── LICENSE └── slip-0019.md /slip-0039/lagrange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pi-node/slips/HEAD/slip-0039/lagrange.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pi-node/slips/HEAD/slip-0039/secret_sharing_1.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pi-node/slips/HEAD/slip-0039/secret_sharing_2.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pi-node/slips/HEAD/slip-0039/secret_sharing_3.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pi-node/slips/HEAD/slip-0039/secret_sharing_4.png -------------------------------------------------------------------------------- /check.sh: -------------------------------------------------------------------------------- 1 | echo SLIP-0044 duplicates: 2 | grep '^[0-9]' slip-0044.md | cut -f 3 -d '|' | tr -d ' ' | sort | uniq -d 3 | -------------------------------------------------------------------------------- /markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD004": false, 3 | "MD013": false, 4 | "MD024": false, 5 | "MD029": false, 6 | "MD033": false, 7 | "MD040": false 8 | } 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "node" 5 | 6 | before_script: 7 | - npm install -g markdownlint-cli 8 | 9 | script: 10 | - markdownlint -c markdownlint.json *.md 11 | - ./check.sh 12 | -------------------------------------------------------------------------------- /slip-0015/2_accountkey.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import hmac, hashlib, base58, binascii, sys 4 | 5 | # xpub of the first account 6 | xpub = sys.argv[1] 7 | # hexadecimal representation of the master key 8 | master_hex = sys.argv[2] 9 | 10 | master_key = binascii.unhexlify(master_hex) 11 | digest = hmac.new(master_key, xpub, hashlib.sha256).digest() 12 | print base58.b58encode_check(digest) 13 | 14 | -------------------------------------------------------------------------------- /slip-0015/1_masterkey.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | from trezorlib.client import TrezorClient 4 | from trezorlib.transport_hid import HidTransport 5 | from binascii import hexlify, unhexlify 6 | 7 | # for more details on this, see python-trezor 8 | client = TrezorClient(HidTransport(HidTransport.enumerate()[0])) 9 | 10 | bip32_path = client.expand_path("10015'/0'") 11 | masterkey = client.encrypt_keyvalue( 12 | bip32_path, 13 | "Enable labeling?", 14 | unhexlify("fedcba98765432100123456789abcdeffedcba98765432100123456789abcdef"), 15 | True, 16 | True 17 | ) 18 | 19 | print 'Key:', hexlify(masterkey) 20 | 21 | -------------------------------------------------------------------------------- /slip-0039/test_wordlist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # wordlist is alphabetically sorted 4 | diff wordlist.txt <(sort wordlist.txt) && echo OK 5 | 6 | # no word is shorter than 4 letters 7 | diff wordlist.txt <(grep '^....' wordlist.txt) && echo OK 8 | 9 | # no word is longer than 8 letters 10 | ! grep -q '^.........' wordlist.txt && echo OK 11 | 12 | # all words have unique 4-letter prefix 13 | diff <(cut -c 1-4 wordlist.txt) <(cut -c 1-4 wordlist.txt | sort -u) && echo OK 14 | 15 | # wordlist contains only common English words (+ the word "satoshi") 16 | test "$(comm -23 wordlist.txt <(aspell -l en dump master | tr [A-Z] [a-z] | sort ))" = "satoshi" && echo OK 17 | -------------------------------------------------------------------------------- /slip-0020.md: -------------------------------------------------------------------------------- 1 | # SLIP-0020 : Proof of User Confirmation 2 | 3 | ``` 4 | Number: SLIP-0020 5 | Title: Proof of User Confirmation 6 | Type: Standard 7 | Status: Draft 8 | Authors: TBD 9 | Created: 2019-04-25 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This is a section for an abstract. 15 | 16 | ## Motivation 17 | 18 | This is a section for a motivation. 19 | 20 | ## Body 21 | 22 | This is a section for a body. The title of the section should be changed 23 | and the section can be split into multiple sections and subsections. 24 | 25 | ## References 26 | 27 | This is a section for references such as links to other documents (BIP or SLIP) 28 | or to reference implementations. 29 | -------------------------------------------------------------------------------- /slip-0000.md: -------------------------------------------------------------------------------- 1 | # SLIP-0000 : SLIP Template 2 | 3 | ``` 4 | Number: SLIP-0000 5 | Title: SLIP Template 6 | Type: Informational 7 | Status: Accepted 8 | Authors: SatoshiLabs 9 | Created: 2014-06-06 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This is a section for an abstract. 15 | 16 | ## Motivation 17 | 18 | This is a section for a motivation. 19 | 20 | ## Body 21 | 22 | This is a section for a body. The title of the section should be changed 23 | and the section can be split into multiple sections and subsections. 24 | 25 | ## References 26 | 27 | This is a section for references such as links to other documents (BIP or SLIP) 28 | or to reference implementations. 29 | -------------------------------------------------------------------------------- /slip-0012.md: -------------------------------------------------------------------------------- 1 | # SLIP-0012 : Public key encryption using deterministic hierarchy 2 | 3 | ``` 4 | Number: SLIP-0012 5 | Title: Public key encryption using deterministic hierarchy 6 | Type: Standard 7 | Status: Draft 8 | Authors: Pavol Rusnak 9 | Marek Palatinus 10 | Created: 2014-06-12 11 | ``` 12 | 13 | ## Abstract 14 | 15 | This is a section for an abstract. 16 | 17 | ## Motivation 18 | 19 | This is a section for a motivation. 20 | 21 | ## Body 22 | 23 | This is a section for a body. The title of the section should be changed 24 | and the section can be split into multiple sections and subsections. 25 | 26 | ## References 27 | 28 | This is a section for references such as links to other documents (BIP or SLIP) 29 | or to reference implementations. 30 | -------------------------------------------------------------------------------- /slip-0015/3_decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import hmac, hashlib, binascii, sys 4 | from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes 5 | from cryptography.hazmat.backends import default_backend 6 | 7 | key = sys.argv[1] 8 | 9 | constant_hex = "0123456789abcdeffedcba9876543210" 10 | constant = binascii.unhexlify(constant_hex) 11 | digest = hmac.new(key, constant, hashlib.sha512).digest() 12 | 13 | filename_binary = digest[0:32] 14 | 15 | # right now the file needs to be in the working directory 16 | filename = binascii.hexlify(filename_binary) + ".mtdt" 17 | 18 | backend = default_backend() 19 | cipherkey = digest[32:64] 20 | 21 | with open(filename, "rb") as f: 22 | iv = f.read(12) 23 | tag = f.read(16) 24 | cipher = Cipher(algorithms.AES(cipherkey), modes.GCM(iv, tag), backend=backend) 25 | decryptor = cipher.decryptor() 26 | data = ""; 27 | while True: 28 | block = f.read(16) 29 | # data are not authenticated yet 30 | if block: 31 | data = data + decryptor.update(block) 32 | else: 33 | break 34 | # throws exception when the tag is wrong 35 | data = data + decryptor.finalize() 36 | 37 | print data 38 | 39 | -------------------------------------------------------------------------------- /slip-0015/4_encrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import hmac, hashlib, binascii, sys, os 4 | from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes 5 | from cryptography.hazmat.backends import default_backend 6 | 7 | key = sys.argv[1] 8 | 9 | constant_hex = "0123456789abcdeffedcba9876543210" 10 | constant = binascii.unhexlify(constant_hex) 11 | digest = hmac.new(key, constant, hashlib.sha512).digest() 12 | 13 | filename_binary = digest[0:32] 14 | 15 | # right now the file needs to be in the working directory 16 | filename = binascii.hexlify(filename_binary) + ".mtdt" 17 | 18 | # hardcoded 19 | data = """{ 20 | "accountLabel": "Saving account", 21 | "addressLabels": { 22 | "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL": "My receiving address", 23 | "1GWFxtwWmNVqotUPXLcKVL2mUKpshuJYo": "" 24 | }, 25 | "version": "1.0.0", 26 | "outputLabels": { 27 | "350eebc1012ce2339b71b5fca317a0d174abc3a633684bc65a71845deb596539": { 28 | "0": "Money to Adam" 29 | }, 30 | "ebbd138134e2c8acfee4fd4edb6f7f9175ee7b4020bcc82aba9a13ce06fae85b": { 31 | "0": "Feeding bitcoin eater" 32 | } 33 | } 34 | }""" 35 | 36 | backend = default_backend() 37 | cipherkey = digest[32:64] 38 | 39 | iv = os.urandom(12) 40 | cipher = Cipher(algorithms.AES(cipherkey), modes.GCM(iv), backend=backend) 41 | encryptor = cipher.encryptor() 42 | 43 | ctext = encryptor.update(data) + encryptor.finalize() 44 | tag = encryptor.tag 45 | 46 | with open(filename, "wb") as f: 47 | f.write(iv) 48 | f.write(tag) 49 | f.write(ctext) 50 | 51 | -------------------------------------------------------------------------------- /slip-0010/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import binascii 4 | import hashlib 5 | import hmac 6 | import struct 7 | 8 | 9 | def int_to_string(x, pad): 10 | result = ['\x00'] * pad 11 | while x > 0: 12 | pad -= 1 13 | ordinal = x & 0xFF 14 | result[pad] = (chr(ordinal)) 15 | x >>= 8 16 | return ''.join(result) 17 | 18 | def string_to_int(s): 19 | result = 0 20 | for c in s: 21 | if not isinstance(c, int): 22 | c = ord(c) 23 | result = (result << 8) + c 24 | return result 25 | 26 | 27 | # mode 0 - compatible with BIP32 private derivation 28 | def derive(parent_key, parent_chaincode, i): 29 | assert len(parent_key) == 32 30 | assert len(parent_chaincode) == 32 31 | secp256k1_n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 32 | k = parent_chaincode 33 | d = '\x00' + parent_key + struct.pack('>L', i) 34 | h = hmac.new(k, d, hashlib.sha512).digest() 35 | key, chaincode = h[:32], h[32:] 36 | key = (string_to_int(key) + string_to_int(parent_key)) % secp256k1_n 37 | key = int_to_string(key, 32) 38 | return (key, chaincode) 39 | 40 | # mode 1 - universal 41 | def derive_universal(parent_key, parent_chaincode, i, n, curveid, data): 42 | assert len(parent_key) == 32 43 | assert len(parent_chaincode) == 32 44 | ctr = 0 45 | while True: 46 | k = parent_chaincode 47 | d = '\x01' + parent_key + struct.pack('>L', i) + curveid + struct.pack('>L', ctr) + data 48 | h = hmac.new(k, d, hashlib.sha512).digest() 49 | key, chaincode = h[:32], h[32:] 50 | if string_to_int(key) >= n: 51 | ctr += 1 52 | else: 53 | return (key, chaincode) 54 | 55 | 56 | master_key = binascii.unhexlify('e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35') 57 | master_chaincode = binascii.unhexlify('873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508') 58 | 59 | 60 | k, c = derive(master_key, master_chaincode, 0x80000000 + 44) 61 | assert binascii.hexlify(k) == '8a8e34c835bceec0213d542623158811d5686d931d51efbf8e3ea8f62edc703f' 62 | assert binascii.hexlify(c) == '4681a20841656292a6f6fda184811ace2c5fa67de53c47eb9d0cc557bae2dea4' 63 | print 'ok' 64 | 65 | 66 | k, c = derive_universal(master_key, master_chaincode, 1337, n=(2**255 - 19), curveid='ed25519', data='https://www.example.com') 67 | assert binascii.hexlify(k) == '51e7ccf5c5fd11301926ccdf195f6c02b2696a2b9e5a95a930f7e527654b5d03' 68 | assert binascii.hexlify(c) == 'b45f2b67f218223833f5607d1a26b030e6a1ebc7fdd7b3bc9481e1d78ee2c728' 69 | print 'ok' 70 | -------------------------------------------------------------------------------- /slip-0017.md: -------------------------------------------------------------------------------- 1 | # SLIP-0017 : ECDH using deterministic hierarchy 2 | 3 | ``` 4 | Number: SLIP-0017 5 | Title: ECDH using deterministic hierarchy 6 | Type: Standard 7 | Status: Final 8 | Authors: Roman Zeyde 9 | Created: 2016-05-29 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This document describes a method for implementing Elliptic Curve 15 | Diffie-Hellman algorithm, using a determinstic hierarchy. 16 | 17 | ## Motivation 18 | 19 | Using Deterministic Hierarchy for encryption and decryption is ideal, 20 | because the same concepts of easy backup that relate to backing up 21 | deterministic wallets can be applied to backing up private keys. 22 | 23 | ## Service Identity 24 | 25 | Let's introduce the service identity. It consists of two elements: 26 | 27 | a) RFC 3986 URI `proto://[user@]host[:port][/path]` 28 | 29 | Examples: 30 | 31 | * `https://example.com` 32 | * `ftp://public@example.com/pub` 33 | * `ssh://root@example.com:2222` 34 | 35 | b) index (32-bit unsigned integer) 36 | 37 | The index is used so one can generate more keys corresponding to the same URI. 38 | 39 | ## HD Structure 40 | 41 | 1. First concatenate `index` with the URI (`uri`). Use little endian for `index`. 42 | 43 | 2. Compute the SHA256 hash of the result (`hash`). 44 | 45 | 3. Truncate `hash` to 128 bits (`hash128`) 46 | 47 | 4. Split `hash128` into four 32-bit integers `A`, `B`, `C`, `D`. Use little endian for each. 48 | 49 | 5. Set highest bits of numbers `A`, `B`, `C`, `D` to 1 (e.g. logical OR with 0x80000000) to harden 50 | 51 | 6. Derive the HD node `m/17'/A'/B'/C'/D'` according to BIP32. 52 | 53 | ## Shared secret generation 54 | 55 | Suppose that Alice and Bob need to agree on a shared secret. 56 | 57 | First, they agree on a specific elliptic curve and generate 58 | two public keys: `P1 = k1*G` for Alice and `P2 = k2*G` for Bob. 59 | 60 | In order to derive a shared secret, Alice retrieves Bob's public key (P2). 61 | Then, she calls `Q = GetECDHSessionKey(P2)` API on her TREZOR, to compute 62 | `Q = k1*P2`, by multiplying Bob's public key `P2` (as an elliptic curve point) 63 | by her private key `k1` (as a 256-bit scalar). 64 | 65 | The result is the elliptic curve point `Q = k1*k2*P`, which can be computed in a 66 | similar way by Bob (since `Q = k2*P1`), is used to derive a shared secret. 67 | 68 | ## References 69 | 70 | * [BIP-0032: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 71 | * [BIP-0043: Purpose Field for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) 72 | * [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax](https://tools.ietf.org/html/rfc3986) 73 | -------------------------------------------------------------------------------- /slip-0077.md: -------------------------------------------------------------------------------- 1 | # SLIP-0077 : Deterministic blinding key derivation for Confidential Transactions 2 | 3 | ``` 4 | Number: SLIP-0077 5 | Title: Deterministic blinding key derivation for Confidential Transactions 6 | Type: Standard 7 | Status: Draft 8 | Authors: Roman Zeyde 9 | Created: 2019-06-15 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This document describes a method for blinding key derivation 15 | for Confidential Transactions, using a deterministic hierarchy. 16 | 17 | ## General design 18 | 19 | In confidential transactions, the sender and the receiver use ECDH to derive a shared nonce, which is then used for hiding/recovering of the actual value and asset type being transacted. 20 | In Elements/Liquid, the receiver uses the following derivation scheme for his ECDH public/private keys: 21 | 22 | ``` 23 | blinding_private_key := HMAC_SHA256(key=master_blinding_key, msg=script_pubkey) 24 | blinding_public_key := secp256k1_publickey(private_key=blinding_private_key) 25 | ``` 26 | 27 | Note: `blinding_private_key` (as 256-bit scalar) must be less than the secp256k1 curve group order - otherwise, the derivation above must fail. 28 | 29 | The receiver is using `blinding_public_key` to construct a "confidential address", which is used by the sender to blind the relevant transaction outputs. Each such blinded transaction output also contains the sender's ECDH public key, so the receiver would be able to recover the shared nonce using its `blinding_private_key`. 30 | 31 | An additional use-case is sharing some/all of the receiver's blinding private keys with an external auditor, allowing unblinding the audited outputs without being able to spend them. 32 | 33 | ## Design details 34 | 35 | ### Master blinding key derivation 36 | 37 | In order to use similar blinding key derivation scheme on TREZOR, we suggest using [SLIP-0021](https://github.com/satoshilabs/slips/blob/master/slip-0021.md) derivation scheme for `master_blinding_key`: 38 | 39 | ``` 40 | domain := b"Symmetric key seed" 41 | root := HMAC_SHA512(key=domain, msg=seed) 42 | 43 | label := b"SLIP-0077" 44 | node := HMAC_SHA512(key=root[0:32], msg=(b"\x00" + label)) 45 | 46 | master_blinding_key := node[32:64] 47 | ``` 48 | 49 | The above seed should be derived using [BIP-0039](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#from-mnemonic-to-seed) mnemonic and passphrase (if available). 50 | 51 | ### Shared nonce derivation 52 | 53 | The shared nonce is derived using ECDH and double-SHA256 of the compressed shared public key: 54 | 55 | ``` 56 | shared := secp256k1_multiply(blinding_private_key, sender_public_key, compressed=True) 57 | nonce := SHA256(SHA256(shared)) 58 | ``` 59 | 60 | ## References 61 | 62 | * [An investigation into Confidential Transactions](https://github.com/AdamISZ/ConfidentialTransactionsDoc/blob/master/essayonCT.pdf) 63 | * [Confidential Transactions tutorial](https://elementsproject.org/elements-code-tutorial/confidential-transactions#blindingkey) 64 | * [Liquid Developer Guide](https://docs.blockstream.com/liquid/developer-guide/developer-guide-index.html#confidential-transactions) 65 | * [Elements' blinding key derivation](https://github.com/ElementsProject/elements/blob/a6beb256ed5195c2a1014a34fdf354d5797247a8/src/wallet/wallet.cpp#L5594) 66 | * [Elements' output unblinding using ECDH](https://github.com/ElementsProject/elements/blob/66c015529e7846f8491bcafd986326bcafc1bfcb/src/blind.cpp#L53) 67 | -------------------------------------------------------------------------------- /slip-0013.md: -------------------------------------------------------------------------------- 1 | # SLIP-0013 : Authentication using deterministic hierarchy 2 | 3 | ``` 4 | Number: SLIP-0013 5 | Title: Authentication using deterministic hierarchy 6 | Type: Standard 7 | Status: Final 8 | Authors: Pavol Rusnak 9 | Created: 2015-03-12 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This document describes a method that is used for authenticating 15 | to various services such as websites or remote shells using a determinstic 16 | hierarchy. 17 | 18 | ## Motivation 19 | 20 | Using Deterministic Hierarchy for authenticating into systems is ideal, 21 | because the same concepts of easy backup that relate to backing up 22 | deterministic wallets can be applied to backing up user identities. 23 | 24 | ## Service Identity 25 | 26 | Let's introduce the service identity. It consists of two elements: 27 | 28 | a) RFC 3986 URI `proto://[user@]host[:port][/path]` 29 | 30 | Examples: 31 | 32 | * `https://example.com` 33 | * `ftp://public@example.com/pub` 34 | * `ssh://root@example.com:2222` 35 | 36 | b) index (32-bit unsigned integer) 37 | 38 | The index is used so one can generate more keys corresponding to the same URI. 39 | 40 | ## HD Structure 41 | 42 | 1. First concatenate `index` with the URI (`uri`). Use little endian for `index`. 43 | 44 | 2. Compute the SHA256 hash of the result (`hash`). 45 | 46 | 3. Truncate `hash` to 128 bits (`hash128`) 47 | 48 | 4. Split `hash128` into four 32-bit integers `A`, `B`, `C`, `D`. Use little endian for each. 49 | 50 | 5. Set highest bits of numbers `A`, `B`, `C`, `D` to 1 (e.g. logical OR with 0x80000000) to harden 51 | 52 | 6. Derive the HD node `m/13'/A'/B'/C'/D'` according to BIP32. 53 | 54 | ### Worked example 55 | 56 | 1. `index + uri`=`0` + `https://satoshi@bitcoin.org/login` 57 | 58 | 2. `sha256(index + uri)` = `d0e2389d4c8394a9f3e32de01104bf6e8db2d9e2bb0905d60fffa5a18fd696db` 59 | 60 | 3. `hash128` = `d0e2389d4c8394a9f3e32de01104bf6e` 61 | 62 | 4. `A` = 2637750992, `B` = 2845082444, `C` = 3761103859, `D` = 1858012177 63 | 64 | 5. `A'` = 2637750992, `B'` = 2845082444, `C'` = 3761103859, `D'` = 4005495825 65 | 66 | 6. `bip32 node path` = `m/2147483661/2637750992/2845082444/3761103859/4005495825` 67 | 68 | See a [Python example](https://github.com/trezor/python-trezor/blob/ca45019918bc4c54f1ace899a9acf397c8f4d92f/tests/test_msg_signidentity.py#L27). 69 | 70 | ## Challenge - Response 71 | 72 | Service issues the challenge consisting of three parts: 73 | 74 | a) service identity described above (e.g. `https://example.com 0`) 75 | 76 | b) hidden challenge 77 | 78 | * random bytes sequence of maximum length 64 79 | * this won't be shown to the user 80 | 81 | c) visual challenge 82 | 83 | * arbitrary string of text of maximum length 64 84 | * this will be shown to the user and we recommend using timestamp in `YYYY-MM-DD HH:MM:SS` format or similar 85 | 86 | Signer takes this data and computes the private key according to section HD Structure. 87 | Then it concatenates sha256 hashes of challenge hidden and challenge visual and 88 | signs the result using the standard Bitcoin message signing. 89 | Finally, the signature is returned together with the node public key and node address. 90 | 91 | It's up to service operator to take this message and react in three possible ways: 92 | 93 | 1. signature is invalid or not present -> show error to user 94 | 2. signature is valid, address/public key seen for the first time -> create user account 95 | 3. signature is valid, address/public key known -> login to user account 96 | 97 | ## References 98 | 99 | * [BIP-0032: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 100 | * [BIP-0043: Purpose Field for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) 101 | * [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax](https://tools.ietf.org/html/rfc3986) 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SatoshiLabs Improvement Proposals 2 | 3 | [![Build Status](https://travis-ci.org/satoshilabs/slips.svg?branch=master)](https://travis-ci.org/satoshilabs/slips) 4 | 5 | SatoshiLabs projects need a way how to document their technical decisions and features. 6 | For some of them Bitcoin Improvement Proposal (BIP) is not a right place because 7 | their range and implications are outside of the scope of Bitcoin and cryptocurrencies. 8 | 9 | SLIP repository is an extension to Bitcoin Improvement Proposal (BIP) process 10 | and contains the documents that are unsuitable for submission to BIP repository. 11 | 12 | Each SLIP should provide a concise technical specification of the feature and a rationale for the feature. 13 | 14 | | Number | Title | Type | Status | 15 | |---------------------------|-----------------------------------------------------------------------|---------------|----------| 16 | | [SLIP-0000](slip-0000.md) | SLIP Template | Informational | Accepted | 17 | | [SLIP-0010](slip-0010.md) | Universal private key derivation from master private key | Standard | Final | 18 | | [SLIP-0011](slip-0011.md) | Symmetric encryption of key-value pairs using deterministic hierarchy | Standard | Final | 19 | | [SLIP-0012](slip-0012.md) | Public key encryption using deterministic hierarchy | Standard | Draft | 20 | | [SLIP-0013](slip-0013.md) | Authentication using deterministic hierarchy | Standard | Final | 21 | | [SLIP-0014](slip-0014.md) | Stress Test Deterministic Wallet | Informational | Active | 22 | | [SLIP-0015](slip-0015.md) | Format for Bitcoin metadata and its encryption in HD wallets | Standard | Final | 23 | | [SLIP-0016](slip-0016.md) | Format for password storage and its encryption | Standard | Final | 24 | | [SLIP-0017](slip-0017.md) | Elliptic Curve Diffie-Hellman using deterministic hierarchy | Standard | Final | 25 | | [SLIP-0018](slip-0018.md) | reserved (CoSi) | Standard | Draft | 26 | | [SLIP-0019](slip-0019.md) | Proof of Ownership | Standard | Accepted | 27 | | [SLIP-0020](slip-0020.md) | Proof of User Confirmation | Standard | Draft | 28 | | [SLIP-0021](slip-0021.md) | Hierarchical derivation of symmetric keys | Standard | Final | 29 | | [SLIP-0022](slip-0022.md) | FIDO2 Credential ID format for HD wallets | Standard | Final | 30 | | [SLIP-0023](slip-0023.md) | Cardano HD master node derivation from a master seed | Standard | Final | 31 | | [SLIP-0032](slip-0032.md) | Extended serialization format for BIP-32 wallets | Standard | Draft | 32 | | [SLIP-0039](slip-0039.md) | Shamir's Secret-Sharing for Mnemonic Codes | Standard | Final | 33 | | [SLIP-0044](slip-0044.md) | Registered coin types for BIP-0044 | Standard | Active | 34 | | [SLIP-0048](slip-0048.md) | Deterministic key hierarchy for Graphene-based networks | Standard | Active | 35 | | [SLIP-0077](slip-0077.md) | Deterministic blinding key derivation for Confidential Transactions | Standard | Draft | 36 | | [SLIP-0132](slip-0132.md) | Registered HD version bytes for BIP-0032 | Standard | Active | 37 | | [SLIP-0173](slip-0173.md) | Registered human-readable parts for BIP-0173 | Standard | Active | 38 | 39 | --- 40 | 41 | This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/). 42 | -------------------------------------------------------------------------------- /slip-0048/testvectors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import binascii 4 | import hashlib 5 | import hmac 6 | import struct 7 | import ecdsa 8 | from mnemonic import mnemonic 9 | 10 | privdev = 0x80000000 11 | 12 | 13 | def int_to_string(x, pad): 14 | result = ['\x00'] * pad 15 | while x > 0: 16 | pad -= 1 17 | ordinal = x & 0xFF 18 | result[pad] = (chr(ordinal)) 19 | x >>= 8 20 | return ''.join(result) 21 | 22 | 23 | def string_to_int(s): 24 | result = 0 25 | for c in s: 26 | if not isinstance(c, int): 27 | c = ord(c) 28 | result = (result << 8) + c 29 | return result 30 | 31 | 32 | def seed2hdnode(seed, modifier, curve): 33 | while True: 34 | h = hmac.new(modifier, seed, hashlib.sha512).digest() 35 | key, chaincode = h[:32], h[32:] 36 | a = string_to_int(key) 37 | if (a < curve.order and a != 0): 38 | break 39 | seed = h 40 | return (key, chaincode) 41 | 42 | 43 | def fingerprint(publickey): 44 | h = hashlib.new('ripemd160', hashlib.sha256(publickey).digest()).digest() 45 | return h[:4] 46 | 47 | 48 | def publickey(private_key, curve): 49 | Q = string_to_int(private_key) * curve.generator 50 | xstr = int_to_string(Q.x(), 32) 51 | parity = Q.y() & 1 52 | return chr(2 + parity) + xstr 53 | 54 | 55 | def derive(parent_key, parent_chaincode, i, curve): 56 | assert len(parent_key) == 32 57 | assert len(parent_chaincode) == 32 58 | k = parent_chaincode 59 | if ((i & privdev) != 0): 60 | key = '\x00' + parent_key 61 | else: 62 | key = publickey(parent_key, curve) 63 | d = key + struct.pack('>L', i) 64 | while True: 65 | h = hmac.new(k, d, hashlib.sha512).digest() 66 | key, chaincode = h[:32], h[32:] 67 | a = string_to_int(key) 68 | key = (a + string_to_int(parent_key)) % curve.order 69 | if (a < curve.order and key != 0): 70 | key = int_to_string(key, 32) 71 | break 72 | d = '\x01' + h[32:] + struct.pack('>L', i) 73 | return (key, chaincode) 74 | 75 | 76 | def get_curve_info(curvename): 77 | return (ecdsa.curves.SECP256k1, 'Bitcoin seed') 78 | 79 | 80 | def show_testvector(name, curvename, seedhex, derivationpath): 81 | curve, seedmodifier = get_curve_info(curvename) 82 | master_seed = binascii.unhexlify(seedhex) 83 | k, c = seed2hdnode(master_seed, seedmodifier, curve) 84 | p = publickey(k, curve) 85 | fpr = '\x00\x00\x00\x00' 86 | path = 'm' 87 | print("### " + name + " for " + curvename) 88 | print("Seed (hex): " + seedhex) 89 | print('* Chain ' + path) 90 | print(' * fpr: ' + binascii.hexlify(fpr)) 91 | print(' * chain: ' + binascii.hexlify(c)) 92 | print(' * prv: ' + binascii.hexlify(k)) 93 | print(' * pub: ' + binascii.hexlify(p)) 94 | depth = 0 95 | for i in derivationpath: 96 | fpr = fingerprint(p) 97 | depth = depth + 1 98 | path = path + "/" + str(i & (privdev - 1)) 99 | if ((i & privdev) != 0): 100 | path = path + "H" 101 | k, c = derive(k, c, i, curve) 102 | p = publickey(k, curve) 103 | print('* Chain ' + path) 104 | print(' * fpr: ' + binascii.hexlify(fpr)) 105 | print(' * chain: ' + binascii.hexlify(c)) 106 | print(' * prv: ' + binascii.hexlify(k)) 107 | print(' * pub: ' + binascii.hexlify(p)) 108 | print 109 | 110 | 111 | m = mnemonic.Mnemonic("english") 112 | show_testvector("Test vector 1", 113 | 'secp256k1', 114 | binascii.hexlify(m.to_seed("hello")), 115 | [ 116 | privdev + 48, 117 | privdev + 0, 118 | privdev + 0, 119 | privdev + 1, 120 | privdev + 0, 121 | ]) 122 | 123 | show_testvector("Test vector 2", 124 | 'secp256k1', 125 | binascii.hexlify(m.to_seed("hello")), 126 | [ 127 | privdev + 48, 128 | privdev + 1, 129 | privdev + 3, 130 | privdev + 0, 131 | privdev + 3, 132 | ]) 133 | -------------------------------------------------------------------------------- /slip-0011.md: -------------------------------------------------------------------------------- 1 | # SLIP-0011 : Symmetric encryption of key-value pairs using deterministic hierarchy 2 | 3 | ``` 4 | Number: SLIP-0011 5 | Title: Symmetric encryption of key-value pairs using deterministic hierarchy 6 | Type: Standard 7 | Status: Final 8 | Authors: Pavol Rusnak 9 | Marek Palatinus 10 | Karel Bilek 11 | Created: 2014-06-12 12 | ``` 13 | 14 | ## Abstract 15 | 16 | This document is explaining symmetric encryption on hardware devices, using deterministic hierarchy. 17 | 18 | ## Motivation 19 | 20 | We want to provide a symmetric encryption in the hardware wallet, where the key doesn't exit the device, and where the user might be forced to confirm the encryption/decryption on the display. 21 | 22 | ## Body 23 | 24 | ### Overview 25 | 26 | The following data are sent to the hardware wallet: 27 | 28 | * BIP 32 path 29 | * key (that is being shown on the device) 30 | * value 31 | * encrypt/decrypt direction 32 | * should user confirm on encrypt? 33 | * should user confirm on decrypt? 34 | * optional IV 35 | 36 | Value is what is actually being encrypted. The key for the encryption is constructed from the private key on the BIP address, the key displayed on the device, and the two informations about whether to ask for confirmation. 37 | 38 | It is constructed in such a way, that different path, key or the confirm information will get a different encryption key and IV. So, you cannot "skip" the confirmation by using different input. 39 | 40 | IV can be either manually set, or it is computed together with the key. 41 | 42 | The value must be divisible into 16-byte blocks. The application has to pad the blocks itself and ensure safety; for example, by using PKCS7. 43 | 44 | ### Details 45 | 46 | The details are best explained on a slightly simplified code from TREZOR Python emulator. 47 | 48 | ```python 49 | def _cipher_keyvalue(self, address_n, key, value, encrypt, ask_on_encrypt, ask_on_decrypt, iv): 50 | if len(value) % 16 > 0: 51 | return Failure(message="Input length must be a multiple of 16") 52 | private_key = BIP32(self.storage.get_node()).get_private_node(list(address_n)).private_key 53 | key += "E1" if ask_on_encrypt else "E0" 54 | key += "D1" if ask_on_decrypt else "D0" 55 | secret = hmac.HMAC(key=private_key, msg=key, digestmod=hashlib.sha512).digest() 56 | aes_key = secret[0:32] 57 | aes_iv = iv if iv else secret[32:48] 58 | aes = pyaes.AESModeOfOperationCBC(key=aes_key, iv=aes_iv) 59 | if encrypt: 60 | res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)]) 61 | else: 62 | res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)]) 63 | return CipheredKeyValue(value=res) 64 | ``` 65 | 66 | ```python 67 | if len(value) % 16 > 0: 68 | return Failure(message="Input length must be a multiple of 16") 69 | ``` 70 | 71 | First, the value is checked, if it is divisable into 16-byte blocks, since the symmetric cipher is block cipher. The application has to pad the blocks itself and ensure safety; for example, by using PKCS7. 72 | 73 | ```python 74 | private_key = BIP32(self.storage.get_node()).get_private_node(list(address_n)).private_key 75 | ``` 76 | 77 | Private key of the BIP32 node is derived. 78 | 79 | ```python 80 | key += "E1" if ask_on_encrypt else "E0" 81 | key += "D1" if ask_on_decrypt else "D0" 82 | ``` 83 | 84 | The key, displayed on the device, is concatenated with either E1 or E0 and either D1 or D0, depending on whether the confirmation is enabled in a given direction. 85 | 86 | ```python 87 | secret = hmac.HMAC(key=private_key, msg=key, digestmod=hashlib.sha512).digest() 88 | ``` 89 | 90 | The key, with the concatenated E1/E0 or D1/D0, is HMACed, with the private key from HD Node, with SHA512 as a hash function. 91 | 92 | ```python 93 | aes_key = secret[0:32] 94 | aes_iv = iv if iv else secret[32:48] 95 | ``` 96 | 97 | The AES key is the first 32 bytes of the HMAC; the input vector is the next 16 bytes. 98 | 99 | ```python 100 | aes = pyaes.AESModeOfOperationCBC(key=aes_key, iv=aes_iv) 101 | ``` 102 | 103 | The algorithm is AES, in CBC mode. 104 | 105 | ```python 106 | if encrypt: 107 | res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)]) 108 | else: 109 | res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)]) 110 | ``` 111 | 112 | The result are the encrypted/decrypted blocks, concatenated together. 113 | 114 | ## Test Vectors 115 | 116 | Check [test_msg_cipherkeyvalue.py](https://github.com/trezor/python-trezor/blob/master/trezorlib/tests/device_tests/test_msg_cipherkeyvalue.py) for the test vectors. 117 | 118 | ## References 119 | 120 | The algorithm is implemented in [TREZOR firmware](https://github.com/trezor/trezor-mcu/blob/master/firmware/fsm.c) (function `fsm_msgCipherKeyValue`) and its [emulator](https://github.com/trezor/trezor-emu/blob/master/trezor/machine.py#L781) (function `_cipher_keyvalue`). 121 | 122 | It is used in algorithms described in [SLIP-0015](slip-0015.md) and [SLIP-0016](slip-0016.md). 123 | -------------------------------------------------------------------------------- /slip-0173.md: -------------------------------------------------------------------------------- 1 | # SLIP-0173 : Registered human-readable parts for BIP-0173 2 | 3 | ``` 4 | Number: SLIP-0173 5 | Title: Registered human-readable parts for BIP-0173 6 | Type: Standard 7 | Status: Active 8 | Authors: Clark Moody 9 | Created: 2017-05-17 10 | ``` 11 | 12 | ## Abstract 13 | 14 | BIP-0173 defines a new format for segregated witness output addresses that contains a human-readable part that identifies the coin type. 15 | 16 | ## Motivation 17 | 18 | The BIP repository does not want to deal with assigning the values for various coin types different than Bitcoin so we propose this SLIP to become such body. 19 | 20 | ## Registered human-readable parts 21 | 22 | These are the registered human-readable parts for usage in Bech32 encoding of witness programs. 23 | 24 | | Coin | Mainnet | Testnet | Regtest | 25 | | ---------------------------------------------- | ---------- | ------- | ----------- | 26 | | [Alaya](https://alaya.network/) | `atp` | `atx` | | 27 | | [BARE](https://bare.network) | `bare` | `tbare` | `bart` | 28 | | [Bellcoin](https://bellcoin.web4u.jp/) | `bm` | `bt` | `br` | 29 | | [Bitcoin](https://bitcoin.org/) | `bc` | `tb` | `bcrt` | 30 | | [Bitcoin Atom](https://bitcoinatom.io/) | `bca` | `tbca` | `bcart` | 31 | | [Bitcoin Gold](https://bitcoingold.org/) | `btg` | `tbtg` | | 32 | | [Bitcoin Platinum](https://btcplt.org/) | `btp` | `tbtp` | | 33 | | [Bitcoin Post-Quantum](https://bitcoinpq.org/) | `pq` | `tq` | `pqrt` | 34 | | [Bitcoin Private](https://btcprivate.org/) | `btcp` | `tbtcp` | `regbtcp` | 35 | | [Bitcore](https://bitcore.cc/) | `btx` | `tbtx` | | 36 | | [BitZeny](https://bitzeny.tech/) | `bz` | `tz` | `rz` | 37 | | [Blacknet](https://blacknet.ninja/) | `blacknet` | | `rblacknet` | 38 | | [CPUchain](https://cpuchain.org) | `cpu` | `tcpu` | `rcpu` | 39 | | [CranePay](https://cranepay.io/) | `cp` | `cpt` | `cpr` | 40 | | [Crypto.com Chain](https://crypto.com/chain) | `cro` | `tcro` | `dcro` | 41 | | [DigiByte](https://www.digibyte.io/) | `dgb` | `dgbt` | `dgbrt` | 42 | | [FujiCoin](http://www.fujicoin.org/) | `fc` | `tf` | `fcrt` | 43 | | [Groestlcoin](https://groestlcoin.org/) | `grs` | `tgrs` | `grsrt` | 44 | | [Handshake](https://handshake.org/) | `hs` | `ts` | `rs` | 45 | | [IoTeX](https://www.iotex.io/) | `io` | `it` | | 46 | | [IOV](https://www.iov.one/) | `iov` | `tiov` | | 47 | | [LatticeX](https://latticex.foundation/) | `pla` | `plt` | | 48 | | [Litecoin](https://litecoin.org/) | `ltc` | `tltc` | `rltc` | 49 | | [Monacoin](https://monacoin.org/) | `mona` | `tmona` | `rmona` | 50 | | [Myriad](https://myriadcoin.org/) | `my` | `tm` | | 51 | | [Namecoin](https://www.namecoin.org/) | `nc` | `tn` | `ncrt` | 52 | | [Oasis Network](https://oasisprotocol.org/) | `oasis` | `oasis` | | 53 | | [Omni](https://www.omnilayer.org) | `o` | `to` | `ocrt` | 54 | | [Peercoin](https://www.peercoin.net) | `xpc` | `tpc` | | 55 | | [PKT](https://github.com/pkt-cash/pktd) | `pkt` | `tpk` | | 56 | | [PlatON](https://platon.network/) | `lat` | `lax` | | 57 | | [Quantum Resistant Ledger](https://theqrl.org) | `qrl` | `tqrl` | `qrlrt` | 58 | | [Ravencoin](https://ravencoin.org/) | `rc` | `tr` | `rcrt` | 59 | | [Riecoin](https://riecoin.dev/) | `ric` | `tric` | `rric` | 60 | | [Sugarchain](https://sugarchain.org/) | `sugar` | `tugar` | `rugar` | 61 | | [Susucoin](https://www.susukino.com/) | `susu` | `tutu` | `ruru` | 62 | | [Syscoin](https://syscoin.org/) | `sys` | `tsys` | `scrt` | 63 | | [Unit-e](https://dtr.org/unit-e/) | `ue` | `tue` | `uert` | 64 | | [Vertcoin](https://vertcoin.org/) | `vtc` | `tvtc` | | 65 | | [Viacoin](https://viacoin.org/) | `via` | `tvia` | | 66 | | [VIPSTARCOIN](https://www.vipstarcoin.jp/) | `vips` | `tvips` | | 67 | | [YeeCo](https://www.yeeco.io/) | `yee` | `tyee` | | 68 | | [Zen Protocol](https://zenprotocol.com/) | `zen` | `tzn` | | 69 | | [Zilliqa](https://zilliqa.com/) | `zil` | `tzil` | | 70 | 71 | ## Libraries 72 | 73 | * [Reference Implementations](https://github.com/sipa/bech32/tree/master/ref) 74 | 75 | ## References 76 | 77 | * [BIP-0173: Base32 address format for native v0-16 witness outputs](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) 78 | -------------------------------------------------------------------------------- /slip-0010/testvectors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import binascii 4 | import hashlib 5 | import hmac 6 | import struct 7 | import ecdsa 8 | import ed25519 9 | from base58 import b58encode_check 10 | 11 | privdev = 0x80000000 12 | 13 | def int_to_string(x, pad): 14 | result = ['\x00'] * pad 15 | while x > 0: 16 | pad -= 1 17 | ordinal = x & 0xFF 18 | result[pad] = (chr(ordinal)) 19 | x >>= 8 20 | return ''.join(result) 21 | 22 | def string_to_int(s): 23 | result = 0 24 | for c in s: 25 | if not isinstance(c, int): 26 | c = ord(c) 27 | result = (result << 8) + c 28 | return result 29 | 30 | # mode 0 - compatible with BIP32 private derivation 31 | def seed2hdnode(seed, modifier, curve): 32 | k = seed 33 | while True: 34 | h = hmac.new(modifier, seed, hashlib.sha512).digest() 35 | key, chaincode = h[:32], h[32:] 36 | a = string_to_int(key) 37 | if (curve == 'ed25519'): 38 | break 39 | if (a < curve.order and a != 0): 40 | break 41 | seed = h 42 | #print 'RETRY seed: ' + binascii.hexlify(seed) 43 | return (key, chaincode) 44 | 45 | def fingerprint(publickey): 46 | h = hashlib.new('ripemd160', hashlib.sha256(publickey).digest()).digest() 47 | return h[:4] 48 | 49 | def b58xprv(parent_fingerprint, private_key, chain, depth, childnr): 50 | raw = ('\x04\x88\xad\xe4' + 51 | chr(depth) + parent_fingerprint + int_to_string(childnr, 4) + 52 | chain + '\x00' + private_key) 53 | return b58encode_check(raw) 54 | 55 | def b58xpub(parent_fingerprint, public_key, chain, depth, childnr): 56 | raw = ('\x04\x88\xb2\x1e' + 57 | chr(depth) + parent_fingerprint + int_to_string(childnr, 4) + 58 | chain + public_key) 59 | return b58encode_check(raw) 60 | 61 | def publickey(private_key, curve): 62 | if curve == 'ed25519': 63 | sk = ed25519.SigningKey(private_key) 64 | return '\x00' + sk.get_verifying_key().to_bytes() 65 | else: 66 | Q = string_to_int(private_key) * curve.generator 67 | xstr = int_to_string(Q.x(), 32) 68 | parity = Q.y() & 1 69 | return chr(2 + parity) + xstr 70 | 71 | def derive(parent_key, parent_chaincode, i, curve): 72 | assert len(parent_key) == 32 73 | assert len(parent_chaincode) == 32 74 | k = parent_chaincode 75 | if ((i & privdev) != 0): 76 | key = '\x00' + parent_key 77 | else: 78 | key = publickey(parent_key, curve) 79 | d = key + struct.pack('>L', i) 80 | while True: 81 | h = hmac.new(k, d, hashlib.sha512).digest() 82 | key, chaincode = h[:32], h[32:] 83 | if curve == 'ed25519': 84 | break 85 | #print 'I: ' + binascii.hexlify(h) 86 | a = string_to_int(key) 87 | key = (a + string_to_int(parent_key)) % curve.order 88 | if (a < curve.order and key != 0): 89 | key = int_to_string(key, 32) 90 | break 91 | d = '\x01' + h[32:] + struct.pack('>L', i) 92 | #print 'a failed: ' + binascii.hexlify(h[:32]) 93 | #print 'RETRY: ' + binascii.hexlify(d) 94 | 95 | return (key, chaincode) 96 | 97 | def get_curve_info(curvename): 98 | if curvename == 'secp256k1': 99 | return (ecdsa.curves.SECP256k1, 'Bitcoin seed') 100 | if curvename == 'nist256p1': 101 | return (ecdsa.curves.NIST256p, 'Nist256p1 seed') 102 | if curvename == 'ed25519': 103 | return ('ed25519', 'ed25519 seed') 104 | raise BaseException('unsupported curve: '+curvename) 105 | 106 | def show_testvector(name, curvename, seedhex, derivationpath): 107 | curve, seedmodifier = get_curve_info(curvename) 108 | master_seed = binascii.unhexlify(seedhex) 109 | k,c = seed2hdnode(master_seed, seedmodifier, curve) 110 | p = publickey(k, curve) 111 | fpr = '\x00\x00\x00\x00' 112 | path = 'm' 113 | print "### "+name+" for "+curvename 114 | print '' 115 | print "Seed (hex): " + seedhex 116 | print '' 117 | print '* Chain ' + path 118 | print ' * fingerprint: ' + binascii.hexlify(fpr) 119 | print ' * chain code: ' + binascii.hexlify(c) 120 | print ' * private: ' + binascii.hexlify(k) 121 | print ' * public: ' + binascii.hexlify(p) 122 | depth = 0 123 | for i in derivationpath: 124 | if curve == 'ed25519': 125 | # no public derivation for ed25519 126 | i = i | privdev 127 | fpr = fingerprint(p) 128 | depth = depth + 1 129 | path = path + "/" + str(i & (privdev-1)) 130 | if ((i & privdev) != 0): 131 | path = path + "H" 132 | k,c = derive(k, c, i, curve) 133 | p = publickey(k, curve) 134 | print '* Chain ' + path 135 | print ' * fingerprint: ' + binascii.hexlify(fpr) 136 | print ' * chain code: ' + binascii.hexlify(c) 137 | print ' * private: ' + binascii.hexlify(k) 138 | print ' * public: ' + binascii.hexlify(p) 139 | #print b58xprv(fpr, kc, cc, depth, i) 140 | #print b58xpub(fpr, pc, cc, depth, i) 141 | print 142 | 143 | def show_testvectors(name, curvenames, seedhex, derivationpath): 144 | for curvename in curvenames: 145 | show_testvector(name, curvename, seedhex, derivationpath) 146 | 147 | 148 | curvenames = ['secp256k1', 'nist256p1', 'ed25519']; 149 | 150 | show_testvectors("Test vector 1", curvenames, 151 | '000102030405060708090a0b0c0d0e0f', 152 | [privdev + 0, 1, privdev + 2, 2, 1000000000]) 153 | show_testvectors("Test vector 2", curvenames, 154 | 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', 155 | [0, privdev + 2147483647, 1, privdev + 2147483646, 2]) 156 | 157 | show_testvectors("Test derivation retry", ['nist256p1'], 158 | '000102030405060708090a0b0c0d0e0f', 159 | [privdev + 28578, 33941]) 160 | 161 | show_testvectors("Test seed retry", ['nist256p1'], 162 | 'a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446', 163 | []) 164 | 165 | -------------------------------------------------------------------------------- /slip-0132.md: -------------------------------------------------------------------------------- 1 | # SLIP-0132 : Registered HD version bytes for BIP-0032 2 | 3 | ``` 4 | Number: SLIP-0132 5 | Title: Registered HD version bytes for BIP-0032 6 | Type: Standard 7 | Status: Active 8 | Authors: Clark Moody 9 | Created: 2018-02-08 10 | ``` 11 | 12 | ## Abstract 13 | 14 | BIP-0032 defines the derivation scheme for hierarchical deterministic wallets, which encode their public and private keys in an extended serialization format known as `xpub`. The `xpub` prefix is an artifact of Base58 encoding the four version bytes of the serialization format. 15 | 16 | ## Motivation 17 | 18 | The BIP repository defines public and private key version bytes for Bitcoin's mainnet and testnet. However, other cryptocurrencies use different version bytes for encoding HD seeds, and the BIP repository is focused on Bitcoin. Thus, we propose this SLIP act as a registry for all coin HD version bytes. 19 | 20 | Since BIP-0032 does not specify the address format for a given derivation path, wallet developers [have proposed](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-September/014907.html) altering the version bytes to achieve this. With the activation of SegWit on Bitcoin, the number of ways of encoding an address public key has increased. While [BIP-0049](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki) proposes a method for encoding P2WPKH-nested-in-P2SH addresses, its original version failed to change the HD seed version bytes (retained `xpub` prefix), leading to unsustainable user confusion. Either the user must know that the `xpub` uses BIP-0049 derivation, or the consumer of the `xpub` must scan both address spaces (P2PKH and P2WPKH-in-P2SH). 21 | 22 | [BIP-0084](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) proposes a native-SegWit derivation scheme, encoding P2WPKH addresses in Bech32. However, the extended serialization format was originally presented with a `zpub` prefix but no version bytes. This is an issue since multiple values of the version bytes may encode to the same prefix. 23 | 24 | A final important motiviation for establishing a clearinghouse of HD version bytes is the fact that the extended serialization format does not encode the coin type. The [SLIP-0032](https://github.com/satoshilabs/slips/blob/master/slip-0032.md) proposal attempts a remedy by including the full BIP-0032 derivation path within the serialized key. Along with a human-readable prefix of `xpub` and Bech32 encoding, SLIP-0032 should greatly improve the wallet ecosystem. Until wallets begin implementation of SLIP-0032, however, this registry aims to alleviate the confusion. 25 | 26 | ## Registered HD version bytes 27 | 28 | These are the registered HD version bytes for extended serialization of public and private keys. 29 | 30 | Coin | Public Key | Private Key | Address Encoding | BIP 32 Path | 31 | ------------------------------------------|-----------------------|-----------------------|----------------------------------|-------------| 32 | [Bitcoin](https://bitcoin.org/) | `0x0488b21e` - `xpub` | `0x0488ade4` - `xprv` | P2PKH or P2SH | m/44'/0' | 33 | Bitcoin | `0x049d7cb2` - `ypub` | `0x049d7878` - `yprv` | P2WPKH in P2SH | m/49'/0' | 34 | Bitcoin | `0x04b24746` - `zpub` | `0x04b2430c` - `zprv` | P2WPKH | m/84'/0' | 35 | Bitcoin | `0x0295b43f` - `Ypub` | `0x0295b005` - `Yprv` | Multi-signature P2WSH in P2SH | - | 36 | Bitcoin | `0x02aa7ed3` - `Zpub` | `0x02aa7a99` - `Zprv` | Multi-signature P2WSH | - | 37 | Bitcoin Testnet | `0x043587cf` - `tpub` | `0x04358394` - `tprv` | P2PKH or P2SH | m/44'/1' | 38 | Bitcoin Testnet | `0x044a5262` - `upub` | `0x044a4e28` - `uprv` | P2WPKH in P2SH | m/49'/1' | 39 | Bitcoin Testnet | `0x045f1cf6` - `vpub` | `0x045f18bc` - `vprv` | P2WPKH | m/84'/1' | 40 | Bitcoin Testnet | `0x024289ef` - `Upub` | `0x024285b5` - `Uprv` | Multi-signature P2WSH in P2SH | - | 41 | Bitcoin Testnet | `0x02575483` - `Vpub` | `0x02575048` - `Vprv` | Multi-signature P2WSH | - | 42 | [Litecoin](https://litecoin.org/) | `0x019da462` - `Ltub` | `0x019d9cfe` - `Ltpv` | P2PKH or P2SH | m/44'/2' | 43 | Litecoin | `0x01b26ef6` - `Mtub` | `0x01b26792` - `Mtpv` | P2WPKH in P2SH | m/49'/1' | 44 | Litecoin Testnet | `0x0436f6e1` - `ttub` | `0x0436ef7d` - `ttpv` | P2PKH or P2SH | m/44'/1' | 45 | [Vertcoin](https://vertcoin.org/) | `0x0488b21e` - `vtcp` | `0x0488ade4` - `vtcv` | P2PKH or P2SH | m/44'/28' | 46 | [Polis](https://polispay.org/) | `0x03e25d7e` - `ppub` | `0x03e25945` - `pprv` | P2PKH | m/44'/1997' | 47 | [Syscoin](https://syscoin.org/) | `0x04b24746` - `zpub` | `0x04b2430c` - `zprv` | P2WPKH | m/84'/57' | 48 | Syscoin | `0x02aa7ed3` - `Zpub` | `0x02aa7a99` - `Zprv` | Multi-signature P2WSH | - | 49 | 50 | ## Bitcoin Test Vectors 51 | 52 | ``` 53 | Mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about 54 | 55 | m/44'/0'/0' 56 | xprv9xpXFhFpqdQK3TmytPBqXtGSwS3DLjojFhTGht8gwAAii8py5X6pxeBnQ6ehJiyJ6nDjWGJfZ95WxByFXVkDxHXrqu53WCRGypk2ttuqncb 57 | xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj 58 | m/44'/0'/0'/0/0 address: 59 | 1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA 60 | 61 | m/49'/0'/0' 62 | yprvAHwhK6RbpuS3dgCYHM5jc2ZvEKd7Bi61u9FVhYMpgMSuZS613T1xxQeKTffhrHY79hZ5PsskBjcc6C2V7DrnsMsNaGDaWev3GLRQRgV7hxF 63 | ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP 64 | m/49'/0'/0'/0/0 address: 65 | 37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf 66 | 67 | m/84'/0'/0' 68 | zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE 69 | zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs 70 | m/84'/0'/0'/0/0 address: 71 | bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu 72 | ``` 73 | 74 | [Test vectors generation code](https://gist.github.com/clarkmoody/0a788d2e012ffe339bb7d3873e47c081) 75 | 76 | ## References 77 | 78 | * [BIP-0032: Hierarchical Deterministic Wallets # Serialization](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#serialization-format) 79 | * [SLIP-0032: Extended serialization format for BIP-32 wallets](https://github.com/satoshilabs/slips/blob/master/slip-0032.md) 80 | -------------------------------------------------------------------------------- /slip-0021.md: -------------------------------------------------------------------------------- 1 | # SLIP-0021 : Hierarchical derivation of symmetric keys 2 | 3 | ``` 4 | Number: SLIP-0021 5 | Title: Hierarchical derivation of symmetric keys 6 | Type: Standard 7 | Status: Final 8 | Authors: Andrew R. Kozlik 9 | Ondrej Vejpustek 10 | Pavol Rusnak 11 | Created: 2019-06-25 12 | ``` 13 | 14 | ## Abstract 15 | 16 | This document describes a method of deriving a hierarchy of symmetric keys from a master secret, such as the recovery seed used in cryptocurrency wallets. 17 | 18 | ## Motivation 19 | 20 | The [BIP-0032](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) specifications define how to derive a hierarchy of private/public key pairs from a master seed for the elliptic curves secp256k1, NIST P-256 and ed25519. However, there does not exist any similar specification for the derivation of keys for symmetric-key algorithms, which are needed for example in password encryption or encryption of Bitcoin metadata. [SLIP-0011](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) deals with this problem by first using BIP-0032 to derive a secp256k1 private key and then deriving the symmetric key from this private key. However, BIP-0032 was not designed to be used in this way and it also implies that an implementation of SLIP-0011 requires secp256k1 arithmetic, which should not be needed for symmetric key derivation. The purpose of this specification is to lay down a common framework for the deterministic derivation of a hierarchy of symmetric keys from a master seed. 21 | 22 | ## Master node generation 23 | 24 | We adapt the master node generation from BIP-0032 and SLIP-0010. To achieve proper domain separation from the secp256k1, NIST P-256 and ed25519 key hierarchies, we use the string “Symmetric key seed” instead of the curve name. Let *S* be the master secret, such as that defined in [SLIP-0039](https://github.com/satoshilabs/slips/blob/master/slip-0039.md) or the binary seed defined in [BIP-0039](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki). Then the master node *m* is derived as follows: 25 | 26 | ``` 27 | m = HMAC-SHA512(key = b"Symmetric key seed", msg = S) 28 | ``` 29 | 30 | The master node is used to derive child nodes, each of which can in turn be used to derive lower-level child nodes of their own and so on. Each node is associated with a 256-bit symmetric key. The master node is thus the root of a key tree. 31 | 32 | ## Child node derivation 33 | 34 | The child nodes of a parent node *N* are identified by a variable-length byte string called a *label*. The labels of all nodes which are derived from the master node, i.e., the first-level labels, MUST identify the purpose of the subordinate nodes. The purpose determines the further structure beneath the node. This label must be sufficiently unique to avoid collisions between applications. Examples include the ASCII encoding of the strings "BIP-9999", "SLIP-9999" or "FIDO2 Trezor Credential ID". 35 | 36 | The derivation function is defined as: 37 | 38 | ``` 39 | ChildNode(N, label) = HMAC-SHA512(key = N[0:32], msg = b"\x00" + label), 40 | ``` 41 | 42 | where *N*[0:32] is the first 32 bytes of node data. The key for a given node is defined as the last 32 bytes of the node data: 43 | 44 | ``` 45 | Key(N) = N[32:64] 46 | ``` 47 | 48 | ## Example 49 | 50 | This example shows several keys derived from the master secret 51 | 52 | ``` 53 | S = c76c4ac4f4e4a00d6b274d5c39c700bb4a7ddc04fbc6f78e85ca75007b5b495f74a9043eeb77bdd53aa6fc3a0e31462270316fa04b8c19114c8798706cd02ac8 54 | ``` 55 | 56 | which is the binary seed obtained from the BIP-0039 mnemonic "all all all all all all all all all all all all" with an empty passphrase. 57 | 58 | ``` 59 | Key(m) = dbf12b44133eaab506a740f6565cc117228cbf1dd70635cfa8ddfdc9af734756 60 | Key(m/"SLIP-0021") = 1d065e3ac1bbe5c7fad32cf2305f7d709dc070d672044a19e610c77cdf33de0d 61 | Key(m/"SLIP-0021"/"Master encryption key") = ea163130e35bbafdf5ddee97a17b39cef2be4b4f390180d65b54cf05c6a82fde 62 | Key(m/"SLIP-0021"/"Authentication key") = 47194e938ab24cc82bfa25f6486ed54bebe79c40ae2a5a32ea6db294d81861a6 63 | ``` 64 | 65 | ## Design rationale 66 | 67 | This standard is designed in accordance with [NIST SP 800-108](https://doi.org/10.6028/NIST.SP.800-108) Recommendation for Key Derivation Using Pseudorandom Functions. 68 | 69 | ### Key length 70 | 71 | Each node is associated with a 256-bit symmetric key. This key length is considered sufficiently secure for a number of years to come, see [keylength.com](https://www.keylength.com/en/compare/). It is also compatible with all major symmetric-key algorithms in use today, such as AES-256, ChaCha20Poly1305 or HMAC. The key derivation functions specified in NIST SP 800-108 allow for the derivation of variable length keys. Nevertheless, since such a feature appears to be of little use, a fixed key length was chosen to keep the implementation of this SLIP as simple as possible. 72 | 73 | ### Key separation 74 | 75 | The fact that each node is associated with a key of its own and uses a separate key for the derivation of child nodes is based on the principle that a single key should be used for only one purpose, e.g., encryption, integrity authentication, key derivation. The reasoning behind this principle is well known: 76 | 77 | 1. The use of the same key for two different cryptographic processes may weaken the security provided by one or both of the processes. 78 | 2. Limiting the use of a key limits the damage that could be done if the key is compromised. 79 | 3. Some uses of keys interfere with each other. 80 | 81 | Most importantly, the scheme is designed so that the knowledge of Key(*N*) is independent of the ability to derive child nodes of *N*. Thus the compromise of Key(*N*) does not jeopardize any child keys of *N*. 82 | 83 | ### Labeling child nodes 84 | 85 | In the BIP-0032 specification child nodes are indexed by a 31-bit integer. This is well suited for hierarchical wallets, but there are instances where it would be more convenient to be able to specify the derived key using a randomly generated value with sufficient entropy to avoid collisions. For such purposes a 31-bit index is insufficient. A variable-length byte string allows maximum flexibility in labeling nodes, for example by using a printable string, an encoded integer index or a 256-bit random value. 86 | 87 | ### Child node derivation 88 | 89 | Since this derivation scheme is intended to be fully deterministic once the master secret is known, the context and separator as defined in NIST SP 800-108 are omitted from the HMAC-SHA512 input. The counter and the length of the derived key are also omitted from the input, because they are constant. 90 | 91 | The value of the message entering the HMAC-SHA512 function is a null byte followed by the label of the child node. The reason for this is that the first byte of the message value is reserved for future use. It can be used for domain separation in case support for other types of labels is desired. 92 | 93 | ## References 94 | 95 | * [BIP-0032: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 96 | * [SLIP-0010: Universal private key derivation from master private key](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) 97 | * [SLIP-0011: Symmetric encryption of key-value pairs using deterministic hierarchy](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) 98 | * [NIST Special Publication 800-108: Recommendation for Key Derivation Using Pseudorandom Functions](https://doi.org/10.6028/NIST.SP.800-108) 99 | -------------------------------------------------------------------------------- /slip-0016.md: -------------------------------------------------------------------------------- 1 | # SLIP-0016 : Format for password storage and its encryption 2 | 3 | ``` 4 | Number: SLIP-0016 5 | Title: Format for password storage and its encryption 6 | Type: Standard 7 | Status: Final 8 | Authors: Peter Jensen 9 | Created: 2016-18-02 10 | ``` 11 | 12 | ## Abstract 13 | 14 | SLIP-0016 describes simple encryption concept for hardware device for secure storage of passwords. 15 | 16 | ## General design 17 | 18 | At first, we derive a master key from HW device itself, which is divided in two parts. 19 | First part is hashed and used as a name of storage file. 20 | Second part is used for primary storage encryption. 21 | 22 | Storage file is encrypted JSON object, which contains configuration, tags and separate entries. Each entry has other two encrypted properties derivated from device to provide higher level of security with low risk of leaks. 23 | 24 | ## Design details 25 | 26 | ### Deriving master key 27 | 28 | We derive masterKey from hardware device by sending cipherKeyValue with following params: 29 | 30 | * path: `m/10016'/0` (hardened path, see BIP32) 31 | * ENC_KEY: `'Unlock encrypted storage?'` (max length message is 256 bytes) 32 | * ENC_VALUE: `'2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee'` (in hexadecimal (128 /2), max length is 1024 bytes) 33 | * encrypt: `true` 34 | * ask_on_encrypt: `true` 35 | * ask_on_decrypt: `true` 36 | * iv: unset 37 | 38 | JS EXAMPLE: 39 | 40 | ```javascript 41 | session.cipherKeyValue( 42 | [(10016 | 0x80000000) >>> 0, 0], 43 | 'Unlock encrypted storage?', 44 | '2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee', 45 | true, true, true) 46 | ``` 47 | 48 | CipherKeyValue is defined in [SLIP-0011](slip-0011.md). 49 | 50 | ### Deriving file name 51 | 52 | From the first half of master key, we derive the file name for every user/device in the following way: 53 | First, we use the HMAC function: 54 | 55 | `HMAC-SHA256(fileKey, FILENAME_MESS)` 56 | 57 | where: 58 | 59 | - fileKey is the first half of masterKey (`masterKey.substring(0, masterKey.length / 2)`) 60 | - FILENAME_MESS is a constant string `'5f91add3fa1c3c76e90c90a3bd0999e2bd7833d06a483fe884ee60397aca277a'` 61 | 62 | The output result is digested to HEX string. After, we append extension `'.pswd'` 63 | 64 | EXAMPLE RESULT: `a80387a2222f4360f71fd2165368c6ed91b26287d9bc1ce8be71e64e6b216a4f.pswd` 65 | 66 | ### Deriving encryption key and file level encryption 67 | 68 | As an encryption key is used the SECOND half (32 bytes) of master key for the first level of data file encryption. Encryption key is in HEX string. 69 | 70 | For encrypt/decrypt we are using `AES-256-GCM` algorithm. 71 | 72 | - Input Vector (IV) is 12 randomly generated bytes 73 | - GCM is used with full 128-bit autentication tag (authTag) 74 | 75 | [more info](https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv) 76 | 77 | The result output stored in file is: 78 | 79 | - first 12 bytes of the file is randomly generated IV 80 | - next 16 bytes is the GCM authTag 81 | - the rest is output ciphertext 82 | 83 | [more info](https://nodejs.org/api/crypto.html#crypto_crypto_createdecipheriv_algorithm_key_iv) 84 | 85 | ### Data format 86 | 87 | (Decrypted) data file is serialized JSON object with the following keys: 88 | 89 | * `version`: for future backwards compatibility and data storage manipulation 90 | * `config`: for remembering personal setup of application 91 | * `tags`: contain set of labels with their icons (from icomoon set). Default tag is **All** and it is only tag, unable to edit or delete. 92 | 93 | ```javascript 94 | {title:"My social networks", icon:"person", active:"active"} 95 | ``` 96 | 97 | * `entries`: is object of all password entries encrypted second time 98 | 99 | ```javascript 100 | { 101 | "title": "http://wwww.github.com", 102 | "username": "Satoshi Nakamoto", 103 | "nonce": "8688105887642a3cbb61889d8762432ef864df107e097d2b19e93c8d808c2e21", 104 | "note": "public note", 105 | "password": {}, 106 | "safe_note": {}, 107 | "tags": [1] 108 | } 109 | ``` 110 | 111 | ### Entry level encryption 112 | 113 | Every entry contains keys from upper example. 114 | 115 | - `title`: title is represented as string. If given string is matching URL, it will be shown on device as domain without protocol prefix. 116 | - `username`: string, will be passed to device, in encryption/decryption process 117 | - `nonce`: hidden generated string which is output of cipherKeyValue over Title + Username key and random values 118 | - `password`: is buffer array output of plain string and nonce (encryption process described later) 119 | - `safe_note`: is also buffer array output of plain string and nonce (also described later) 120 | - `note`: is plain UTF8 string 121 | - `tags`: is array of Tags key values 122 | 123 | Step by step entry encryption: 124 | 125 | 1. Generate random 32 bytes buffer and convert to HEX string inadequately called `nonce` 126 | 2. Set key as `'Unlock ' + title + ' for user ' + username + '?'` 127 | 3. Ask device for `cipherKeyValue`, where path is the same as in the deriving file name, key is described in second step and enc_value is our `nonce` from the first step. Do not forget to setup properly other three bool values! 128 | 129 | EXAMPLE: 130 | 131 | ```javascript 132 | session.cipherKeyValue( 133 | [(10016 | 0x80000000) >>> 0, 0], // same path 134 | 'Unlock github.com for user Satoshi Nakamoto?', 135 | '2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee', 136 | true, //encrypt? - has to be TRUE in encryption 137 | false, //askOnEncrypt? is the same in encryption and decryption 138 | true) // askOnDecrypt? we want this becuase otherwise somebody could rob us! 139 | ``` 140 | 141 | 4. Then we use our famous `nonce` from the first step in `AES-256-GCM` algorithm encryption for `password` string and `safe_note` string. Process of encryption is the same as in the deriving encryption key and file level encryption. So basically we get some Buffer array output with 12 bytes of IV and 16 bytes of GCM authTag and the rest is cipherText. 142 | 5. Output of each encryption is stored to appropriate keys, just instead of generated `nonce` we store result from third step ( `cipherKeyValue`) which we later use for decryption process 143 | 144 | ### Entry decryption 145 | 146 | 1. We ask device for the same `cipherKeyValue` as in encryption process, just instead of `nonce`, we use our encrypted result and boolean value `encrypt?` is **false**! 147 | 148 | EXAMPLE: 149 | 150 | ```javascript 151 | session.cipherKeyValue( 152 | [(10016 | 0x80000000) >>> 0, 0], // same path 153 | 'Unlock github.com for user Satoshi Nakamoto?', 154 | '8688105887642a3cbb61889d8762432ef864df107e097d2b19e93c8d808c2e21', 155 | false, //encrypt? - has to be FALSE in decryption 156 | false, //askOnEncrypt? is the same in encryption and decryption 157 | true) // askOnDecrypt? we want this becuase otherwise somebody could rob us! 158 | ``` 159 | 160 | 2. Other steps are the same as in entry encryption, we just symetrically decrypt values of `password` and `safe_note` via `AES-256-GCM` algorithm. Size of IV and authTag for AES is the same as in encryption. Beware on cipher Key data type - it must be hex. Output is in JSON. 161 | 162 | Check example of password reader implementation in Python: [pwd_reader.py](https://github.com/trezor/python-trezor/blob/master/tools/pwd_reader.py) - there is an example code for decryption. 163 | -------------------------------------------------------------------------------- /slip-0014.md: -------------------------------------------------------------------------------- 1 | # SLIP-0014 : Stress Test Deterministic Wallet 2 | 3 | ``` 4 | Number: SLIP-0014 5 | Title: Stress Test Deterministic Wallet 6 | Type: Informational 7 | Status: Active 8 | Authors: Pavol Rusnak 9 | Created: 2015-01-12 10 | ``` 11 | 12 | ## Abstract 13 | 14 | SLIP-0014 describes a stress test deterministic wallet, which can be used 15 | to test various cornercases that such wallet can encounter. 16 | 17 | ## Motivation 18 | 19 | During the development of myTREZOR deterministic wallet we realized there 20 | are quite a lot of different types of transactions in the network. In order 21 | to simplify testing of transaction history we came up with the idea to create 22 | a special xpub that will contain these various types of transactions. 23 | 24 | For more coins and their addresses (not listed in this document) see [addresses.md](slip-0014/addresses.md) 25 | 26 | ## Wallet 27 | 28 | ### Bitcoin Legacy P2PKH (BIP44) 29 | 30 | ``` 31 | mnemonic: all all all all all all all all all all all all 32 | 33 | m/0/i account: 34 | xprv9xj9UhHNKHr6kJKJBVj82ZxFrbfhczBDUHyVj7kHGAiZqAeUenz2JhrphnMMYVKcWcVPFJESngtKsVa4FYEvFfWUTtZThCoZdwDeS9qQnqm 35 | xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy 36 | 37 | m/i account: 38 | xprvA1xn6h6qAwinYq5P37sJsEY39ntjzDpueQPAX9dBQcU81dqZrfBJBVMVuyqnVrMRViPxriZkdLd2vTtpnJaoaomJ67JBk3G1xMagp89w2XX 39 | xpub6Ex8WCdj1KH5mK9r99QKENUmhpjEPgYm1dJmKY2nxx16tSAiQCVYjHfymFdzfpYDAHGtWYTif7WkUKLMULRJFPeV1hvEbeXqrM11K85yPjp 40 | ``` 41 | 42 | [link to btc1.trezor.io](https://btc1.trezor.io/xpub/xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy) 43 | 44 | #### Addresses 45 | 46 | index | address | private key 47 | ------|------------------------------------|----------------------------------------------------- 48 | 0 | 1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL | L1KjqxZkUwdXaKNL15F2jJZVZpgi2HkHPHGyqTrQNNegyZez3A7Z 49 | 1 | 1GWFxtwWmNVqotUPXLcKVL2mUKpshuJYo | KyBcuurcaJw6NqnZsmtpDqjbsS67PTXEZAK9QyFEDsyYjmNJJozj 50 | 2 | 1Eni8JFS4yA2wJkicc3yx3QzCNzopLybCM | L3yYwqub7bYq6qKkPf9UAE7uuZYV8adAHvEaceXY9fKX8G7FDCoZ 51 | 3 | 124dT55Jqpj9AKTyJnTX6G8RkUs7ReTzun | L2SNnZeTNHwgr9mayyHLZxmpyQN4SNbrxjBf9Rwq5Fvu2wwTm476 52 | 4 | 15T9DSqc6wjkPxcr2MNVSzF9JAePdvS3n1 | L4jzKXRhQXesPeUSUNi7EMHAEBFzwJuAkZsNi5tja9rLxgGajwPv 53 | 5 | 1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ | L1N67rzEMn6fqvhkFeDnt11LMxYdGZtGQgdYVuASNpmQRawgbJEN 54 | 6 | 1PogPE3bXc84abzEuM2rJEZf2vCbCEZzXz | L3Y5pgT2ewKqdqh6kcGDQ7YHFoW5Vh4xErrPqb4Yjb5re9QYZw7D 55 | 7 | 176U2WABbj4h5PCrxE963wmxzXd2Mw6bP4 | L2RpVajejxusxUXqLHTFJAyp1nzJnT2xuJpfm7Uah4GGUHz7XD58 56 | 8 | 1HRZDR7CmLnq59w6mtzNa7SHtVWPSxdgKA | Kx8nBDjAkXkykD62AF8XjP8W5Z4a79iZC8Z7axyDWXsZTcn5agzM 57 | 9 | 1MPdvYLzcekvEzAB7DmiHa1oU8Foh4KUw8 | L1xWyxmCkjsB2Z9wnjoZ5TGabeg8KbpZt1PjgVsKA9pn3L7JCiTs 58 | 59 | ### Bitcoin Segwit P2SH (BIP49) 60 | 61 | ``` 62 | mnemonic: all all all all all all all all all all all all 63 | 64 | m/0/i account: 65 | yprvAJLEmZgYvTa8bVbfcqqsucwzYZvkFoafreCSNEfazkMqLgoGG8dBxbvyf9CnBpnFZeJPQn557NkeBJX3AAVfPVzh97JgJDh5KKcKDCEbbzm 66 | ypub6XKbB5DSkq8Royg8isNtGktj6bmEfGJXDs83Ad5CZ5tpDV8QofwSWQFTWP2Pv24vNdrPhquehL7vRMvSTj2GpKv6UaTQCBKZALm6RJAmxG6 67 | xprv9yVyTu1dmn2ekCQYnV4FhXrVNbnJKBbAwXgDaqmhcjyxHaz31UTdLYGqdwFCBv8LA1BafJUWeiQ6J1uUSU5ebGK6GmcFiJsb3bYfpfpLyva 68 | xpub6CVKsQYXc9awxgV1tWbG4foDvdcnieK2JkbpPEBKB5WwAPKBZ1mstLbKVB4ov7QzxzjaxNK6EfmNY5Jsk2cG26EVcEkycGW4tchT2dyUhrx 69 | 70 | m/i account: 71 | yprvALdQ3U9NJhsbrLxVLYzob6JfpC6bpsZ4b6n2wY6sjBqJymkRNRZbiWPZPTpQvDomCEePhzdHGNCYmrUpJXVrAS7XE77u2ks7ngs2DgoWAZv 72 | ypub6ZckSygG95Ru4q2xSaXoxEFQNDw6ELGuxKhdjvWVHXNHra5ZuxsrGJi3EhxtZBhUfkteowVwM3xEDqYoSHemQTJPH67BTUXc1V7Hvneqgzd 73 | xprvA1o8joUTA2L813mNWCDBP1DAeDx9tFZZfzFpA9CzMBTRvfwC7mQ36SjRNFrpvK9qnbXaxX2iohqztZsFaq5qNCRvMmRUSr3dWxoNq8pNtmz 74 | xpub6EnV9K1LzPtRDXqqcDkBk99uCFneHiHR3DBQxXcbuWzQoUGLfJiHeF3uDW1JZH3ZG7mr4TuNtPbgLYwEibEkcDcnQkQksZi7jm3eY8PqKFv 75 | ``` 76 | 77 | [link to btc1.trezor.io](https://btc1.trezor.io/xpub/ypub6XKbB5DSkq8Royg8isNtGktj6bmEfGJXDs83Ad5CZ5tpDV8QofwSWQFTWP2Pv24vNdrPhquehL7vRMvSTj2GpKv6UaTQCBKZALm6RJAmxG6) 78 | 79 | #### Addresses 80 | 81 | index | address | private key 82 | ------|------------------------------------|----------------------------------------------------- 83 | 0 | 3L6TyTisPBmrDAj6RoKmDzNnj4eQi54gD2 | L1xY6RmpnGn7r5bhQCrDXFTqVGFY7e1p62Rw5yw6bNzKUzRLD1tw 84 | 1 | 3GMMgFUQiYTYQhuHQuZfQoXPvW3GPqfGmD | Kx2KfpCa6Aewb1zxPBt5ex8MFNKk3SrJaeYRVjNRCUg7zALXDy8w 85 | 2 | 3BKbtvJtLSjnSoGUYTeQ17tMKTuyqbUV7P | L3L1oYXQbPmgpgvyB6BzM5PihfAvZfi3pFMZfppVQscM1zQokdtg 86 | 3 | 3Dyf1D6pVR6ZAQYN1th6ehgS1uqgGk1TGh | L3w2TxQpwJCkEhM96o3DTFTC1Pv67kpQ4Nwp4jD9n8oHvFQ7KsSB 87 | 4 | 33wLRyxHFtrXLF7Aun38Dctw5QyiBdruK2 | L1K9dsgY46AgcGsNYdqJCEQbKBvvSuRz1MrWu3ATgyRaq3vVprtn 88 | 5 | 32pKKUD5TKyqb4kzPorJnY8XhiLaHBKni1 | L2ET81wAcxm4vU22w7mEU2EC9bf5aNr1XaMNA1B9GkMHr5YT99a5 89 | 6 | 3NCRi181wMB1v9gPyms9WDruKemBfrE9rQ | KzyfHMxPYBmwgy3pJtqj2UK6xbqzA8TDZUdapXMCQidk2zLg1zVC 90 | 7 | 32d6ze9Be4J45ERomziXxGWXxLobAAQq85 | L3i75zyVQKi5ZBjHMghQSgCx1HYQnYjZh1N2Y6gBLciEa7mqYqvN 91 | 8 | 3FNTNKoAcXDUTUSNAtVTcvAehwQLyJSmP9 | L5SXQN7L1KNFTVurn4xaevP494RYRWNSqVUE2cUFMFnpQTSPHNYG 92 | 9 | 3L55P4LZsyKYUw5Aqy6DPky6ySw3g34TQS | Kzi8YhDogNJKVis8r5z4Lq8M6rSNudAG5p63pF45i9fQQb3KCAeC 93 | 94 | ### Bitcoin Native Segwit P2SH (BIP84) 95 | 96 | ``` 97 | mnemonic: all all all all all all all all all all all all 98 | 99 | m/0/i account: 100 | zprvAdteb7dRG4MHTAMUsLbyeUjn4VNQv8cvNWkC47f3wzMdvj4yZanmTGVtTSWEPbEAFyU2PCtDFTXXkUMaPnTwMs4n9PaKaEMAzKMzZguzwHG 101 | zpub6rszzdAK6RuafeRwyN8z1cgWcXCuKbLmjjfnrW4fWKtcoXQ8787214pNJjnBG5UATyghuNzjn6Lfp5k5xymrLFJnCy46bMYJPyZsbpFGagT 102 | xprv9zE7ynHaxhGKkZyFCd2jEJYmiZ5X2tdvYHhkVKsHBybspXSX4GTeD9BcR2b4PmvKShEQtFh6L8pRyu8SxPdumPhaQiBUQQiCSsEhnaadaYm 103 | xpub6DDUPHpUo4pcy43iJeZjbSVWGav1SMMmuWdMHiGtkK8rhKmfbomtkwW6GKs1GGAKehT6QRocrmda3WWxXawpjmwaUHfFRXuKrXSapdckEYF 104 | 105 | m/i account: 106 | zprvAfsoEuau196uNhLqiXUYRFTZSo97XHx3pdnRm6HAxF29d3Rswme3XE2oRwiLyitzijzMftxSeDU4xHZ7VDHktLdSe9gMX5mrjK47T728VMG 107 | zpub6ts9eR7nqWfCbBRJpZ1YnPQHzpybvkfuBri2ZUgnWaZ8Vqm2VJxJ52MHHCUoW7e47VBXCik3trD7DP1Xf7R9MT2JCH9Qzf3jWgSWDogr5oM 108 | xprvA2DGdaF4hn1wg6xc3ouJ15GZ6rrDe3y3zQjzCJVQCEGPWqoRSTJvH6iXPXoAyub9uTkkAwmKitkyBiKz3pTjHsGEuUHWMG8tBrvpg3G2uoU 109 | xpub6FCd35mxY9aEtb359qSJNDDHetgi3WguMdfazgu1kZoNPe8ZyzdApu31EnZdWJLDJCwuhmYvyXW1SonQDib7kyf6TbkZpqQkyEKDSf3g1jX 110 | ``` 111 | 112 | [link to btc1.trezor.io](https://btc1.trezor.io/xpub/zpub6rszzdAK6RuafeRwyN8z1cgWcXCuKbLmjjfnrW4fWKtcoXQ8787214pNJjnBG5UATyghuNzjn6Lfp5k5xymrLFJnCy46bMYJPyZsbpFGagT) 113 | 114 | #### Addresses 115 | 116 | index | address | private key 117 | ------|--------------------------------------------|----------------------------------------------------- 118 | 0 | bc1qannfxke2tfd4l7vhepehpvt05y83v3qsf6nfkk | Kycvq5CiKukoBWJjN3WEduoHnE6pKWrQPM7XuiLEkbgLuQgEzZPu 119 | 1 | bc1q7e6qu5smalrpgqrx9k2gnf0hgjyref5p36ru2m | Kz4p2JcERCPT6LADX5pDmV1XNtnskABTaCFQb1hyNuWDqY43HuwE 120 | 2 | bc1q5f2lvs7t29wv8nwssse6a4f6099sc3nagchqyc | KxXM7XXwK8G1yZpw5o8tqaA5Ria5R3WxX78zbdPdg3Ncp9mgHiur 121 | 3 | bc1q6hr68ewf72l6r7cj6ut286x0xkwg5706jq450u | KyGV2ApxE2gLmCukQbjKAKKrcGKBCGSRy2itnyXDoxcdjsdd9vXH 122 | 4 | bc1q7zql632newlfv9rt269jyxdn30370rh4kp23pd | L5gUrfBMftHbbn6tUaHNHkNcPxpz6niJsdCubAMHTaxU759RDY6N 123 | 5 | bc1qfcjv620stvtzjeelg26ncgww8ks49zy8lracjz | L3YbRwxjxLx9SwcKYyaKXWPtR3pqbPdzMjaTHv6oi62jETv6VNvC 124 | 6 | bc1quqgq44wq0zjh6d920zs42nsy4n4ev5vt8nxke4 | L1i1MqdvaTpcaPaHXfgMkxLU7Mq6DZHRzs54AmdAYNstE4vRRT2i 125 | 7 | bc1qunyzxr3gfcg7ggxp5vpxwm3q7t3xc52rcaupu4 | KzkvQCu5ERcFcd6HBicdcDEom3MEaP3ptRLeHqnG6X1LU3jj7vjh 126 | 8 | bc1q2glg28yag4rdgrd0hj5ntdvva8cgrjdsku5prc | KyQf4uHNM1eskde2jJ7XwrXDe8TD9DAML5UTp3uxA7uzbWSY1NzZ 127 | 9 | bc1q9z4cdmrgtfjsp34dmtvha98shje83jjn2t27z5 | L5o7HpPciFxK9QrJu2tWg6aVTK89KjLHizHPwwAfqVX2qyzxqmrB 128 | 129 | ## References 130 | 131 | - [BIP-0032: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 132 | - [BIP-0039: Mnemonic code for generating deterministic keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) 133 | - [BIP-0044: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) 134 | - [BIP-0049: Derivation scheme for P2WPKH-nested-in-P2SH based accounts](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki) 135 | - [BIP-0084: Derivation scheme for P2WPKH based accounts](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) 136 | -------------------------------------------------------------------------------- /slip-0023.md: -------------------------------------------------------------------------------- 1 | # SLIP-0023 : Cardano HD master node derivation from a master seed 2 | 3 | ``` 4 | Number: SLIP-0023 5 | Title: Cardano HD master node derivation from a master seed 6 | Type: Standard 7 | Status: Final 8 | Authors: Andrew R. Kozlik 9 | Created: 2019-07-24 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This specification describes how to derive the master node, aka root node, of the key tree in Cardano hierarchical deterministic wallets. 15 | 16 | ## Motivation 17 | 18 | Cryptocurrency wallets generally work by combining a [BIP-0039](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic or a set of [SLIP-0039](https://github.com/satoshilabs/slips/blob/master/slip-0039.md) mnemonics with a user-entered passphrase to generate a master seed. This master seed is then used to derive a hierarchy of cryptographic keys as defined in [BIP-0032](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md). 19 | 20 | Cardano hierarchical deterministic wallets use an extended private key which requires them to implement a custom adaptation of the BIP-0032 child key derivation scheme. The Cardano wallets currently in existence implement several mutually incompatible schemes for the derivation of the master node from a BIP-0039 mnemonic and passphrase. Unfortunately all of these derivation schemes fail to separate the derivation of the seed from the derivation of the key tree, making it impossible to integrate them with new seed derivation schemes. This specification aims to rectify this by defining a new scheme for the derivation of the master node from a seed. The new scheme is primarily intended for use with SLIP-0039 Shamir's Secret-Sharing for Mnemonic Codes. 21 | 22 | ## Cardano universal master node derivation 23 | 24 | This scheme adapts the master node derivation used in BIP-0032 and SLIP-0010 by defining a new curve name "ed25519 cardano seed" for the Ed25519 curve with the Cardano deterministic key hierarchy. The curve name is used as salt in BIP-0032 and SLIP-0010 when deriving the master node from the seed. This is necessary to ensure proper domain separation between different elliptic curves or different types of key hierarchies. The root extended private key (*k*L, *k*R) is computed by taking the SHA-512 hash of the root private key *I*L, modifying certain bits to make it a valid EdDSA key and clearing the third highest bit of *k*L to ensure compatibility with Cardano child key derivation. 25 | 26 | 1. Let *S* be a seed byte sequence such as the master secret from SLIP-0039. 27 | 2. Calculate *I* := HMAC-SHA512(Key = "ed25519 cardano seed", Data = *S*). 28 | 3. Split *I* into two 32-byte sequences, *I*L := *I*[0:32] and *I*R := *I*[32:64]. 29 | 4. Let *k* := SHA-512(*I*L). 30 | 5. Modify *k* by assigning *k*[0] := *k*[0] & 0xf8 and *k*[31] := (*k*[31] & 0x1f) | 0x40. 31 | 6. Interpret *k*[0:32] as a 256-bit integer *k*L in little-endian byte order. Let *k*R := *k*[32:64] and use (*k*L, *k*R) as the root extended private key and *c* := *I*R as the root chain code. 32 | 33 | ## Cardano Icarus master node derivation 34 | 35 | The Icarus master node derivation scheme, aka V2 derivation scheme, is commonly used with BIP-0039 in Cardano wallets. Since there does not exist any specification of this scheme, its description is included below for completeness. 36 | 37 | 1. Let *M* be a BIP-0039 mnemonic and *P* the passphrase entered by the user. 38 | 2. Determine the initial entropy *E* that was used to generate *M*. 39 | 3. Compute *S* := PBKDF2-HMAC-SHA512(password = *P*, salt = *E*, iterations = 4096, dkLen = 96). 40 | 4. Modify *S* by assigning *S*[0] := *S*[0] & 0xf8 and *S*[31] := (*S*[31] & 0x1f) | 0x40. 41 | 5. Interpret *S*[0:32] as a 256-bit integer *k*L in little-endian byte order. Let *k*R := *S*[32:64] and use (*k*L, *k*R) as the root extended private key and *c* := *S*[64:96] as the root chain code. 42 | 43 | ## Child key derivation 44 | 45 | The derivation of child keys in the Cardano deterministic key hierarchy is specified in [BIP32-Ed25519](https://cardanolaunch.com/assets/Ed25519_BIP.pdf). 46 | 47 | ## Compliance 48 | 49 | When SLIP-0039 is used as the source of the master secret the master node for the Cardano deterministic key hierarchy MUST be derived using the Cardano universal master node derivation scheme as specified [above](#cardano-universal-master-node-derivation). 50 | 51 | When BIP-0039 is used as the source of the master secret the master node for the Cardano deterministic key hierarchy SHOULD be derived using the Cardano Icarus master node derivation scheme to maintain compatibility with existing wallets. 52 | 53 | ## Test vectors 54 | 55 | In the following test vectors the values of *S*, *k*R, *A* and *c* are each encoded as a string containing two hexadecimal digits for each byte. The value of *k*L is encoded as an integer in base 10. 56 | 57 | ### Test vector 1 for Cardano universal master node derivation (128 bits) 58 | 59 | Let the seed be *S* = "578d685d20b602683dc5171df411d3e2". 60 | 61 | Note that *S* is the master secret obtained from the following three SLIP-0039 share mnemonics with the passphrase "TREZOR": 62 | 63 | * "extra extend academic bishop cricket bundle tofu goat apart victim enlarge program behavior permit course armed jerky faint language modern", 64 | * "extra extend academic acne away best indicate impact square oasis prospect painting voting guest either argue username racism enemy eclipse", 65 | * "extra extend academic arcade born dive legal hush gross briefing talent drug much home firefly toxic analysis idea umbrella slice". 66 | 67 | The root extended private key is:
68 | *k*L = 38096432269777187972282727382530464140043628323029465813805073381215192153792
69 | *k*R = "4064253ffefc4127489bce1b825a47329010c5afb4d21154ef949ef786204405" 70 | 71 | The root public key is:
72 | *A* = "83e3ecaf57f90f022c45e10d1b8cb78499c30819515ad9a81ad82139fdb12a90" 73 | 74 | The root chain code is:
75 | *c* = "22c12755afdd192742613b3062069390743ea232bc1b366c8f41e37292af9305" 76 | 77 | The address for the derivation path 44'/1815'/0'/0/0 is:
78 | Ae2tdPwUPEYxF9NAMNdd3v2LZoMeWp7gCZiDb6bZzFQeeVASzoP7HC4V9s6 79 | 80 | The address for the derivation path 44'/1815'/0'/0/1 is:
81 | Ae2tdPwUPEZ1TjYcvfkWAbiHtGVxv4byEHHZoSyQXjPJ362DifCe1ykgqgy 82 | 83 | The address for the derivation path 44'/1815'/0'/0/2 is:
84 | Ae2tdPwUPEZGXmSbda1kBNfyhRQGRcQxJFdk7mhWZXAGnapyejv2b2U3aRb 85 | 86 | ### Test vector 2 for Cardano universal master node derivation (256 bits) 87 | 88 | Let the seed be *S* = "a055b781aac0c9dc1bfb7d803bc8ffd5d4392e506db2e4a5a93f0aba958c5be7". 89 | 90 | Note that this is the master secret obtained from the two SLIP-0039 share mnemonics with the passphrase "TREZOR": 91 | 92 | * "hobo romp academic axis august founder knife legal recover alien expect emphasis loan kitchen involve teacher capture rebuild trial numb spider forward ladle lying voter typical security quantity hawk legs idle leaves gasoline", 93 | * "hobo romp academic agency ancestor industry argue sister scene midst graduate profile numb paid headset airport daisy flame express scene usual welcome quick silent downtown oral critical step remove says rhythm venture aunt". 94 | 95 | The extended private key is:
96 | *k*L = 97 | 35870817594148037193235249761081259065186522922583196642112477624627719791504 98 |
99 | *k*R = "f9d99bf3cd9c7e12663e8646afa40cb3aecf15d91f2abc15d21056c6bccb3414" 100 | 101 | The root public key is:
102 | *A* = "eea170f0ef97b59d22907cb429888029721ed67d3e7a1b56b81731086ab7db64" 103 | 104 | The root chain code is:
105 | *c* = "04f1de750b62725fcc1ae1b93ca4063acb53c486b959cadaa100ebd7828e5460" 106 | 107 | The address for the derivation path 44'/1815'/0'/0/0 is:
108 | Ae2tdPwUPEYyDD1C2FbVJFAE3FuAxLspfMYt29TJ1urnSKr57cVhEcioSCC 109 | 110 | The address for the derivation path 44'/1815'/0'/0/1 is:
111 | Ae2tdPwUPEZHJGtyz47F6wD7qAegt1JNRJWuiE36QLvFzeqJPBZ2EBvhr8M 112 | 113 | The address for the derivation path 44'/1815'/0'/0/2 is:
114 | Ae2tdPwUPEYxD9xNPBJTzYmtFVVWEPB6KW4TCDijQ4pDwU11wt5621PyCi4 115 | 116 | ## References 117 | 118 | * [BIP-0032](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki): Hierarchical Deterministic Wallets 119 | * [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md): Universal private key derivation from master private key 120 | * [BIP-0039](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki): Mnemonic code for generating deterministic keys 121 | * [SLIP-0039](https://github.com/satoshilabs/slips/blob/master/slip-0039.md): Shamir's Secret-Sharing for Mnemonic Codes 122 | * D. Khovratovich and J. Law: [BIP32-Ed25519 Hierarchical Deterministic Keys over a Non-linear Keyspace](https://cardanolaunch.com/assets/Ed25519_BIP.pdf) 123 | -------------------------------------------------------------------------------- /slip-0015.md: -------------------------------------------------------------------------------- 1 | # SLIP-0015 : Format for Bitcoin metadata and its encryption in HD wallets 2 | 3 | ``` 4 | Number: SLIP-0015 5 | Title: Format for Bitcoin metadata and its encryption in HD wallets 6 | Type: Standard 7 | Status: Final 8 | Authors: Karel Bilek 9 | Created: 2015-01-12 10 | ``` 11 | 12 | ## Abstract 13 | 14 | SLIP-0015 describes a format to save Bitcoin transaction metadata (labels to accounts, transactions) 15 | in a secure way, with regard to HD wallets, especially (but not limited to) hardware HD wallets. 16 | 17 | ## Goals 18 | 19 | In myTREZOR web wallet, we need to save additional metadata, such as account labels or transaction labels. 20 | We had several goals: 21 | 22 | 1. data should be safely saved on a untrustworthy cloud service (such as Dropbox) 23 | 2. usage should be effortless with secure hardware wallet 24 | 3. we should allow other applications to use the files, even when they don't support hardware wallets in general 25 | 26 | Because we want effortless usage, we want users to be able to add metadata even when they don't have the device connected, or even when they don't actually own the device. 27 | 28 | For this reason, we don't want to sign the changes on the secure device and we want to encrypt everything 29 | on an unsecure device, with the key in memory. 30 | This has the unfortunate consequence of attacker being able to both read and edit metadata if he attacks 31 | the unsecure device. 32 | 33 | However, we want at least prevent the cloud storage operator to be able to read the metadata. We want to hide 34 | the metadata itself from the cloud storage operator, and even the XPUBs of the accounts for deniability. 35 | 36 | ## General design 37 | 38 | We first derive a *master key* from hardware device itself, which is shared for all accounts on the device. 39 | 40 | We then derive *account key* for every account. This key is a string -- because of the stated goal 3., we want to be able to import it into third party applications without HD wallets. 41 | 42 | From the account key, we derive both a filename and a symmetric encryption key. We then save the metadata to the given file, in an encrypted JSON. 43 | 44 | ## Design details 45 | 46 | ### Deriving master key 47 | 48 | We first get the master key by sending CipherKeyValue to hardware device with following parameters 49 | 50 | * path: `m/10015'/0'` (hardened path, see BIP32) 51 | * key: `Enable labeling?` 52 | * value: `fedcba98765432100123456789abcdeffedcba98765432100123456789abcdef` (byte sequence, here in hexadecimal) 53 | * encrypt: true 54 | * ask_on_encrypt, ask_on_decrypt: true 55 | * iv: unset 56 | 57 | CipherKeyValue is defined in [SLIP-0011](slip-0011.md). 58 | 59 | The master key should be 32 bytes (256 bits) long. It is treated as a pseudo-random byte sequence. 60 | 61 | ### Deriving account key 62 | 63 | From the master key, we derive the account key for every account in the following way: 64 | 65 | First, we use the HMAC function: 66 | 67 | `HMAC-SHA256(master key, xpub)` 68 | 69 | where 70 | 71 | * master key is a byte sequence, as defined in the previous section 72 | * xpub is a string, as defined in BIP32. For example: 73 | 74 | `xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy` 75 | 76 | Then, the result is converted to string using Base58Check encoding, as used in Bitcoin. 77 | 78 | The API key is either 49 or 50 characters long. 79 | 80 | ### Deriving filename and password from account key 81 | 82 | We take the account key, *as a string*, and we use HMAC function to derive filename and password for metadata file. Every account has its own metadata file. 83 | 84 | * First, we use the HMAC function `HMAC-SHA512(API key, constant)`, where 85 | 86 | * API key is a string (in base58c) from the previous section. 87 | 88 | The API key is taken as a string, so third-party applications can use their own API keys. 89 | 90 | * constant is `0123456789abcdeffedcba9876543210` (byte sequence, here in hexadecimal). 91 | 92 | * The result is 64 bytes/512 bits. 93 | 94 | * The first half is used to derive the filename. 95 | 96 | The bytes are converted to hexadecimal, which is the used as a filename, with the extension ".mtdt". 97 | 98 | We are using hexadecimal instead of base64/base58 because of the ambiguity on case-insensitive filesystems. 99 | 100 | * The second half is used as a key for further encryption, as a byte sequence. 101 | 102 | * We are using `AES-256-GCM` algorithm for encryption. 103 | 104 | * Random 12 bytes are generated as a IV 105 | * GCM is used with the full 128-bit tag 106 | 107 | * The resulting file looks like this: 108 | 109 | * first 12 bytes of the file are the random IV 110 | * the next 16 bytes are the GCM authentication tag 111 | * the rest is the ciphertext 112 | 113 | ### Data format 114 | 115 | The (decrypted) metadata are in following format: 116 | 117 | The file is a serialized JSON object with the following keys: 118 | 119 | * `version`: version of metadata format, for future backwards compatibility. The version is currently `1.0.0`. 120 | * `accountLabel`: label for the account, a string 121 | * `outputLabels`: labels for outputs, described further 122 | * `addressLabels`: labels for addresses, described further 123 | 124 | `outputLabels` has transaction hashes for keys, and for values it has object with output indexes for keys and output labels, as strings, for values. Output indexes start at 0. 125 | 126 | `addressLabels` has addresses (in traditional Base58Check encoding) for keys and their labels for values. Only receiving addresses are saved in this object. 127 | 128 | All labels can have any unicode letters. Empty string is treated in the software as having no label. 129 | 130 | An example object looks like this: 131 | 132 | ```javascript 133 | { 134 | "version": "1.0.0", 135 | "accountLabel": "Saving account", // one file per account, so only 1 label needed 136 | "addressLabels": { 137 | "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL": "My receiving address", 138 | "1GWFxtwWmNVqotUPXLcKVL2mUKpshuJYo": "" // equivalent to no label set or null 139 | }, 140 | "outputLabels": { 141 | "350eebc1012ce2339b71b5fca317a0d174abc3a633684bc65a71845deb596539": { 142 | "0": "Money to Adam", 143 | "1": "" // equivalent to no label set 144 | }, 145 | "ebbd138134e2c8acfee4fd4edb6f7f9175ee7b4020bcc82aba9a13ce06fae85b": { 146 | "0": "Feeding bitcoin eater" 147 | } 148 | } 149 | } 150 | ``` 151 | 152 | (comments are of course not part of a valid JSON and are included here only for clarity) 153 | 154 | ## Example 155 | 156 | All the example code is in Python2. 157 | 158 | ### Deriving "master" key 159 | 160 | Example code, deriving a master key from a connected TREZOR is in [1_masterkey.py](slip-0015/1_masterkey.py). It requires [python-trezor](https://github.com/trezor/python-trezor) installed and TREZOR connencted 161 | 162 | For the "stress test" wallet, defined in SLIP-0014, the master key should be (in hex): 163 | 164 | ``` 165 | 20c8bf0701213cdcf4c2f56fd0096c1772322d42fb9c4d0ddf6bb122d713d2f3 166 | ``` 167 | 168 | ### Deriving "account" key 169 | 170 | Example code, deriving an account key for master key, is in [2_accountkey.py](slip-0015/2_accountkey.py). First argument of the script is xpub of the account, the second argument is the master key from previous step (in hexadecimal). 171 | 172 | For the "stress test" wallet, defined in SLIP-0014, and its first account (with the xpub `xpub6BiVtCp...`), the key should be: 173 | 174 | ``` 175 | v5kCxSKLTsnwmgPBeaRyFDWeG9zXouF34L72763zjLrS4LWy8 176 | ``` 177 | 178 | ### Deriving filename, decoding 179 | 180 | Example code for decryption is in [3_decrypt.py](slip-0015/3_decrypt.py). First and only argument is the account key from previous step. The file has to be in a current working directory (in myTREZOR, we use `~/Dropbox/Apps/TREZOR/` for saving the files). 181 | 182 | With the key `v5kCxSKLTsnwmgPBeaRyFDWeG9zXouF34L72763zjLrS4LWy8`, filename `08108c3a46882bb71a5df59f4962e02f89a63efb1cf5f32ded94694528be6cec.mtdt` and the data (in hex) 183 | 184 | ``` 185 | d32a5831b74ba04cdf44309fbb96a1b464fe5d4a27d1e753c30602ba1947 186 | 3cca7d8734e8b9442dbd41d530c42e03fea59a5d38b21392f3e4a135eb07 187 | 009d5a8b9996055b7aff076918c4ed63ee49db56c5a6b069cac7f221f704 188 | 5af7197cdbb562ba004d7a6f06eb7cffd1dfb177fd652e66c2d05d944b58 189 | 85d6a104853a0d07e4cebff3513a2f6a1c8ff6f4f98ce222f3d601f1c796 190 | d070b7523649e10242dfe78cb2db50e826dd18b1f65213f5c0748577ecc9 191 | 7b8e13ab9cd0c5fe7b76635717c64ad352064a3321df6bbfa2db8ef8c692 192 | 55ef9d8a8dfbce9c6ad3029bbdcf1b2bb04795fd96aa95d27e6ca1ed2658 193 | bfb108b44dac2159184d6e3cabe341e2ec5d83756aeb8c408e92fe6ca3e6 194 | 3d4c0d644aa2648341506324574d205934c65f54979b1d684f7a2442e8d5 195 | 2149ed67449019e6091aa182afcaf5aa1fa8bf3114ee7b46e47b4c6648d1 196 | d1355cefd10081be6e8c7bdf1b2ff14d8896b1ede811fa1aa2c024a6ebf3 197 | 6baf0a8d6afa2975bf551e8bc3f03117b42dc4cbe2a6bd700f2fda40c78a 198 | 48627ebc130286ba98 199 | ``` 200 | 201 | we should get to file, similar to the one described above. 202 | 203 | Similarly, in [4_encrypt.py](slip-0015/4_encrypt.py) there is an example code for encrypting. 204 | -------------------------------------------------------------------------------- /slip-0014/addresses.md: -------------------------------------------------------------------------------- 1 | # SLIP-0014: Addresses for various Coins and Chains 2 | 3 | Generated using [https://iancoleman.github.io/bip39/](https://iancoleman.github.io/bip39/) 4 | 5 | ## Bitcoin 6 | 7 | `m/44'/0'/0'/0/i` 8 | 9 | index | address | public key | private key 10 | ------|------------------------------------|--------------------------------------------------------------------|------------ 11 | 0 | 1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL | 03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c | L1KjqxZkUwdXaKNL15F2jJZVZpgi2HkHPHGyqTrQNNegyZez3A7Z 12 | 1 | 1GWFxtwWmNVqotUPXLcKVL2mUKpshuJYo | 02c651a011009e2c7e7b3ed2068857ca0a47cba35b73e06c32e3c06ef3aa67621d | KyBcuurcaJw6NqnZsmtpDqjbsS67PTXEZAK9QyFEDsyYjmNJJozj 13 | 2 | 1Eni8JFS4yA2wJkicc3yx3QzCNzopLybCM | 03330236b68aa6fdcaca0ea72e11b360c84ed19a338509aa527b678a7ec9076882 | L3yYwqub7bYq6qKkPf9UAE7uuZYV8adAHvEaceXY9fKX8G7FDCoZ 14 | 3 | 124dT55Jqpj9AKTyJnTX6G8RkUs7ReTzun | 03e6c684d1e5edffe2fc43d260eb19fea91754b92e90627df7f87e06fc12c6a485 | L2SNnZeTNHwgr9mayyHLZxmpyQN4SNbrxjBf9Rwq5Fvu2wwTm476 15 | 4 | 15T9DSqc6wjkPxcr2MNVSzF9JAePdvS3n1 | 03f54094da6a0b2e0799286268bb59ca7c83538e81c78e64f6333f40f9e0e222c0 | L4jzKXRhQXesPeUSUNi7EMHAEBFzwJuAkZsNi5tja9rLxgGajwPv 16 | 5 | 1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ | 02a7a079c1ef9916b289c2ff21a992c808d0de3dfcf8a9f163205c5c9e21f55d5c | L1N67rzEMn6fqvhkFeDnt11LMxYdGZtGQgdYVuASNpmQRawgbJEN 17 | 6 | 1PogPE3bXc84abzEuM2rJEZf2vCbCEZzXz | 0369cb2f81b3ec4f0132cf1ac88f09332439773b3f1579bb6557717d0b720c7226 | L3Y5pgT2ewKqdqh6kcGDQ7YHFoW5Vh4xErrPqb4Yjb5re9QYZw7D 18 | 7 | 176U2WABbj4h5PCrxE963wmxzXd2Mw6bP4 | 03dca76f16e6dd87396c5cdae1af1515b60d104fba881cd7591fe6fa60ef3aeabd | L2RpVajejxusxUXqLHTFJAyp1nzJnT2xuJpfm7Uah4GGUHz7XD58 19 | 8 | 1HRZDR7CmLnq59w6mtzNa7SHtVWPSxdgKA | 0346978a895e75eb498dbf4aff8fa334e6994db1b34a4f2576adc9225415eb9548 | Kx8nBDjAkXkykD62AF8XjP8W5Z4a79iZC8Z7axyDWXsZTcn5agzM 20 | 9 | 1MPdvYLzcekvEzAB7DmiHa1oU8Foh4KUw8 | 02c3ffb6e3456bda85d17845a764f23a54aad4fd39260d5c8da6493134713862ca | L1xWyxmCkjsB2Z9wnjoZ5TGabeg8KbpZt1PjgVsKA9pn3L7JCiTs 21 | 22 | ## Bitcoin Testnet 23 | 24 | `m/44'/1'/0'/0/i` 25 | 26 | index | address | public key | private key 27 | ------|------------------------------------|--------------------------------------------------------------------|------------ 28 | 0 | mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q | 030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0 | cPigoY3hubxpXad1t5WmxpcQpmezLeCcbpA7EpyhDofFnein2wF5 29 | 1 | mopZWqZZyQc3F2Sy33cvDtJchSAMsnLi7b | 0294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852 | cVN8eHRQh8r9THM2Mu5HCSjx6cfVdssqGL1KeiCKBwUouyf6K5F5 30 | 2 | mgswWyysmViMqYmn5XEj1pVz7rVUftVEBP | 03f5008445568548bd745a3dedccc6048969436bf1a49411f60938ff1938941f14 | cUCiXe6qNE43rEJkSR9e1Tt37W5gQmmGeBiSmXzDbZgxbs5Z5nvK 31 | 3 | momtnzR3XqXgDSsFmd8gkGxUiHZLde3RmA | 029ad0b9519779c540b34fa8d11d24d14a5475546bfa28c7de50573d22a503ce21 | cTAi8RAF2htyUn3F921npbuJLSVdYfpfwqjwLEAPkqvFxLAF716k 32 | 4 | moE1dVYvebvtaMuNdXQKvu4UxUftLmS1Gt | 0313a443e806f25052ac7363adc689fcfa72893f2a51a35ab5e096ed5e6cd8517e | cUmGFJMq5Vkh4rjKHe4J4S5adJH1E8xFJJ2ZARBSZNBVzYwj1RvH 33 | 5 | muXZYKRJFJ2qPegzV2GEzLqHxngJpzMrmT | 02e35cca50cb2626212bce8fdfb988bb33f303b15536e9f84f018e63045dbb84ac | cRHMG1RjgVWTdUNEgDD5oNEvQvBAha5N3YntnT7rC8yekePLGQwR 34 | 6 | mnY26FLTzfC94mDoUcyDJh1GVE3LuAUMbs | 0344e14b3da8f5fe77a5465d0f8fe089d64ed5517d1f1f989edd00f530938a2c22 | cS9rFFu8douRgweuQKLdF4QXpS3H1UeoNxZWTt6K874nt4sy56HX 35 | 7 | mgV9Z3YuSbxGb2b2Y1T6VCqtU2osui7vhG | 035169c4d6a36b6c4f3e210f46d329efa1cb7a67ffce7d62062d4a8a17c23756e1 | cQ1Uh9vXLhaoEgPGUEGMoWACpzrVesmB8G4KdK5vZBnLBifyB29Q 36 | 8 | miLqfMwzis98J5vkjjhTiXVsrkAYwuxmts | 03260dc4925b14addb52b4e62c698b99d2318f3d909477a081ae8e5d94dc3c66d8 | cPwi3WVwjgr422fBeLa22UHwRkQEMZqoJBjevuosqd25yyYekEkF 37 | 9 | mhAacBq3SnXEpoxzEwKqfnQz1iYjxmGg9V | 02b3397d76b093624981b3c3a279c79496d16820f821528b9e403bdfc162b34c3c | cRkkmKXgTmq3Je2B71Rn4HQxeo2hEqvtUeQ5r4Q7eKr5qtq6vzu4 38 | 39 | ## Dash 40 | 41 | `m/44'/5'/0'/0/i` 42 | 43 | index | address | public key | private key 44 | ------|------------------------------------|--------------------------------------------------------------------|------------ 45 | 0 | XdTw4G5AWW4cogGd7ayybyBNDbuB45UpgH | 02936f80cac2ba719ddb238646eb6b78a170a55a52a9b9f08c43523a4a6bd5c896 | XFiosCguxccAvHDasUYWU4mmx4PABR4dDQhk99k8D2N9cKeTRnYq 46 | 1 | XbDjZajDR6Y9uB23GBrMUKX4Lci3PqPXT1 | 027e1c93904ae880921decff4042cee3901c984fb89f33b39e9cf1db544002e6ba | XKCAE7yNMpRyczUehbX1aMQabUqd8g5Hx2FobmkZ2QVUmoRFiKGJ 47 | 2 | XimA3jRAgsksN937ibHrMny6gYy3RChjFs | 0233e06386e60f9f02fcd2b73f1868cdf5a6dfdcebcd6ddc2b337b25feb1053532 | XBscYDmgeg6xuK9tUZk5itHGYRqs5VqpUcu4Yn5An3TJrfz7xfgb 48 | 3 | Xhxyt3pKQKa2HkePA8tP3NSjkWXFgdsjzH | 02012cf694423b0bba8a54596f4923c1c8d74458f884f8d611c7305ca6d25320d1 | XEkU65os4QjrLYy8HKxfEYtFyuy7RqMAGpHDEgSdMjFWtDFDRPid 49 | 4 | XfcGasDgKu2JvVS38b9pWUcfY8yfCaH9dF | 029aaeefff9ae8ea408de41747ac634b49cb90e111b1ac623c3c742dc5ebe42737 | XFaR8NpQjY8wWrUPNmedwvXyFQTJyj75k1jfYh4Bs2sfBzmfTRFz 50 | 5 | XuBYWmRi7q2KrajtXxpmWC5vKMyqCeKMAj | 0211311f13a287ad81adf710cc837f66b2ce432070752c376861d08c7b91eda67e | XEBxR4AExnhCEBXLvQGX9KYg1TwSfngN4CgnzMeY6zeAgLQYxnYH 51 | 6 | XvYXR1LCedCJBXDVuye7wevrmR5ASaQdEq | 03a526d4aa1bd23e3a4d21646b25901d30734b09413eb6462f9251707db0da0f0a | XEo8Haet4xLXrPiEbmRogGXjs8UyeowRUXHrfKkF45m32w18u7hK 52 | 7 | XgrVDtp8X2C3hEPcwcNY31UPvWGfHSBytG | 02c13197de985aff1847a0b0b6fa41d750cdcf3dee03b3e209729ea4a5c99341a7 | XBdQ7YnpdKqyuA5RH2RzwfWnACKgpTJg9STbxrGFmgoKG7URhYGN 53 | 8 | XteBgFFTpGz2NNedqsZEcqPz5m31AQBBYz | 0260ec3beb9f51b4de98fe7f4c13814077603b6211c9e6acdd1c7b0cc796450d79 | XK13VgxcbF3h9Hr9g5bn1uuhtuaNsfEbcFzQxUsowVVeV7LKGQRy 54 | 9 | XpkAwbPzQFdLmuAeYs7BLJfHfXL163QatG | 027df3bcb58f397d99ec944ae74b15f15bf6ab24190e11e7d3fc164107eb36258b | XEq1Rvq4AQKNm52pqiaeUnyG6DZ9Zf6EvrmaZ23Xx2aVrUPYkq6b 55 | 56 | ## Litecoin 57 | 58 | `m/44'/2'/0'/0/i` 59 | 60 | index | address | public key | private key 61 | ------|------------------------------------|--------------------------------------------------------------------|------------ 62 | 0 | LcubERmHD31PWup1fbozpKuiqjHZ4anxcL | 021239d8b20ad1f83d34383e82075d0e11f7a98d06f9e015b56cff61db1e4f8c25 | T5wTndHdQ1sDnQhApMnDrbQV56PEnjZeRMq9ao2aRJALyUdjdExP 63 | 1 | LVWBmHBkCGNjSPHucvL2PmnuRAJnucmRE6 | 02c88e3d1c97fe3ff8eb2f51c37ca66cbfabb6404ddf8158478fae3b8a90e98035 | TAZnJTHBjN7UoXV6v1aGhVkgq7kBbtXe9h1oKND7LHGS4FC5wnKQ 64 | 2 | LUQ91iCfoayy3G3rrFtmF6eVzKQyFSdi2T | 02df4513e0faae40c6e1dbca606c4fe6c3e22d00a30024ea2b01b7da0097a97f82 | T3bxs7ZtsnCrXn1dhYJeRBu2FkLFLf8oyhiahMkhdJwxiDVAUP1e 65 | 3 | LNk7cQvGW5LPgkii3RUX7YQWtX6HjmLbB4 | 03a69bec3139474eec35f7c87d59f8b6ec37423dbcfce5c5d090bd26de604a2b70 | T3SQgQ4byehx5ayT98PE7ZDPr68taysoW2Hm6FyDNWuyKiBpWa3L 66 | 4 | Laz1nYzJwrGcaZDEERENpNVbgte1n3vWLJ | 03ed59a1f1b1e2af17ae00ff373a3cedd8b7bd3c4723a76d469e52ec8caba09337 | T5HGaZgAs35kWheKDFDhdHz1sqNgo3FitUaeBegugamfFxRSjYga 67 | 5 | LcBMCi1mQ71LLvFqN2TMgEgomoc9yqEFzg | 0279224038c76ffcfd1a95ca5d93bcb15c426e18776362fcddd76ff7cc60b9a25d | TAdPGc81ANgVhvEVyK5K5DQee4DEv1dDeXAUCBqn6ocPx5Wdi7qc 68 | 6 | LfyFtx6XekFZ54gATTjrgeFFmMqAboZwvi | 0284b369982fba3be2ef729a96b13806b2372c6f3b5209c44fd5ce29c0a1eca976 | T8WecZVp58aYSvtaw8PAhhx2hxMRBUuvT25dtDyk4x6vE97PHnAY 69 | 7 | Le2twPHqkDEiPrY4uZw6Ufes3e7t4VUZ68 | 032e030b64a7de06fc972b7fb82ca4392c4e5a535ce942f32d6b660b1d58b5176c | T5ojDJgMa3QYZkst9po2B6P5SXyP4vFuBFZBhvyp8E9Ek74yCzoE 70 | 8 | LViaNcv7TTQv8yFFvBnjC63dwVNL3e21c1 | 026b9d73e88ecbcd55a68e0a8e6c651e2543075b85fc6e85386e1a8009e9a55abe | T7YQp9UidMzNSRJHPpCVWeANPpDK5Nz1MhfWuP5sy6YFUB5VJiat 71 | 9 | LfritJSaLhmsRDaZwYSnfpUMNTA8kTweHa | 030ad428a32f117f21cbf581630858b28baa957cb475ac43b7536b1a1da3d00293 | T3WSZzJmXPZB7Mr5vAQ5qmi2b9zFww5oLHqUcyy7371d9ujZb8Kb 72 | 73 | ## Ethereum 74 | 75 | `m/44'/60'/0'/0/i` 76 | 77 | index | address | public key | private key 78 | ------|--------------------------------------------|--------------------------------------------------------------------|------------ 79 | 0 | 0x73d0385F4d8E00C5e6504C6030F47BF6212736A8 | 03ad8e7eb4f3a7d1a409fa7bdc7b79d8840fe746d3fa9ee17fee4f84631ec1430b | 759e46263f1505994d11142d70027975c9b9fef15489b09bd987eb8a31aba0db 80 | 1 | 0xFA01a39f8Abaeb660c3137f14A310d0b414b2A15 | 03ddeae7da4e54757d3f3038315344709971849a971d2619797d9b8574e373ae9b | 616883a861adaab932634c283e294bcfdc9797757984bc4a15a9484ada947177 81 | 2 | 0x574BbB36871bA6b78E27f4B4dCFb76eA0091880B | 039d09121b995a1f7fe5d30996f6a66fff4688f8eee096faea2957e1fe53923860 | 4f74b7bb78734476e41caa28a397493260103f4ccf0b8a14fe340da5a8a7e22c 82 | 3 | 0xba98D6a5ac827632E3457De7512d211e4ff7e8bD | 0307b32cc46360c9acf750da7acf7dce918aee97dd383236248c9c79b8efbd98fc | a02122e1ac06fb63da2fd293706c91b5839108de765dc9ce3e2d3fb1573bafd4 83 | 4 | 0x1f815D67006163E502b8eD4947C91ad0A62De24e | 03d26a9f183bbb531e140ab3d87bca361706b4c4be7c731e29160cab833e7a9282 | f686b6033ef11ad995ff93b240bd28b04c6dc3a24cb35861b642f7ba969564e0 84 | 5 | 0xf69619a3dCAA63757A6BA0AF3628f5F6C42c50d2 | 02ae8cef29ef6d2ad9b98af746589743c510e4b49784ec1181a079b4b1df3c5211 | 945f0973cd011048b56bb87887ad782c72b09ff181f4af97ad033581ea009a74 85 | 6 | 0xA8664Df3D5E74BE57c19fC7005BBcd0F5328041e | 023ed2881ee76991dafd40e33df96a88a5e929869635cdfc261e947d1e9ca31be9 | 7226389c1de87a3498234ad49e00e48060609b839616de313b341c6245142993 86 | 7 | 0xf2252f414e727d652d5a488fE4BFf7e64478737F | 03b765e9b8ba13ffb45e69f038bf1506aa2ecf1f1824c88551f98e93026c06e6b4 | 640dfbf3d433c548d0a1b9d0d5dc824f72d631cdfca0902ad16788b6b3081067 87 | 8 | 0x5708Ae081b48ad7bA8c50ca3D4fa0238d544D6FA | 031acf557e85d59e0305b8b79d4a5cc5077d09811206be208c00c4e457e7017ac1 | 728a3bd762ac7a25d58eafcd3240bb783304cd323e78b5967a8ecdb4c1e1a982 88 | 9 | 0x12eF7dfb86f6D5E3e0521b72472ca02D2a3814F4 | 02c9f2bf6bbf6244eec9866ad6eb6dec628cbf71f2e2cb77c25d72baeca2c32f61 | 9ee5234da5069eede6135c0f684fd0b633504a04614c740aef47a57a28c0384d 89 | -------------------------------------------------------------------------------- /slip-0048.md: -------------------------------------------------------------------------------- 1 | # SLIP-0048 : Deterministic Key Hierarchy for Graphene-based Networks 2 | 3 | ``` 4 | Number: SLIP-0048 5 | Title: Deterministic key hierarchy for Graphene-based networks 6 | Type: Standard 7 | Status: Active 8 | Authors: Fabian Schuh 9 | Created: 2016-10-18 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This SLIP defines the logical hierarchy for deterministic wallets using Graphene technology. 15 | It extends [BIP-0044](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) known from Bitcoin which should be read and understood before going into the details of this specification. 16 | 17 | ## Motivation 18 | 19 | The key derivation structure defined in BIP-0044/SLIP-0044 does not properly represent the possibilities available to Graphene based networks. For this reason, we defined this SLIP and provide a standard for hierarchies on those networks. 20 | 21 | ## Account Roles on Graphene 22 | 23 | Graphene-based blockchains (such as BitShares, Steem, Peerplays, MUSE, etc.) do not use the UTXO model. Instead, there are accounts registered on the blockchains that have a (modifiable) role scheme attached to each of them. The actual roles depend on the use case of the network but most of them constitute an `owner` and an `active` role among others. Usually, the only difference between `owner` and `active` role is that the `owner` can change the `owner` role, while the `active` cannot, and thus represents some kind of cold storage or super-admin roles. 24 | 25 | Technically, each role can consist of multiple (weighted) keys or other accounts to facilitate hierarchical weighted roles on the blockchain. 26 | 27 | Wallets are supposed to have at least one key installed that is associated with the account's owner role (i.e. the `owner` key) to allow recovery. 28 | 29 | The `memo` key is different in that it is **not** a roles but a single key that is assigned to an account. This key is used for private (encrypted) messaging to derive a shared secret between sender and receiver. 30 | 31 | ## Deterministic Key Hierarchy 32 | 33 | ``` 34 | m / purpose' / network' / role' / account-index' / key-index' 35 | ``` 36 | 37 | Each level has a special meaning, described in the chapters below. Apostrophe in the path indicates that BIP32 hardened derivation is used. 38 | 39 | ### Purpose 40 | 41 | Purpose is a constant set to 48' (or 0x80000030) following the BIP43 recommendation. It indicates that the subtree of this node is used according to this specification. 42 | 43 | Hardened derivation is used at this level. 44 | 45 | ### Network 46 | 47 | One master node (seed) can be used for unlimited number of independent keys which can be used in different networks such as BitShares, Steem, PeerPlays and others. However, sharing the same space for various networks has some disadvantages. 48 | 49 | This level creates a separate subtree for every network, avoiding reusing addresses across networks and improving privacy issues. 50 | 51 | `network`is a constant, set for each network. Developers may ask for registering unused number for their project. 52 | 53 | The list of already allocated networks is in the chapter "Registered networks" below. 54 | 55 | Hardened derivation is used at this level. 56 | 57 | ### Role 58 | 59 | Each account can be associated with its own keys. To distinguish different roles, a roles id is used to obtain a specific sub tree. Since each Graphene-based network can have it's own specific set of roles, the actually used role indices are provided in the section "Registered networks", below. 60 | 61 | Hardened derivation is used at this level. 62 | 63 | The Role comes prior to the Account index so that a role-specific parent key can be derived which allows to derive child keys that do not interfer with other roles. 64 | A simple use-case would be a mobile wallet app that does not want to expose owner keys but only has active keys available by going through the tree starting with: 65 | 66 | ``` 67 | m / purpose' / network' / [active] 68 | ``` 69 | 70 | ### Account-Index 71 | 72 | Since hierarchical key derivation can be used to obtain an infinite amount of keys, we allow users to store keys for an infinite amount of accounts by using account indices. This means that account-index 0, derives a subkey to obtain multiple keys associated with account *A*, while account-index 1 does the same for account *B*. Note that the public keys cannot be associated with each other unless a common parent node in the tree is published. 73 | 74 | Software needs to discover all used accounts after importing the seed from an external source. Such an algorithm is described in "Account discovery" chapter. 75 | 76 | Thus, software should prevent a update of an account with a specific key (see below) if a previous key does not have an account associated with it. 77 | 78 | ## Account discovery 79 | 80 | When the master seed is imported from an external source the software should start to discover the accounts in the following manner (for a specific role, e.g. `active`): 81 | 82 | * derive the first account's node (index = 0) 83 | * derive the child keys for each role (respect the gap limit) 84 | * use the blockchains API to obtain the account associated with one of this public keys 85 | * if the public key is not associated with any account, stop discovery 86 | * if there is an account associated with any of these key, increase the account index and go to step 1 87 | 88 | Depending on the blockchain's API and available resources, account discovery could be done with multiple accounts (resepct the gap limit) at once. With a gap limit of 5 for account's and a gap limit of 5 for keys, we would need to scan for 25 keys. Combined with bloom filtering, the amount of data could be reduced at the expense of a single step lookup. 89 | 90 | This algorithm is successful because software should disallow creation of new accounts if previous one has no associated account. 91 | 92 | ### Key-Index 93 | 94 | We want to be able to for example take an account's current role key and put it on a different device. 95 | If that device is compromised, we want the other (more secure) device to be able to generate the new generation of that posting key without further interaction. For this reason, each accounts-role leaf generates a new subtree of keys. This allows to keep the keys for other roles and merely update the role with the compromised keys. Other wallets with the same tree will still be able to access the accounts by deriving the new keys. 96 | 97 | ### Public Key gap limit 98 | 99 | Public Key gap limit is currently set to 5. If the software hits 5 unused public keys in a row, it expects there are no used accounts beyond this point and stops searching the public key chain. 100 | 101 | Wallet software should allow the advanced user to manually search beyond the gap limit of 5. 102 | 103 | ## Account Setup Procedure 104 | 105 | This paragraph describes how to *onboard* an existing account into this standard, e.g. for hardware wallets. Later it will be possible to create (and register) new accounts, given a funded account is already available through this specifications (account creation costs a fee on most networks). 106 | 107 | The procedure to onboard an account involves **two** transactions and works as follows: 108 | 109 | 1. The user requests an unused public key from the master (seed) node according to the specifications 110 | 2. The obtained public key is **added** to the existing account's **owner** role (full-weight) 111 | 3. This key is used for an `account_update` operation in order to replace the existing roles for sole access to the account by keys following this specification. 112 | 113 | The advantages of this procedure are: 114 | 115 | * This algorithm proves that it has the correct private key to obtain owner roles since this key is required to sign the `account_update` operation. 116 | * Optionally, alternative keys to specific operations (e.g. *posting* roles on Steem) can be added that do not follow the above specification, to allow for multi-signature schemes 117 | * Wallets following this specification can be used solely as coldstorage for the owner key while the active key could be held outside the wallet 118 | 119 | Disadvantages are: 120 | 121 | * The user needs to be educated about the roles, or 122 | * a simplified account roles setup scheme needs to be developed 123 | 124 | ## Registered networks 125 | 126 | Index | Network | Roles 127 | ---------------|-------------|--------------------------------------------------------- 128 | 0x00000000 | Steem | `0x0`: owner, `0x1`: active, `0x3`: memo, `0x4`: posting 129 | 0x00000001 | BitShares | `0x0`: owner, `0x1`: active, `0x3`: memo 130 | 0x00000002 | PeerPlays | `0x0`: owner, `0x1`: active, `0x3`: memo 131 | 0x00000003 | Muse | `0x0`: owner, `0x1`: active, `0x3`: memo 132 | 0x00000004 | EOS | `0x0`: owner, `0x1`: active 133 | 0x00000005 | FIBOS | `0x0`: owner, `0x1`: active 134 | 0x00000006 | ONE | `0x0`: owner, `0x1`: active 135 | 0x00000007 | SBC | `0x0`: owner, `0x1`: active 136 | 0x00000008 | YOYOW | `0x0`: owner, `0x1`: active, `0x3`: memo, `0x4`: secondary 137 | 0x00000009 | BOS | `0x0`: owner, `0x1`: active 138 | 0x0000000a | ONEGRAM | `0x0`: owner, `0x1`: active 139 | 0x0000000b | BRAVO | `0x0`: owner, `0x1`: active, `0x3`: memo, `0x4`: posting 140 | 0x0000000c | DECENT | `0x0`: owner, `0x1`: active, `0x3`: memo 141 | 0x0000000d | Hive | `0x0`: owner, `0x1`: active, `0x3`: memo, `0x4`: posting 142 | 143 | ## Examples 144 | 145 | Network | Role | Account-index | Key-Index | Path 146 | -----------|---------------|----------------|-----------|---------------------------- 147 | Steem | active | first | first | m / 48' / 0' / 1' / 0' / 0' 148 | BitShares | owner | forth | forth | m / 48' / 1' / 0' / 3' / 3' 149 | EOS | owner | first | first | m / 48' / 4' / 0' / 0' / 0' 150 | FIBOS | owner | first | first | m / 48' / 5' / 0' / 0' / 0' 151 | BOS | owner | first | first | m / 48' / 9' / 0' / 0' / 0' 152 | ONEGRAM | owner | first | first | m / 48' / 10' / 0' / 0' / 0' 153 | 154 | ## References 155 | 156 | * [BIP-0044: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) 157 | * [Graphene Wiki](https://github.com/cryptonomex/graphene/wiki) 158 | 159 | ## Updates 160 | 161 | 2017/09/07: In the hierarchy, the key role and the account index are swapped to allow separation of roles in sub-trees. 162 | -------------------------------------------------------------------------------- /slip-0032.md: -------------------------------------------------------------------------------- 1 | # SLIP-0032 : Extended serialization format for BIP-32 wallets 2 | 3 | ``` 4 | Number: SLIP-0032 5 | Title: Extended serialization format for BIP-32 wallets 6 | Type: Standard 7 | Status: Draft 8 | Authors: Pavol Rusnak 9 | Created: 2017-09-06 10 | ``` 11 | 12 | ## Abstract 13 | 14 | BIP-0032 already defines a serialization format for hierarchical deterministic 15 | keys. In this document we present extended version of the serialization 16 | format, which aims to overcome some limitations of the original proposal. 17 | 18 | ## Changes 19 | 20 | First modification is including full BIP-32 path of the exported node, so 21 | wallet can check whether the provided key was exported from expected part of 22 | the deterministic hierarchy. 23 | 24 | Second modification is removal of fingerprint field, which was barely used by 25 | wallets and introduces unnecessary extra computation steps during serialization 26 | of the key. Sometimes it is even not possible to compute the fingerprint at all 27 | (when the parent key is unknown). 28 | 29 | Last modification is the change from Base58 encoding to Bech32 encoding, which 30 | is more efficient in many areas. 31 | 32 | ## Serialization format 33 | 34 | Extended public and private keys are serialized as follows: 35 | 36 | * 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 derived keys, ... 37 | * 4 * depth bytes: serialized BIP-32 path; each entry is encoded as 32-bit unsigned integer, most significant byte first 38 | * 32 bytes: the chain code 39 | * 33 bytes: the public key or private key data (serP(K) for public keys, 0x00 || ser256(k) for private keys) 40 | 41 | This structure is encoded using Bech32 format described in BIP-0173. We will 42 | use 'xpub' human-readable part for extended public keys and 'xprv' for extended 43 | private keys. 44 | 45 | ## Test vectors 46 | 47 |
 48 | mnemonic = abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
 49 | 
 50 | m :
 51 | 
 52 | legacy_bip32_xprv = xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu
 53 | legacy_bip32_xpub = xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8
 54 | 
 55 | slip32_prv_hex    = 007923408dadd3c7b56eed15567707ae5e5dca089de972e07f3b860450e2a3b70e001837c1be8e2995ec11cda2b066151be2cfb48adf9e47b151d46adab3a21cdf67
 56 | slip32_pub_hex    = 007923408dadd3c7b56eed15567707ae5e5dca089de972e07f3b860450e2a3b70e03d902f35f560e0470c63313c7369168d9d7df2d49bf295fd9fb7cb109ccee0494
 57 | 
 58 | slip32_prv_bech32 = xprv1qpujxsyd4hfu0dtwa524vac84e09mjsgnh5h9crl8wrqg58z5wmsuqqcxlqmar3fjhkprndzkpnp2xlze76g4hu7g7c4r4r2m2e6y8xlvu566tn6
 59 | slip32_pub_bech32 = xpub1qpujxsyd4hfu0dtwa524vac84e09mjsgnh5h9crl8wrqg58z5wmsuq7eqte474swq3cvvvcncumfz6xe6l0j6jdl990an7mukyyuemsyjszuwypl
 60 | 
 61 | m/0 :
 62 | 
 63 | legacy_bip32_xprv = xprv9ukW2UsmeQP9NB14w61cimzwEKbUJxHCypMb1PpEafjCETz69a6tp8aYdMkHfz6U49Ut262f9MpGZkCna1zDhEfW2BGkSehvrxd5ueR4TBe
 64 | legacy_bip32_xpub = xpub68jrRzQfUmwSaf5Y37Yd5uwfnMRxiR14M3HBonDr91GB7GKEh7R9Mvu2UeCtbASfXZ9FdNo9FwFx6a37HNXUDiXVQFXuadXmevRBa3y7rL8
 65 | 
 66 | slip32_prv_hex    = 0100000000e0e6503ac057cf5dc76e0735e56dd44d193b2e9e271cc2d46bc759c99b021e3c00baa89a8bdd61c5e22b9f10601d8791c9f8fc4b2fa6df9d68d336f0eb03b06eb6
 67 | slip32_pub_hex    = 0100000000e0e6503ac057cf5dc76e0735e56dd44d193b2e9e271cc2d46bc759c99b021e3c0376bf533d4b15510fa9f4124b6e48616f07debcf2ef0cfb185cdc4a576450b475
 68 | 
 69 | slip32_prv_bech32 = xprv1qyqqqqqqurn9qwkq2l84m3mwqu672mw5f5vnkt57yuwv94rtcavunxczrc7qpw4gn29a6cw9ug4e7yrqrkrerj0cl39jlfkln45dxdhsavpmqm4krfqykk
 70 | slip32_pub_bech32 = xpub1qyqqqqqqurn9qwkq2l84m3mwqu672mw5f5vnkt57yuwv94rtcavunxczrc7qxa4l2v75k923p75lgyjtdeyxzmc8m6709mcvlvv9ehz22aj9pdr4m6lwmk
 71 | 
 72 | m/1 :
 73 | 
 74 | legacy_bip32_xprv = xprv9ukW2UsmeQP9PQFT4K5ZcUPAXZy7hZPqMAX94Q2rTNA5qRznspNy8q87j3hc5eWWS7hS7sGVpEiGbMHLqxubZFqAASWSBuyVDqE9jxqjD9E
 75 | legacy_bip32_xpub = xpub68jrRzQfUmwSbtKvALcZycKu5boc727giPSjrnSU1hh4iEKwRMhDgdSbaK3Ac8hngo2Fgbz9B5S4V1jbkR8ffjFLjTBWSvALDZPzTLqeMqb
 76 | 
 77 | slip32_prv_hex    = 01000000015c48917d6838b666aeb11eac7c4f98f807779b57c7522e38509719eeb1e7a59200c1beaff0c4db984670a40c69c2947b9d33cd7f6e749c67e1fcb5c6118dda1282
 78 | slip32_pub_hex    = 01000000015c48917d6838b666aeb11eac7c4f98f807779b57c7522e38509719eeb1e7a59202ea2649b3512b9a859ab658a85e2989a7ae39b2518877b2dc0f2b44b785d5788d
 79 | 
 80 | slip32_prv_bech32 = xprv1qyqqqqqpt3yfzltg8zmxdt43r6k8cnuclqrh0x6hcafzuwzsjuv7av085kfqpsd74lcvfkucgec2grrfc228h8fne4lkuayuvlsledwxzxxa5y5zefalyg
 81 | slip32_pub_bech32 = xpub1qyqqqqqpt3yfzltg8zmxdt43r6k8cnuclqrh0x6hcafzuwzsjuv7av085kfq963xfxe4z2u6skdtvk9gtc5cnfaw8xe9rzrhktwq726yk7za27ydw88adn
 82 | 
 83 | m/0' :
 84 | 
 85 | legacy_bip32_xprv = xprv9ukW2Usuz4v7Yd2EC4vNXaMckdsEdgBA9n7MQbqMJbW9FuHDWWjDwzEM2h6XmFnrzX7JVmfcNWMEVoRauU6hQpbokqPPNTbdycW9fHSPYyF
 86 | legacy_bip32_xpub = xpub68jrRzQopSUQm76hJ6TNtiJMJfhj38u1X12xCzExrw388hcN443UVnYpswdUkV7vPJ3KayiCdp3Q5E23s4wvkucohVTh7eSstJdBFyn2DMx
 87 | 
 88 | slip32_prv_hex    = 0180000000f1c03f5ff97108912fd56761d3fada8879e4173aba45f10da4bbd94b1c49716000c08cf331996482c06db3d259ff99be4bf7083824d53185e33191ee7ceb2bf96f
 89 | slip32_pub_hex    = 0180000000f1c03f5ff97108912fd56761d3fada8879e4173aba45f10da4bbd94b1c497160027f1d87730e460e921b382242911565bf93daf2081ed685b2edd1d01176b2c13c
 90 | 
 91 | slip32_prv_bech32 = xprv1qxqqqqqq78qr7hlewyyfzt74vasa87k63pu7g9e6hfzlzrdyh0v5k8zfw9sqpsyv7vcejeyzcpkm85jel7vmujlhpquzf4f3sh3nry0w0n4jh7t0jhc039
 92 | slip32_pub_bech32 = xpub1qxqqqqqq78qr7hlewyyfzt74vasa87k63pu7g9e6hfzlzrdyh0v5k8zfw9sqylcasaesu3swjgdnsgjzjy2kt0unmteqs8kkskewm5wsz9mt9sfuvlxj6p
 93 | 
 94 | m/1' :
 95 | 
 96 | legacy_bip32_xprv = xprv9ukW2Usuz4v7ZSQ9zPsP7jQkeP7MtjLzyyb9zfZ7uZc7Hr1Kf1FKQq1tM8edPHeB2fPBATtH7XYNAEmxtCWRNvP5qZkv4E3CXL3FvwPsBSm
 97 | legacy_bip32_xpub = xpub68jrRzQopSUQmvUd6RQPUsMVCQwrJC4rMCWko3xjTu96AeLUCYZZxdLNCSXBA3QhaZJ67AynQNCtfcBFemxfjzWHWLKbkVCFyHGjFHHgqeE
 98 | 
 99 | slip32_prv_hex    = 018000000143cc4bca59c666a5f79265148125802ed2cec46df1c5ca8e6a058dab525a73f1003ef02fc53000742891fc90458ba9edc8363d8f1f267e326b1078710c7db34de5
100 | slip32_pub_hex    = 018000000143cc4bca59c666a5f79265148125802ed2cec46df1c5ca8e6a058dab525a73f103b5184a526dac6abda3d8d54a541471ce83e8c2260d56706053e2780922319f5e
101 | 
102 | slip32_prv_bech32 = xprv1qxqqqqqpg0xyhjjecen2taujv52gzfvq9mfva3rd78zu4rn2qkx6k5j6w0csq0hs9lznqqr59zgleyz93w57mjpk8k837fn7xf43q7r3p37mxn095hysnx
103 | slip32_pub_bech32 = xpub1qxqqqqqpg0xyhjjecen2taujv52gzfvq9mfva3rd78zu4rn2qkx6k5j6w0cs8dgcfffxmtr2hk3a34222s28rn5rarpzvr2kwps98cncpy3rr867k5u83k
104 | 
105 | m/44'/0'/0' :
106 | 
107 | legacy_bip32_xprv = xprv9xpXFhFpqdQK3TmytPBqXtGSwS3DLjojFhTGht8gwAAii8py5X6pxeBnQ6ehJiyJ6nDjWGJfZ95WxByFXVkDxHXrqu53WCRGypk2ttuqncb
108 | legacy_bip32_xpub = xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj
109 | 
110 | slip32_prv_hex    = 038000002c80000000800000003da4bc190a2680111d31fadfdc905f2a7f6ce77c6f109919116f253d4344521900fe64af825b5b78554c33a28b23085fc082f691b3c712cc1d4e66e133297da87a
111 | slip32_pub_hex    = 038000002c80000000800000003da4bc190a2680111d31fadfdc905f2a7f6ce77c6f109919116f253d4344521903774c910fcf07fa96886ea794f0d5caed9afe30b44b83f7e213bb92930e7df4bd
112 | 
113 | slip32_prv_bech32 = xprv1qwqqqqpvsqqqqqyqqqqqq0dyhsvs5f5qzywnr7klmjg972nldnnhcmcsnyv3zme984p5g5seqrlxftuztddhs42vxw3gkgcgtlqg9a53k0r39nqafenwzvef0k585enml6g
114 | slip32_pub_bech32 = xpub1qwqqqqpvsqqqqqyqqqqqq0dyhsvs5f5qzywnr7klmjg972nldnnhcmcsnyv3zme984p5g5seqdm5eyg0eurl495gd6nefux4etke4l3sk39c8alzzwae9ycw0h6t6ltmssr
115 | 
116 | m/44'/0'/1' :
117 | 
118 | legacy_bip32_xprv = xprv9xpXFhFpqdQK5owUStFsuAiWUxYpLkvQn1QmVDumBKTvmmjkNEZgpMYoAaAftt3JVeDhRkvyLvrKathDToUMdz2FqRF7JNavF7uboJWArrw
119 | legacy_bip32_xpub = xpub6BosfCnifzxcJJ1wYuntGJfF2zPJkDeG9ELNHcKNjezuea4tumswN9sH1psMdSVqCMoJC21Bv8usSeqSP4Sp1tLzW7aY59fGn9GCYzx5UTo
120 | 
121 | slip32_prv_hex    = 038000002c80000000800000012971fa2db0ff5d69e166a406813aa3d9ed09c4adac2e0ce33523da8c5609f4f4008855dfda37fe663bffc0136618504e3cbd7d992134609cef6191c729339d5c65
122 | slip32_pub_hex    = 038000002c80000000800000012971fa2db0ff5d69e166a406813aa3d9ed09c4adac2e0ce33523da8c5609f4f4025d0261853d4c3a379160fb51d2f262ac64e65219139982c4e2180bcef1a233d9
123 | 
124 | slip32_prv_bech32 = xprv1qwqqqqpvsqqqqqyqqqqqz2t3lgkmpl6ad8skdfqxsya28k0dp8z2mtpwpn3n2g7633tqna85qzy9th76xllxvwllcqfkvxzsfc7t6lveyy6xp880vxguw2fnn4wx2mhtjy8
125 | slip32_pub_bech32 = xpub1qwqqqqpvsqqqqqyqqqqqz2t3lgkmpl6ad8skdfqxsya28k0dp8z2mtpwpn3n2g7633tqna85qfwsycv984xr5du3vra4r5hjv2kxfejjryfenqkyugvqhnh35geajlgxhp0
126 | 
127 | m/44'/2'/0' :
128 | 
129 | legacy_bip32_xprv = Ltpv7735AbcbmL1gbgDWj2ezvs59rh4RM1oTN2BKTKbfe3146FCPCNFbBBSWfuV9vCJNMXD9LuHpQnqVWpn2hbMhikqPdoGqbS3ptdPoNWEvvgR
130 | legacy_bip32_xpub = Ltub2YDQmP391UYeDYvLye9P1SuNJFkcRGN7SYHM8JMxaDnegcPTXHJ2BnYmvHnFnGPGKu2WMuCga6iZV3SDxDMGrRyMcrYEfSPhrpS1EPkC43E
131 | 
132 | slip32_prv_hex    = 038000002c8000000280000000869c5045e5fc789646babcd1961b101bc31e75fe50df8a585c79b05dca0ac75800983cd10d8d14160b10b9a4bb63207e9585054a3133619d57b78ea9d5aa3046d2
133 | slip32_pub_hex    = 038000002c8000000280000000869c5045e5fc789646babcd1961b101bc31e75fe50df8a585c79b05dca0ac7580340fe3b8e89165258bac0cb711613c618d1af63dc321a90b751d0697301441bcc
134 | 
135 | slip32_prv_bech32 = xprv1qwqqqqpvsqqqqq5qqqqqpp5u2pz7tlrcjert40x3jcd3qx7rre6lu5xl3fv9c7dsth9q436cqzvre5gd352pvzcshxjtkceq062c2p22xyekr82hk782n4d2xprdysp4gxc
136 | slip32_pub_bech32 = xpub1qwqqqqpvsqqqqq5qqqqqpp5u2pz7tlrcjert40x3jcd3qx7rre6lu5xl3fv9c7dsth9q436cqdq0uwuw3yt9yk96cr9hz9snccvdrtmrmsep4y9h28gxjucpgsducuj4f9r
137 | 
138 | m/49'/0'/0' :
139 | 
140 | legacy_bip32_xprv = yprvAHwhK6RbpuS3dgCYHM5jc2ZvEKd7Bi61u9FVhYMpgMSuZS613T1xxQeKTffhrHY79hZ5PsskBjcc6C2V7DrnsMsNaGDaWev3GLRQRgV7hxF
141 | legacy_bip32_xpub = ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP
142 | 
143 | slip32_prv_hex    = 038000003180000000800000006eaae365ae0e0a0aab84325cfe7cd76c3b909035f889e7d3f1b847a9a0797ecb00880d51752bda4190607e079588d3f644d96bfa03446bce93cddfda3c4a99c7e6
144 | slip32_pub_hex    = 038000003180000000800000006eaae365ae0e0a0aab84325cfe7cd76c3b909035f889e7d3f1b847a9a0797ecb02f1f347891b20f7568eae3ec9869fbfb67bcab6f358326f10ecc42356bd55939d
145 | 
146 | slip32_prv_bech32 = xprv1qwqqqqp3sqqqqqyqqqqqqm42udj6urs2p24cgvjule7dwmpmjzgrt7yfulflrwz84xs8jlktqzyq65t490dyryrq0cretzxn7ezdj6l6qdzxhn5neh0a50z2n8r7vumvllf
147 | slip32_pub_bech32 = xpub1qwqqqqp3sqqqqqyqqqqqqm42udj6urs2p24cgvjule7dwmpmjzgrt7yfulflrwz84xs8jlktqtclx3ufrvs0w45w4clvnp5lh7m8hj4k7dvrymcsanzzx44a2kfe6xynfgh
148 | 
149 | m/49'/2'/0' :
150 | 
151 | legacy_bip32_xprv = Mtpv7RooeEQDUitupgpJcxZnfDwvq8hC24R7GAiscrqFhHHhit96vCNY7yudJgrM841dMbiRUQceC12566XAHHC8Rd1BtnBdokq9tmF7jLLvUdh
152 | legacy_bip32_xpub = Mtub2rz9F1pkisRsSZX8sa4Ajon9GhPP6JymLgpuHqbYdU5JKFLBF7Qy8b1tZ3dccj2fefrAxfrPdVkpCxuWn3g72UctH2bvJRkp6iFmp8aLeRZ
153 | 
154 | slip32_prv_hex    = 0380000031800000028000000067b7e1dc5c70a93504218ccf40c47ad46d4a9c858196376ce0e853aca7be049800cf222cc2e097049fe2ca76626c19c7e7a3ef971b1f64195758ab3c832463fcf4
155 | slip32_pub_hex    = 0380000031800000028000000067b7e1dc5c70a93504218ccf40c47ad46d4a9c858196376ce0e853aca7be049802b07388bd2edaba3c0a2c0856716fd7c9965d212fb2736f7b925f57d922b10ace
156 | 
157 | slip32_prv_bech32 = xprv1qwqqqqp3sqqqqq5qqqqqqeahu8w9cu9fx5zzrrx0grz844rdf2wgtqvkxakwp6zn4jnmupycqr8jytxzuztsf8lzefmxymqecln68muhrv0kgx2htz4neqeyv070gg6dcn7
158 | slip32_pub_bech32 = xpub1qwqqqqp3sqqqqq5qqqqqqeahu8w9cu9fx5zzrrx0grz844rdf2wgtqvkxakwp6zn4jnmupycq2c88z9a9mdt50q29sy9vut06lyevhfp97e8xmmmjf040kfzky9vu2pu92u
159 | 
160 | m/84'/0'/0' :
161 | 
162 | legacy_bip32_xprv = zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE
163 | legacy_bip32_xpub = zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs
164 | 
165 | slip32_prv_hex    = 038000005480000000800000004a53a0ab21b9dc95869c4e92a161194e03c0ef3ff5014ac692f433c4765490fc00e14f274d16ca0d91031b98b162618061d03930fa381af6d4caf44b01819ab6d4
166 | slip32_pub_hex    = 038000005480000000800000004a53a0ab21b9dc95869c4e92a161194e03c0ef3ff5014ac692f433c4765490fc02707a62fdacc26ea9b63b1c197906f56ee0180d0bcf1966e1a2da34f5f3a09a9b
167 | 
168 | slip32_prv_bech32 = xprv1qwqqqqz5sqqqqqyqqqqqqjjn5z4jrwwujkrfcn5j59s3jnsrcrhnlagpftrf9apnc3m9fy8uqrs57f6dzm9qmygrrwvtzcnpspsaqwfslgup4ak5et6ykqvpn2mdggeaxrp
169 | slip32_pub_bech32 = xpub1qwqqqqz5sqqqqqyqqqqqqjjn5z4jrwwujkrfcn5j59s3jnsrcrhnlagpftrf9apnc3m9fy8uqfc85cha4npxa2dk8vwpj7gx74hwqxqdp083jehp5tdrfa0n5zdfkg3lp00
170 | 
171 | 172 | ## References 173 | 174 | * [BIP-0032: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 175 | * [BIP-0173: Base32 address format for native v0-16 witness outputs](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) 176 | -------------------------------------------------------------------------------- /slip-0039/wordlist.txt: -------------------------------------------------------------------------------- 1 | academic 2 | acid 3 | acne 4 | acquire 5 | acrobat 6 | activity 7 | actress 8 | adapt 9 | adequate 10 | adjust 11 | admit 12 | adorn 13 | adult 14 | advance 15 | advocate 16 | afraid 17 | again 18 | agency 19 | agree 20 | aide 21 | aircraft 22 | airline 23 | airport 24 | ajar 25 | alarm 26 | album 27 | alcohol 28 | alien 29 | alive 30 | alpha 31 | already 32 | alto 33 | aluminum 34 | always 35 | amazing 36 | ambition 37 | amount 38 | amuse 39 | analysis 40 | anatomy 41 | ancestor 42 | ancient 43 | angel 44 | angry 45 | animal 46 | answer 47 | antenna 48 | anxiety 49 | apart 50 | aquatic 51 | arcade 52 | arena 53 | argue 54 | armed 55 | artist 56 | artwork 57 | aspect 58 | auction 59 | august 60 | aunt 61 | average 62 | aviation 63 | avoid 64 | award 65 | away 66 | axis 67 | axle 68 | beam 69 | beard 70 | beaver 71 | become 72 | bedroom 73 | behavior 74 | being 75 | believe 76 | belong 77 | benefit 78 | best 79 | beyond 80 | bike 81 | biology 82 | birthday 83 | bishop 84 | black 85 | blanket 86 | blessing 87 | blimp 88 | blind 89 | blue 90 | body 91 | bolt 92 | boring 93 | born 94 | both 95 | boundary 96 | bracelet 97 | branch 98 | brave 99 | breathe 100 | briefing 101 | broken 102 | brother 103 | browser 104 | bucket 105 | budget 106 | building 107 | bulb 108 | bulge 109 | bumpy 110 | bundle 111 | burden 112 | burning 113 | busy 114 | buyer 115 | cage 116 | calcium 117 | camera 118 | campus 119 | canyon 120 | capacity 121 | capital 122 | capture 123 | carbon 124 | cards 125 | careful 126 | cargo 127 | carpet 128 | carve 129 | category 130 | cause 131 | ceiling 132 | center 133 | ceramic 134 | champion 135 | change 136 | charity 137 | check 138 | chemical 139 | chest 140 | chew 141 | chubby 142 | cinema 143 | civil 144 | class 145 | clay 146 | cleanup 147 | client 148 | climate 149 | clinic 150 | clock 151 | clogs 152 | closet 153 | clothes 154 | club 155 | cluster 156 | coal 157 | coastal 158 | coding 159 | column 160 | company 161 | corner 162 | costume 163 | counter 164 | course 165 | cover 166 | cowboy 167 | cradle 168 | craft 169 | crazy 170 | credit 171 | cricket 172 | criminal 173 | crisis 174 | critical 175 | crowd 176 | crucial 177 | crunch 178 | crush 179 | crystal 180 | cubic 181 | cultural 182 | curious 183 | curly 184 | custody 185 | cylinder 186 | daisy 187 | damage 188 | dance 189 | darkness 190 | database 191 | daughter 192 | deadline 193 | deal 194 | debris 195 | debut 196 | decent 197 | decision 198 | declare 199 | decorate 200 | decrease 201 | deliver 202 | demand 203 | density 204 | deny 205 | depart 206 | depend 207 | depict 208 | deploy 209 | describe 210 | desert 211 | desire 212 | desktop 213 | destroy 214 | detailed 215 | detect 216 | device 217 | devote 218 | diagnose 219 | dictate 220 | diet 221 | dilemma 222 | diminish 223 | dining 224 | diploma 225 | disaster 226 | discuss 227 | disease 228 | dish 229 | dismiss 230 | display 231 | distance 232 | dive 233 | divorce 234 | document 235 | domain 236 | domestic 237 | dominant 238 | dough 239 | downtown 240 | dragon 241 | dramatic 242 | dream 243 | dress 244 | drift 245 | drink 246 | drove 247 | drug 248 | dryer 249 | duckling 250 | duke 251 | duration 252 | dwarf 253 | dynamic 254 | early 255 | earth 256 | easel 257 | easy 258 | echo 259 | eclipse 260 | ecology 261 | edge 262 | editor 263 | educate 264 | either 265 | elbow 266 | elder 267 | election 268 | elegant 269 | element 270 | elephant 271 | elevator 272 | elite 273 | else 274 | email 275 | emerald 276 | emission 277 | emperor 278 | emphasis 279 | employer 280 | empty 281 | ending 282 | endless 283 | endorse 284 | enemy 285 | energy 286 | enforce 287 | engage 288 | enjoy 289 | enlarge 290 | entrance 291 | envelope 292 | envy 293 | epidemic 294 | episode 295 | equation 296 | equip 297 | eraser 298 | erode 299 | escape 300 | estate 301 | estimate 302 | evaluate 303 | evening 304 | evidence 305 | evil 306 | evoke 307 | exact 308 | example 309 | exceed 310 | exchange 311 | exclude 312 | excuse 313 | execute 314 | exercise 315 | exhaust 316 | exotic 317 | expand 318 | expect 319 | explain 320 | express 321 | extend 322 | extra 323 | eyebrow 324 | facility 325 | fact 326 | failure 327 | faint 328 | fake 329 | false 330 | family 331 | famous 332 | fancy 333 | fangs 334 | fantasy 335 | fatal 336 | fatigue 337 | favorite 338 | fawn 339 | fiber 340 | fiction 341 | filter 342 | finance 343 | findings 344 | finger 345 | firefly 346 | firm 347 | fiscal 348 | fishing 349 | fitness 350 | flame 351 | flash 352 | flavor 353 | flea 354 | flexible 355 | flip 356 | float 357 | floral 358 | fluff 359 | focus 360 | forbid 361 | force 362 | forecast 363 | forget 364 | formal 365 | fortune 366 | forward 367 | founder 368 | fraction 369 | fragment 370 | frequent 371 | freshman 372 | friar 373 | fridge 374 | friendly 375 | frost 376 | froth 377 | frozen 378 | fumes 379 | funding 380 | furl 381 | fused 382 | galaxy 383 | game 384 | garbage 385 | garden 386 | garlic 387 | gasoline 388 | gather 389 | general 390 | genius 391 | genre 392 | genuine 393 | geology 394 | gesture 395 | glad 396 | glance 397 | glasses 398 | glen 399 | glimpse 400 | goat 401 | golden 402 | graduate 403 | grant 404 | grasp 405 | gravity 406 | gray 407 | greatest 408 | grief 409 | grill 410 | grin 411 | grocery 412 | gross 413 | group 414 | grownup 415 | grumpy 416 | guard 417 | guest 418 | guilt 419 | guitar 420 | gums 421 | hairy 422 | hamster 423 | hand 424 | hanger 425 | harvest 426 | have 427 | havoc 428 | hawk 429 | hazard 430 | headset 431 | health 432 | hearing 433 | heat 434 | helpful 435 | herald 436 | herd 437 | hesitate 438 | hobo 439 | holiday 440 | holy 441 | home 442 | hormone 443 | hospital 444 | hour 445 | huge 446 | human 447 | humidity 448 | hunting 449 | husband 450 | hush 451 | husky 452 | hybrid 453 | idea 454 | identify 455 | idle 456 | image 457 | impact 458 | imply 459 | improve 460 | impulse 461 | include 462 | income 463 | increase 464 | index 465 | indicate 466 | industry 467 | infant 468 | inform 469 | inherit 470 | injury 471 | inmate 472 | insect 473 | inside 474 | install 475 | intend 476 | intimate 477 | invasion 478 | involve 479 | iris 480 | island 481 | isolate 482 | item 483 | ivory 484 | jacket 485 | jerky 486 | jewelry 487 | join 488 | judicial 489 | juice 490 | jump 491 | junction 492 | junior 493 | junk 494 | jury 495 | justice 496 | kernel 497 | keyboard 498 | kidney 499 | kind 500 | kitchen 501 | knife 502 | knit 503 | laden 504 | ladle 505 | ladybug 506 | lair 507 | lamp 508 | language 509 | large 510 | laser 511 | laundry 512 | lawsuit 513 | leader 514 | leaf 515 | learn 516 | leaves 517 | lecture 518 | legal 519 | legend 520 | legs 521 | lend 522 | length 523 | level 524 | liberty 525 | library 526 | license 527 | lift 528 | likely 529 | lilac 530 | lily 531 | lips 532 | liquid 533 | listen 534 | literary 535 | living 536 | lizard 537 | loan 538 | lobe 539 | location 540 | losing 541 | loud 542 | loyalty 543 | luck 544 | lunar 545 | lunch 546 | lungs 547 | luxury 548 | lying 549 | lyrics 550 | machine 551 | magazine 552 | maiden 553 | mailman 554 | main 555 | makeup 556 | making 557 | mama 558 | manager 559 | mandate 560 | mansion 561 | manual 562 | marathon 563 | march 564 | market 565 | marvel 566 | mason 567 | material 568 | math 569 | maximum 570 | mayor 571 | meaning 572 | medal 573 | medical 574 | member 575 | memory 576 | mental 577 | merchant 578 | merit 579 | method 580 | metric 581 | midst 582 | mild 583 | military 584 | mineral 585 | minister 586 | miracle 587 | mixed 588 | mixture 589 | mobile 590 | modern 591 | modify 592 | moisture 593 | moment 594 | morning 595 | mortgage 596 | mother 597 | mountain 598 | mouse 599 | move 600 | much 601 | mule 602 | multiple 603 | muscle 604 | museum 605 | music 606 | mustang 607 | nail 608 | national 609 | necklace 610 | negative 611 | nervous 612 | network 613 | news 614 | nuclear 615 | numb 616 | numerous 617 | nylon 618 | oasis 619 | obesity 620 | object 621 | observe 622 | obtain 623 | ocean 624 | often 625 | olympic 626 | omit 627 | oral 628 | orange 629 | orbit 630 | order 631 | ordinary 632 | organize 633 | ounce 634 | oven 635 | overall 636 | owner 637 | paces 638 | pacific 639 | package 640 | paid 641 | painting 642 | pajamas 643 | pancake 644 | pants 645 | papa 646 | paper 647 | parcel 648 | parking 649 | party 650 | patent 651 | patrol 652 | payment 653 | payroll 654 | peaceful 655 | peanut 656 | peasant 657 | pecan 658 | penalty 659 | pencil 660 | percent 661 | perfect 662 | permit 663 | petition 664 | phantom 665 | pharmacy 666 | photo 667 | phrase 668 | physics 669 | pickup 670 | picture 671 | piece 672 | pile 673 | pink 674 | pipeline 675 | pistol 676 | pitch 677 | plains 678 | plan 679 | plastic 680 | platform 681 | playoff 682 | pleasure 683 | plot 684 | plunge 685 | practice 686 | prayer 687 | preach 688 | predator 689 | pregnant 690 | premium 691 | prepare 692 | presence 693 | prevent 694 | priest 695 | primary 696 | priority 697 | prisoner 698 | privacy 699 | prize 700 | problem 701 | process 702 | profile 703 | program 704 | promise 705 | prospect 706 | provide 707 | prune 708 | public 709 | pulse 710 | pumps 711 | punish 712 | puny 713 | pupal 714 | purchase 715 | purple 716 | python 717 | quantity 718 | quarter 719 | quick 720 | quiet 721 | race 722 | racism 723 | radar 724 | railroad 725 | rainbow 726 | raisin 727 | random 728 | ranked 729 | rapids 730 | raspy 731 | reaction 732 | realize 733 | rebound 734 | rebuild 735 | recall 736 | receiver 737 | recover 738 | regret 739 | regular 740 | reject 741 | relate 742 | remember 743 | remind 744 | remove 745 | render 746 | repair 747 | repeat 748 | replace 749 | require 750 | rescue 751 | research 752 | resident 753 | response 754 | result 755 | retailer 756 | retreat 757 | reunion 758 | revenue 759 | review 760 | reward 761 | rhyme 762 | rhythm 763 | rich 764 | rival 765 | river 766 | robin 767 | rocky 768 | romantic 769 | romp 770 | roster 771 | round 772 | royal 773 | ruin 774 | ruler 775 | rumor 776 | sack 777 | safari 778 | salary 779 | salon 780 | salt 781 | satisfy 782 | satoshi 783 | saver 784 | says 785 | scandal 786 | scared 787 | scatter 788 | scene 789 | scholar 790 | science 791 | scout 792 | scramble 793 | screw 794 | script 795 | scroll 796 | seafood 797 | season 798 | secret 799 | security 800 | segment 801 | senior 802 | shadow 803 | shaft 804 | shame 805 | shaped 806 | sharp 807 | shelter 808 | sheriff 809 | short 810 | should 811 | shrimp 812 | sidewalk 813 | silent 814 | silver 815 | similar 816 | simple 817 | single 818 | sister 819 | skin 820 | skunk 821 | slap 822 | slavery 823 | sled 824 | slice 825 | slim 826 | slow 827 | slush 828 | smart 829 | smear 830 | smell 831 | smirk 832 | smith 833 | smoking 834 | smug 835 | snake 836 | snapshot 837 | sniff 838 | society 839 | software 840 | soldier 841 | solution 842 | soul 843 | source 844 | space 845 | spark 846 | speak 847 | species 848 | spelling 849 | spend 850 | spew 851 | spider 852 | spill 853 | spine 854 | spirit 855 | spit 856 | spray 857 | sprinkle 858 | square 859 | squeeze 860 | stadium 861 | staff 862 | standard 863 | starting 864 | station 865 | stay 866 | steady 867 | step 868 | stick 869 | stilt 870 | story 871 | strategy 872 | strike 873 | style 874 | subject 875 | submit 876 | sugar 877 | suitable 878 | sunlight 879 | superior 880 | surface 881 | surprise 882 | survive 883 | sweater 884 | swimming 885 | swing 886 | switch 887 | symbolic 888 | sympathy 889 | syndrome 890 | system 891 | tackle 892 | tactics 893 | tadpole 894 | talent 895 | task 896 | taste 897 | taught 898 | taxi 899 | teacher 900 | teammate 901 | teaspoon 902 | temple 903 | tenant 904 | tendency 905 | tension 906 | terminal 907 | testify 908 | texture 909 | thank 910 | that 911 | theater 912 | theory 913 | therapy 914 | thorn 915 | threaten 916 | thumb 917 | thunder 918 | ticket 919 | tidy 920 | timber 921 | timely 922 | ting 923 | tofu 924 | together 925 | tolerate 926 | total 927 | toxic 928 | tracks 929 | traffic 930 | training 931 | transfer 932 | trash 933 | traveler 934 | treat 935 | trend 936 | trial 937 | tricycle 938 | trip 939 | triumph 940 | trouble 941 | true 942 | trust 943 | twice 944 | twin 945 | type 946 | typical 947 | ugly 948 | ultimate 949 | umbrella 950 | uncover 951 | undergo 952 | unfair 953 | unfold 954 | unhappy 955 | union 956 | universe 957 | unkind 958 | unknown 959 | unusual 960 | unwrap 961 | upgrade 962 | upstairs 963 | username 964 | usher 965 | usual 966 | valid 967 | valuable 968 | vampire 969 | vanish 970 | various 971 | vegan 972 | velvet 973 | venture 974 | verdict 975 | verify 976 | very 977 | veteran 978 | vexed 979 | victim 980 | video 981 | view 982 | vintage 983 | violence 984 | viral 985 | visitor 986 | visual 987 | vitamins 988 | vocal 989 | voice 990 | volume 991 | voter 992 | voting 993 | walnut 994 | warmth 995 | warn 996 | watch 997 | wavy 998 | wealthy 999 | weapon 1000 | webcam 1001 | welcome 1002 | welfare 1003 | western 1004 | width 1005 | wildlife 1006 | window 1007 | wine 1008 | wireless 1009 | wisdom 1010 | withdraw 1011 | wits 1012 | wolf 1013 | woman 1014 | work 1015 | worthy 1016 | wrap 1017 | wrist 1018 | writing 1019 | wrote 1020 | year 1021 | yelp 1022 | yield 1023 | yoga 1024 | zero 1025 | -------------------------------------------------------------------------------- /slip-0022.md: -------------------------------------------------------------------------------- 1 | # SLIP-0022 : FIDO2 credential ID format for HD wallets 2 | 3 | ``` 4 | Number: SLIP-0022 5 | Title: FIDO2 credential ID format for HD wallets 6 | Type: Standard 7 | Status: Final 8 | Authors: Andrew R. Kozlik 9 | Pavol Rusnak 10 | Ondrej Vejpustek 11 | Created: 2019-07-19 12 | ``` 13 | 14 | ## Abstract 15 | 16 | This document describes an interoperable format for FIDO2 credential IDs for use in hierarchical deterministic wallets. 17 | 18 | ## Motivation 19 | 20 | A FIDO2 credential ID is a probabilistically-unique byte sequence identifying a public key credential. It is generated by the authenticator during registration and stored by the relying party and optionally by the authenticator itself. One way to generate a credential ID is to encrypt all credential data so that only its managing authenticator can decrypt it. This kind of credential ID allows the authenticator to be nearly stateless, by having the relying party store any necessary state. Currently there is no standardized way of formatting the credential data into this kind of credential ID. This specification defines a format for credential IDs designed for use in hierarchical deterministic wallets, which are distinctive in that they derive a hierarchy of cryptographic keys from a single master secret, such as that defined in [SLIP-0039](https://github.com/satoshilabs/slips/blob/master/slip-0039.md) or the binary seed defined in [BIP-0039](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki). This format may also be used for U2F key handles. 21 | 22 | ## Credential ID format 23 | 24 | A SLIP-0022 credential ID is a byte string between 33 and 65535 bytes in length of the following form: 25 | 26 | Version | Initialization vector | Encrypted credential data | Authentication tag 27 | --------|-----------------------|---------------------------|------------------- 28 | 4 bytes | 12 bytes | variable length | 16 bytes 29 | 30 | The version is the byte string "`\xf1\xd0\x02\x00`" in case of FIDO2 credential IDs and "`\xf1\xd0\x01\x01`" in case of U2F key handles. The initialization vector, which is used as input to the Chacha20Poly1305 cipher, is generated randomly for each new credential ID. The Poly1305 authentication tag is used to verify that the credential ID belongs to the authenticator. 31 | 32 | ## Credential data encoding 33 | 34 | Credential data members are encoded using a [CBOR](https://tools.ietf.org/html/rfc7049) map (CBOR major type 5) with keys of unsigned integer type, similar to how CTAP2 command parameters and response members are encoded. The CBOR map must be encoded using the definite length variant. Some members are optional, therefore the length of the credential data map may vary. 35 | 36 | The map keys and value types are specified below: 37 | 38 | Member name | Key | Value type | Required | Definition 39 | ----------------|-----|---------------------------------------|-----------------------------|------------------------- 40 | rpId | 1 | Text string (CBOR major type 3). | Required for FIDO2. | Relying party identifier. The "id" member of the rp parameter from the authenticatorMakeCredential request. 41 | rpName | 2 | Text string (CBOR major type 3). | Optional. | Relying party name. The "name" member of the rp parameter from the authenticatorMakeCredential request. 42 | userId | 3 | Byte string (CBOR major type 2). | Required for FIDO2. | User account ID. The "id" member of the user parameter from the authenticatorMakeCredential request. 43 | userName | 4 | Text string (CBOR major type 3). | Optional. | User account name. The "name" member of the user parameter from the authenticatorMakeCredential request. 44 | userDisplayName | 5 | Text string (CBOR major type 3). | Optional. | User account display name. The "displayName" member of the user parameter from the authenticatorMakeCredential request. In case of U2F the user may be prompted to enter a custom display name during registration. 45 | creationTime | 6 | Unsigned integer (CBOR major type 0). | Required for FIDO2. | Any value which allows credentials to be sorted by the time of their creation, such as the UNIX timestamp or the value of an incremental counter at the moment of creation. 46 | hmacSecret | 7 | Boolean (CBOR simple value 20 or 21). | Optional. False by default. | Indicates whether the credential was created with the hmac-secret extension set to true. 47 | useSignCount | 8 | Boolean (CBOR simple value 20 or 21). | Optional. False by default for FIDO2. Absent for U2F. | If false, all operations with the credential must use zero as the signature counter value. If true, the credential must use a signature counter which is incremented for each successful authenticatorGetAssertion operation. 48 | algorithm | 9 | Integer (CBOR major type 0 or 1) | Required if the "curve" field is present, otherwise optional. | The COSE identifier of the algorithm to be used for generating assertion signatures, as specified in the IANA COSE Algorithms Registry [IANA-COSE-ALGS-REG](https://www.iana.org/assignments/cose/cose.xhtml#algorithms). 49 | curve | 10 | Integer (CBOR major type 0 or 1) | Required if the "algorithm" field specifies an elliptic curve signature algorithm. | The COSE identifier of the elliptic curve to be used for generating assertion signatures, as specified in the IANA COSE Elliptic Curves Registry [IANA-COSE-EC-REG](https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves). 50 | 51 | If the "algorithm" field is not present, then the algorithm defaults to ES256 (-7) and the curve defaults to P-256 (1). 52 | 53 | Credential data MUST be encoded using the CTAP2 canonical CBOR encoding form as specified in [Section 6](https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#message-encoding) of the FIDO Client to Authenticator Protocol (CTAP) v2.0. 54 | 55 | ### Example of credential data encoding 56 | 57 | A credential data object in CBOR diagnostic notation: 58 | 59 | ``` 60 | credentialData = { 61 | 1: "example.com", 62 | 3: h'3082019330820138A0030201023082019330820138A003020102308201933082', 63 | 4: "johnpsmith@example.com", 64 | 6: 2, 65 | 7: true 66 | }; 67 | ``` 68 | 69 | would be CBOR encoded as follows: 70 | 71 | ``` 72 | a5 # map(5) 73 | 01 # unsigned(1) - rpId 74 | 6b # text(11) 75 | 6578616d706c652e636f6d # "example.com" 76 | 03 # unsigned(3) - userId 77 | 58 20 # bytes(32) 78 | 3082019330820138a003020102 # userid 79 | 3082019330820138a003020102 # ... 80 | 308201933082 # ... 81 | 04 # unsigned(4) - userName 82 | 76 # text(22) 83 | 6a6f686e70736d697468406578616d # "johnpsmith@example.com" 84 | 706c652e636f6d # ... 85 | 06 # unsigned(6) - creationTime 86 | 02 # unsigned(2) - the second credential created 87 | # with this authenticator 88 | 07 # unsigned(7) - hmacSecret 89 | f5 # primitive(21) - true 90 | ``` 91 | 92 | ## Encryption 93 | 94 | The CBOR encoded credential data is encrypted using Chacha20Poly1305 as defined in [RFC 8439](https://tools.ietf.org/html/rfc8439). In case of FIDO2 the SHA-256 hash of the rpId is used as the AAD input to the cipher. In case of U2F the application parameter (SHA-256 hash of the UTF-8 encoding of the application identity) is used as the AAD input to the cipher. 95 | 96 | The encryption key *k* is the same for all credential IDs of the same version which are generated by an authenticator with a given master secret. The key is derived from the master secret using the [SLIP-0021](https://github.com/satoshilabs/slips/blob/master/slip-0021.md) method for hierarchical derivation of symmetric keys as: 97 | 98 | ``` 99 | k = Key(m/"SLIP-0022"/version/"Encryption key") 100 | ``` 101 | 102 | where *version* is the first four bytes of the credential ID, for example "`\xf1\xd0\x02\x00`" in case of FIDO2 credential IDs. 103 | 104 | ## Derivation of the credential key pair 105 | 106 | The credential key pair used for generating assertion signatures is derived from a master secret and from the version and authentication tag of the credential ID using the [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) key derivation scheme. The key path is computed from the authentication tag by splitting it into four 4-byte values A, B, C and D which are interpreted as 32-bit integers in big-endian byte order. The highest bit in each integer is set and the key path is: 107 | 108 | ``` 109 | m/10022'/version'/A'/B'/C'/D' 110 | ``` 111 | 112 | where *version* is the first four bytes of the credential ID interpreted as a 32-bit integer in big-endian byte order, for example "0xf1d00200" in case of FIDO2 credential IDs. 113 | 114 | ## Derivation of hmac-secret CredRandom 115 | 116 | The CredRandom value used in the hmac-secret extension is derived from the master secret and the credential ID using the SLIP-0021 method for hierarchical derivation of symmetric keys as: 117 | 118 | ``` 119 | CredRandom = Key(m/"SLIP-0022"/version/"hmac-secret"/credentialId) 120 | ``` 121 | 122 | where *version* is the first four bytes of the credential ID. 123 | 124 | ## Signature counter 125 | 126 | The purpose of the signature counter is to aid relying parties in detecting cloned authenticators. Hierarchical deterministic wallets use a master secret, which can be backed-up and used for device recovery or legitimately used to create a clone of the device. Implementation of a signature counter impedes these use cases. Fortunately, FIDO2 allows authenticators to choose whether a credential will or will not use a signature counter. In the latter case the value of the signature counter remains constant at zero in all authenticatorMakeCredential responses and authenticatorGetAssertion responses. It is therefore recommended that authenticators do not create FIDO2 credentials with the "useSignCount" field set to true, unless required by the relying party. 127 | 128 | The above does not apply to U2F key handles, because the U2F protocol requires the implementation of a signature counter. In case of U2F key handles the "useSignCount" field MUST NOT be present. 129 | 130 | ## Example 131 | 132 | Unless stated otherwise, the values given below are encoded as strings containing two hexadecimal digits for each byte. 133 | 134 | The following is an example of a credential ID and the corresponding keys belonging to an authenticator with the master secret `S`. The credential data stored in the ID is the same as that given in the previous example: 135 | 136 | ``` 137 | credentialId = "f1d0020013e65c865634ad8abddf7a66df56ae7d8c3afd356f76426801508b2e579bcb3496fe6396a6002e3cd6d80f6359dfa9961e24c544bfc2f26acec1b8d878ba56727e1f6a7b5176c607552aea63a5abe5d826d69fab3063edfa0201d9a51013d69eddb2eff37acdd5963f" 138 | ``` 139 | 140 | ``` 141 | S = "c76c4ac4f4e4a00d6b274d5c39c700bb4a7ddc04fbc6f78e85ca75007b5b495f74a9043eeb77bdd53aa6fc3a0e31462270316fa04b8c19114c8798706cd02ac8" 142 | ``` 143 | 144 | Note that `S` is the binary seed obtained from the BIP-0039 mnemonic "all all all all all all all all all all all all" with an empty passphrase. 145 | 146 | Credential data encryption key: 147 | 148 | ``` 149 | k = "5b60f6c30e5ef87a5f6756242c98f487da0ca7c173282737660e7bc320fad6cf" 150 | ``` 151 | 152 | Credential key pair, the private key is encoded as an integer in base 10: 153 | 154 | ``` 155 | privateKey = 17028406872725666093318073001284158176462610154049610120643103153631976435873 156 | 157 | publicKey = "0451f0d4c307bc737c90ac605c6279f7d01e451798aa7b74df550fdb43a7760c7c02b5107fef42094d00f52a9b1e90afb90e1b9decbf15a6f13d4f882de857e2f4" 158 | ``` 159 | 160 | CredRandom value used in the hmac-secret extension: 161 | 162 | ``` 163 | CredRandom = "36a9b5d71c13ed54594474b54073af1fb03ea91cd056588909dae43ae2f35dbf" 164 | ``` 165 | 166 | ## Design rationale 167 | 168 | ### Choice of encoding 169 | 170 | CBOR encoding is used for serialization throughout the CTAP2 protocol. Therefore any authenticator supporting FIDO2 must support CBOR, making it the natural choice for encoding credential data. Encoding the data as a map allows easy handling of optional members, deprecating old members and introducing new members. 171 | 172 | ### Data encryption and authentication 173 | 174 | Generally the data members contained in the credential ID are stored alongside the credential ID or are transmitted on the same channel. Therefore, there does not appear to be a strong reason to encrypt the credential ID content. However, encrypting it allows the credential ID to be separated from the account information so that it is meaningless in isolation. Furthermore, in the future new data members requiring confidentiality may need to be added. In that case it is easier to manage encryption of the entire credential data map rather than its individual members. 175 | 176 | The random 96-bit initialization vector ensures that even if a user were to generate 232 credentials, then the likelihood of a collision occurring would be below 2−32. Since every credential generation requires user consent, this length provides a sufficient guarantee of IV uniqueness. 177 | 178 | The authentication tag is required to prevent an attacker from tampering with credential data and to avoid DOS attacks. 179 | 180 | According to the Web Authentication specification the RP ID is provided by the client to the authenticator for all operations, and the authenticator ensures that credentials created by a relying party can only be used in operations requested by the same RP ID. Using the RP ID as AAD input to the cipher enforces this requirement. 181 | 182 | ### Key pair derivation 183 | 184 | The rationale behind using the authentication tag for the SLIP-0010 key path is as follows: 185 | 186 | * The key path is not a confidential piece of information so it does not need to be encrypted or derived with the knowledge of a secret key. 187 | * The key path should depend on the credential information and on the relying party identifier, which is always provided as AAD when computing the authentication tag. 188 | * There should be an element of randomness so that different keys are generated even if the credential information is the same. Consider for example a relying party which insists on rotating the authentication key every three months and keeps track of old keys. The randomness is ensured by the fact that the IV is generated randomly. 189 | * Key path collisions should be near impossible to ensure unlinkability of various online identities of the same user. The likelihood of a collision occurring between authentication tags is even smaller than in the case of initialization vectors. 190 | 191 | ## References 192 | 193 | * [Web Authentication](https://www.w3.org/TR/webauthn/): An API for accessing Public Key Credentials Level 1, W3C Recommendation, 4 March 2019 194 | * [FIDO Client to Authenticator Protocol (CTAP) v2.0](https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#sctn-hmac-secret-extension), Proposed Standard, January 30, 2019 195 | * [IANA-COSE-REG](https://www.iana.org/assignments/cose/cose.xhtml): IANA CBOR Object Signing and Encryption (COSE) Registries. 196 | * [RFC 7049](https://tools.ietf.org/html/rfc7049): Concise Binary Object Representation (CBOR) 197 | * [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md): Universal private key derivation from master private key 198 | * [SLIP-0021](https://github.com/satoshilabs/slips/blob/master/slip-0021.md): Hierarchical derivation of symmetric keys 199 | -------------------------------------------------------------------------------- /slip-0010.md: -------------------------------------------------------------------------------- 1 | # SLIP-0010 : Universal private key derivation from master private key 2 | 3 | ``` 4 | Number: SLIP-0010 5 | Title: Universal private key derivation from master private key 6 | Type: Standard 7 | Status: Final 8 | Authors: Jochen Hoenicke 9 | Pavol Rusnak 10 | Created: 2016-04-26 11 | ``` 12 | 13 | ## Abstract 14 | 15 | SLIP-0010 describes how to derive private and public key pairs for curve 16 | types different from secp256k1. 17 | 18 | ## Motivation 19 | 20 | Some Trezor applications, in particular SSH and GPG, need different 21 | curve types, e.g., NIST P-256 and ed25519. For security reasons different 22 | private and public key pairs should be used for these curves. This SLIP 23 | describes how to derive a master private/public key for these curves and 24 | how a BIP-0032 like derivation is used. 25 | 26 | ## Body 27 | 28 | Trezor generates all keys from a 12 to 24 word mnemonic sequence and 29 | optionally a passphrase. The BIP-0039 standard describes the procedure 30 | to compute a 512 bit seed from this passphrase. From this seed Trezor 31 | can create several master keys, one for each curve. It uses a process 32 | similar and compatible to BIP-0032. For other curves it uses a 33 | different salt than BIP-0032. This avoids using the same private key 34 | for different elliptic curves with different orders. 35 | 36 | ### Master key generation 37 | 38 | We adapt the master key generation from BIP-0032. To use different 39 | private keys for different curves we use different keys for the HMAC 40 | hash that generates the master key. For the NIST P-256 curve the only 41 | other difference is the different group order. In the algorithm below 42 | we denote the group order of the elliptic curve with n. For ed25519 43 | curve the private keys are no longer multipliers for the group 44 | generator; instead the hash of the private key is the multiplier. For 45 | this reason, our scheme for ed25519 does not support public key 46 | derivation and uses the produced hashes directly as private keys. 47 | 48 | To avoid invalid master keys, the algorithm is retried with the 49 | intermediate hash as new seed if the key is invalid. 50 | 51 | 1. Generate a seed byte sequence S of 512 bits according to BIP-0039. 52 | 2. Calculate I = HMAC-SHA512(Key = Curve, Data = S) 53 | 3. Split I into two 32-byte sequences, IL and IR. 54 | 4. Use parse256(IL) as master secret key, and IR as master chain code. 55 | 5. If curve is not ed25519 and IL is 0 or ≥ n (invalid key): 56 | * Set S := I and continue at step 2. 57 | 58 | The supported curves are 59 | 60 | * Curve = "Bitcoin seed" for the secp256k1 curve (this is compatible to BIP-0032). 61 | * Curve = "Nist256p1 seed" for the NIST P-256 curve. 62 | * Curve = "ed25519 seed" for the ed25519 curve. 63 | 64 | For ed25519, the last step always succeeds since every 256-bit number 65 | (even 0) is a valid private key. 66 | 67 | ### Child key derivation (CKD) functions 68 | 69 | Private and public key derivation for NIST P-256 is identical to the 70 | generation for secp256k1 but uses the order of that curve as modulo. 71 | We change BIP-32 to not fail if the resulting key is not valid but 72 | retry hashing until a valid key is found. For ed25519 only hardened 73 | key generation from Private parent key to private child key is supported. 74 | 75 | Given a parent extended key and an index i, it is possible to compute 76 | the corresponding child extended key. The algorithm to do so depends 77 | on whether the child is a hardened key or not (or, equivalently, 78 | whether i ≥ 231), and whether we're talking about private 79 | or public keys. 80 | 81 | #### Private parent key → private child key 82 | 83 | Let n denote the order of the curve. 84 | 85 | The function CKDpriv((kpar, cpar), i) → (ki, ci) computes a child extended private key from the parent extended private key: 86 | 87 | 1. Check whether i ≥ 231 (whether the child is a hardened key). 88 | * If so (hardened child): let I = HMAC-SHA512(Key = cpar, Data = 0x00 || ser256(kpar) || ser32(i)). (Note: The 0x00 pads the private key to make it 33 bytes long.) 89 | * If not (normal child): 90 | * If curve is ed25519: return failure. 91 | * let I = HMAC-SHA512(Key = cpar, Data = serP(point(kpar)) || ser32(i)). 92 | 2. Split I into two 32-byte sequences, IL and IR. 93 | 3. The returned chain code ci is IR. 94 | 4. If curve is ed25519: The returned child key ki is parse256(IL). 95 | 5. If parse256(IL) ≥ n or parse256(IL) + kpar (mod n) = 0 (resulting key is invalid): 96 | * let I = HMAC-SHA512(Key = cpar, Data = 0x01 || IR || ser32(i) and restart at step 2. 97 | 6. Otherwise: The returned child key ki is parse256(IL) + kpar (mod n). 98 | 99 | The HMAC-SHA512 function is specified in [RFC 4231](http://tools.ietf.org/html/rfc4231). 100 | 101 | #### Public parent key → public child key 102 | 103 | This function always fails for ed25519 since normal derivation is not supported. 104 | 105 | The function CKDpub((Kpar, cpar), i) → (Ki, ci) computes a child extended public key from the parent extended public key. It is only defined for non-hardened child keys. 106 | 107 | 1. Check whether i ≥ 231 (whether the child is a hardened key). 108 | * If so (hardened child): return failure 109 | * If not (normal child): let I = HMAC-SHA512(Key = cpar, Data = serP(Kpar) || ser32(i)). 110 | 2. Split I into two 32-byte sequences, IL and IR. 111 | 3. The returned child key Ki is point(parse256(IL)) + Kpar. 112 | 4. The returned chain code ci is IR. 113 | 5. If parse256(IL) ≥ n or Ki is the point at infinity (the resulting key is invalid): 114 | * let I = HMAC-SHA512(Key = cpar, Data = 0x01 || IR || ser32(i)) and restart at step 2. 115 | 116 | ## Test vectors 117 | 118 | ### Test vector 1 for secp256k1 119 | 120 | Seed (hex): 000102030405060708090a0b0c0d0e0f 121 | 122 | * Chain m 123 | * fingerprint: 00000000 124 | * chain code: 873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508 125 | * private: e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35 126 | * public: 0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2 127 | * Chain m/0H 128 | * fingerprint: 3442193e 129 | * chain code: 47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141 130 | * private: edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea 131 | * public: 035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56 132 | * Chain m/0H/1 133 | * fingerprint: 5c1bd648 134 | * chain code: 2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19 135 | * private: 3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368 136 | * public: 03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c 137 | * Chain m/0H/1/2H 138 | * fingerprint: bef5a2f9 139 | * chain code: 04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f 140 | * private: cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca 141 | * public: 0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2 142 | * Chain m/0H/1/2H/2 143 | * fingerprint: ee7ab90c 144 | * chain code: cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd 145 | * private: 0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4 146 | * public: 02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29 147 | * Chain m/0H/1/2H/2/1000000000 148 | * fingerprint: d880d7d8 149 | * chain code: c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e 150 | * private: 471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8 151 | * public: 022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011 152 | 153 | ### Test vector 1 for nist256p1 154 | 155 | Seed (hex): 000102030405060708090a0b0c0d0e0f 156 | 157 | * Chain m 158 | * fingerprint: 00000000 159 | * chain code: beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea 160 | * private: 612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2 161 | * public: 0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8 162 | * Chain m/0H 163 | * fingerprint: be6105b5 164 | * chain code: 3460cea53e6a6bb5fb391eeef3237ffd8724bf0a40e94943c98b83825342ee11 165 | * private: 6939694369114c67917a182c59ddb8cafc3004e63ca5d3b84403ba8613debc0c 166 | * public: 0384610f5ecffe8fda089363a41f56a5c7ffc1d81b59a612d0d649b2d22355590c 167 | * Chain m/0H/1 168 | * fingerprint: 9b02312f 169 | * chain code: 4187afff1aafa8445010097fb99d23aee9f599450c7bd140b6826ac22ba21d0c 170 | * private: 284e9d38d07d21e4e281b645089a94f4cf5a5a81369acf151a1c3a57f18b2129 171 | * public: 03526c63f8d0b4bbbf9c80df553fe66742df4676b241dabefdef67733e070f6844 172 | * Chain m/0H/1/2H 173 | * fingerprint: b98005c1 174 | * chain code: 98c7514f562e64e74170cc3cf304ee1ce54d6b6da4f880f313e8204c2a185318 175 | * private: 694596e8a54f252c960eb771a3c41e7e32496d03b954aeb90f61635b8e092aa7 176 | * public: 0359cf160040778a4b14c5f4d7b76e327ccc8c4a6086dd9451b7482b5a4972dda0 177 | * Chain m/0H/1/2H/2 178 | * fingerprint: 0e9f3274 179 | * chain code: ba96f776a5c3907d7fd48bde5620ee374d4acfd540378476019eab70790c63a0 180 | * private: 5996c37fd3dd2679039b23ed6f70b506c6b56b3cb5e424681fb0fa64caf82aaa 181 | * public: 029f871f4cb9e1c97f9f4de9ccd0d4a2f2a171110c61178f84430062230833ff20 182 | * Chain m/0H/1/2H/2/1000000000 183 | * fingerprint: 8b2b5c4b 184 | * chain code: b9b7b82d326bb9cb5b5b121066feea4eb93d5241103c9e7a18aad40f1dde8059 185 | * private: 21c4f269ef0a5fd1badf47eeacebeeaa3de22eb8e5b0adcd0f27dd99d34d0119 186 | * public: 02216cd26d31147f72427a453c443ed2cde8a1e53c9cc44e5ddf739725413fe3f4 187 | 188 | ### Test vector 1 for ed25519 189 | 190 | Seed (hex): 000102030405060708090a0b0c0d0e0f 191 | 192 | * Chain m 193 | * fingerprint: 00000000 194 | * chain code: 90046a93de5380a72b5e45010748567d5ea02bbf6522f979e05c0d8d8ca9fffb 195 | * private: 2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7 196 | * public: 00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed 197 | * Chain m/0H 198 | * fingerprint: ddebc675 199 | * chain code: 8b59aa11380b624e81507a27fedda59fea6d0b779a778918a2fd3590e16e9c69 200 | * private: 68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3 201 | * public: 008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c 202 | * Chain m/0H/1H 203 | * fingerprint: 13dab143 204 | * chain code: a320425f77d1b5c2505a6b1b27382b37368ee640e3557c315416801243552f14 205 | * private: b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2 206 | * public: 001932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187 207 | * Chain m/0H/1H/2H 208 | * fingerprint: ebe4cb29 209 | * chain code: 2e69929e00b5ab250f49c3fb1c12f252de4fed2c1db88387094a0f8c4c9ccd6c 210 | * private: 92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9 211 | * public: 00ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1 212 | * Chain m/0H/1H/2H/2H 213 | * fingerprint: 316ec1c6 214 | * chain code: 8f6d87f93d750e0efccda017d662a1b31a266e4a6f5993b15f5c1f07f74dd5cc 215 | * private: 30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662 216 | * public: 008abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c 217 | * Chain m/0H/1H/2H/2H/1000000000H 218 | * fingerprint: d6322ccd 219 | * chain code: 68789923a0cac2cd5a29172a475fe9e0fb14cd6adb5ad98a3fa70333e7afa230 220 | * private: 8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793 221 | * public: 003c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a 222 | 223 | ### Test vector 2 for secp256k1 224 | 225 | Seed (hex): fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542 226 | 227 | * Chain m 228 | * fingerprint: 00000000 229 | * chain code: 60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689 230 | * private: 4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e 231 | * public: 03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7 232 | * Chain m/0 233 | * fingerprint: bd16bee5 234 | * chain code: f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c 235 | * private: abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e 236 | * public: 02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea 237 | * Chain m/0/2147483647H 238 | * fingerprint: 5a61ff8e 239 | * chain code: be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9 240 | * private: 877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93 241 | * public: 03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b 242 | * Chain m/0/2147483647H/1 243 | * fingerprint: d8ab4937 244 | * chain code: f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb 245 | * private: 704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7 246 | * public: 03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9 247 | * Chain m/0/2147483647H/1/2147483646H 248 | * fingerprint: 78412e3a 249 | * chain code: 637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29 250 | * private: f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d 251 | * public: 02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0 252 | * Chain m/0/2147483647H/1/2147483646H/2 253 | * fingerprint: 31a507b8 254 | * chain code: 9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271 255 | * private: bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23 256 | * public: 024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c 257 | 258 | ### Test vector 2 for nist256p1 259 | 260 | Seed (hex): fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542 261 | 262 | * Chain m 263 | * fingerprint: 00000000 264 | * chain code: 96cd4465a9644e31528eda3592aa35eb39a9527769ce1855beafc1b81055e75d 265 | * private: eaa31c2e46ca2962227cf21d73a7ef0ce8b31c756897521eb6c7b39796633357 266 | * public: 02c9e16154474b3ed5b38218bb0463e008f89ee03e62d22fdcc8014beab25b48fa 267 | * Chain m/0 268 | * fingerprint: 607f628f 269 | * chain code: 84e9c258bb8557a40e0d041115b376dd55eda99c0042ce29e81ebe4efed9b86a 270 | * private: d7d065f63a62624888500cdb4f88b6d59c2927fee9e6d0cdff9cad555884df6e 271 | * public: 039b6df4bece7b6c81e2adfeea4bcf5c8c8a6e40ea7ffa3cf6e8494c61a1fc82cc 272 | * Chain m/0/2147483647H 273 | * fingerprint: 946d2a54 274 | * chain code: f235b2bc5c04606ca9c30027a84f353acf4e4683edbd11f635d0dcc1cd106ea6 275 | * private: 96d2ec9316746a75e7793684ed01e3d51194d81a42a3276858a5b7376d4b94b9 276 | * public: 02f89c5deb1cae4fedc9905f98ae6cbf6cbab120d8cb85d5bd9a91a72f4c068c76 277 | * Chain m/0/2147483647H/1 278 | * fingerprint: 218182d8 279 | * chain code: 7c0b833106235e452eba79d2bdd58d4086e663bc8cc55e9773d2b5eeda313f3b 280 | * private: 974f9096ea6873a915910e82b29d7c338542ccde39d2064d1cc228f371542bbc 281 | * public: 03abe0ad54c97c1d654c1852dfdc32d6d3e487e75fa16f0fd6304b9ceae4220c64 282 | * Chain m/0/2147483647H/1/2147483646H 283 | * fingerprint: 931223e4 284 | * chain code: 5794e616eadaf33413aa309318a26ee0fd5163b70466de7a4512fd4b1a5c9e6a 285 | * private: da29649bbfaff095cd43819eda9a7be74236539a29094cd8336b07ed8d4eff63 286 | * public: 03cb8cb067d248691808cd6b5a5a06b48e34ebac4d965cba33e6dc46fe13d9b933 287 | * Chain m/0/2147483647H/1/2147483646H/2 288 | * fingerprint: 956c4629 289 | * chain code: 3bfb29ee8ac4484f09db09c2079b520ea5616df7820f071a20320366fbe226a7 290 | * private: bb0a77ba01cc31d77205d51d08bd313b979a71ef4de9b062f8958297e746bd67 291 | * public: 020ee02e18967237cf62672983b253ee62fa4dd431f8243bfeccdf39dbe181387f 292 | 293 | ### Test vector 2 for ed25519 294 | 295 | Seed (hex): fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542 296 | 297 | * Chain m 298 | * fingerprint: 00000000 299 | * chain code: ef70a74db9c3a5af931b5fe73ed8e1a53464133654fd55e7a66f8570b8e33c3b 300 | * private: 171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012 301 | * public: 008fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a 302 | * Chain m/0H 303 | * fingerprint: 31981b50 304 | * chain code: 0b78a3226f915c082bf118f83618a618ab6dec793752624cbeb622acb562862d 305 | * private: 1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635 306 | * public: 0086fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037 307 | * Chain m/0H/2147483647H 308 | * fingerprint: 1e9411b1 309 | * chain code: 138f0b2551bcafeca6ff2aa88ba8ed0ed8de070841f0c4ef0165df8181eaad7f 310 | * private: ea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4 311 | * public: 005ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d 312 | * Chain m/0H/2147483647H/1H 313 | * fingerprint: fcadf38c 314 | * chain code: 73bd9fff1cfbde33a1b846c27085f711c0fe2d66fd32e139d3ebc28e5a4a6b90 315 | * private: 3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c 316 | * public: 002e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45 317 | * Chain m/0H/2147483647H/1H/2147483646H 318 | * fingerprint: aca70953 319 | * chain code: 0902fe8a29f9140480a00ef244bd183e8a13288e4412d8389d140aac1794825a 320 | * private: 5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72 321 | * public: 00e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b 322 | * Chain m/0H/2147483647H/1H/2147483646H/2H 323 | * fingerprint: 422c654b 324 | * chain code: 5d70af781f3a37b829f0d060924d5e960bdc02e85423494afc0b1a41bbe196d4 325 | * private: 551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d 326 | * public: 0047150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0 327 | 328 | ### Test derivation retry for nist256p1 329 | 330 | Seed (hex): 000102030405060708090a0b0c0d0e0f 331 | 332 | * Chain m 333 | * fingerprint: 00000000 334 | * chain code: beeb672fe4621673f722f38529c07392fecaa61015c80c34f29ce8b41b3cb6ea 335 | * private: 612091aaa12e22dd2abef664f8a01a82cae99ad7441b7ef8110424915c268bc2 336 | * public: 0266874dc6ade47b3ecd096745ca09bcd29638dd52c2c12117b11ed3e458cfa9e8 337 | * Chain m/28578H 338 | * fingerprint: be6105b5 339 | * chain code: e94c8ebe30c2250a14713212f6449b20f3329105ea15b652ca5bdfc68f6c65c2 340 | * private: 06f0db126f023755d0b8d86d4591718a5210dd8d024e3e14b6159d63f53aa669 341 | * public: 02519b5554a4872e8c9c1c847115363051ec43e93400e030ba3c36b52a3e70a5b7 342 | * Chain m/28578H/33941 343 | * fingerprint: 3e2b7bc6 344 | * chain code: 9e87fe95031f14736774cd82f25fd885065cb7c358c1edf813c72af535e83071 345 | * private: 092154eed4af83e078ff9b84322015aefe5769e31270f62c3f66c33888335f3a 346 | * public: 0235bfee614c0d5b2cae260000bb1d0d84b270099ad790022c1ae0b2e782efe120 347 | 348 | ### Test seed retry for nist256p1 349 | 350 | Seed (hex): a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446 351 | 352 | * Chain m 353 | * fingerprint: 00000000 354 | * chain code: 7762f9729fed06121fd13f326884c82f59aa95c57ac492ce8c9654e60efd130c 355 | * private: 3b8c18469a4634517d6d0b65448f8e6c62091b45540a1743c5846be55d47d88f 356 | * public: 0383619fadcde31063d8c5cb00dbfe1713f3e6fa169d8541a798752a1c1ca0cb20 357 | 358 | ## Implementation 359 | 360 | * [Python implementation to generate test vectors](slip-0010/testvectors.py) 361 | * [.NET Standard 2.0 Implementation](https://github.com/elucidsoft/dotnetstandard-bip32) 362 | 363 | ## References 364 | 365 | * [BIP-0032: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 366 | * [BIP-0039: Mnemonic code for generating deterministic keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) 367 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-ShareAlike 4.0 International Public 58 | License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-ShareAlike 4.0 International Public License ("Public 63 | License"). To the extent this Public License may be interpreted as a 64 | contract, You are granted the Licensed Rights in consideration of Your 65 | acceptance of these terms and conditions, and the Licensor grants You 66 | such rights in consideration of benefits the Licensor receives from 67 | making the Licensed Material available under these terms and 68 | conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. Share means to provide material to the public by any means or 126 | process that requires permission under the Licensed Rights, such 127 | as reproduction, public display, public performance, distribution, 128 | dissemination, communication, or importation, and to make material 129 | available to the public including in ways that members of the 130 | public may access the material from a place and at a time 131 | individually chosen by them. 132 | 133 | l. Sui Generis Database Rights means rights other than copyright 134 | resulting from Directive 96/9/EC of the European Parliament and of 135 | the Council of 11 March 1996 on the legal protection of databases, 136 | as amended and/or succeeded, as well as other essentially 137 | equivalent rights anywhere in the world. 138 | 139 | m. You means the individual or entity exercising the Licensed Rights 140 | under this Public License. Your has a corresponding meaning. 141 | 142 | 143 | Section 2 -- Scope. 144 | 145 | a. License grant. 146 | 147 | 1. Subject to the terms and conditions of this Public License, 148 | the Licensor hereby grants You a worldwide, royalty-free, 149 | non-sublicensable, non-exclusive, irrevocable license to 150 | exercise the Licensed Rights in the Licensed Material to: 151 | 152 | a. reproduce and Share the Licensed Material, in whole or 153 | in part; and 154 | 155 | b. produce, reproduce, and Share Adapted Material. 156 | 157 | 2. Exceptions and Limitations. For the avoidance of doubt, where 158 | Exceptions and Limitations apply to Your use, this Public 159 | License does not apply, and You do not need to comply with 160 | its terms and conditions. 161 | 162 | 3. Term. The term of this Public License is specified in Section 163 | 6(a). 164 | 165 | 4. Media and formats; technical modifications allowed. The 166 | Licensor authorizes You to exercise the Licensed Rights in 167 | all media and formats whether now known or hereafter created, 168 | and to make technical modifications necessary to do so. The 169 | Licensor waives and/or agrees not to assert any right or 170 | authority to forbid You from making technical modifications 171 | necessary to exercise the Licensed Rights, including 172 | technical modifications necessary to circumvent Effective 173 | Technological Measures. For purposes of this Public License, 174 | simply making modifications authorized by this Section 2(a) 175 | (4) never produces Adapted Material. 176 | 177 | 5. Downstream recipients. 178 | 179 | a. Offer from the Licensor -- Licensed Material. Every 180 | recipient of the Licensed Material automatically 181 | receives an offer from the Licensor to exercise the 182 | Licensed Rights under the terms and conditions of this 183 | Public License. 184 | 185 | b. Additional offer from the Licensor -- Adapted Material. 186 | Every recipient of Adapted Material from You 187 | automatically receives an offer from the Licensor to 188 | exercise the Licensed Rights in the Adapted Material 189 | under the conditions of the Adapter's License You apply. 190 | 191 | c. No downstream restrictions. You may not offer or impose 192 | any additional or different terms or conditions on, or 193 | apply any Effective Technological Measures to, the 194 | Licensed Material if doing so restricts exercise of the 195 | Licensed Rights by any recipient of the Licensed 196 | Material. 197 | 198 | 6. No endorsement. Nothing in this Public License constitutes or 199 | may be construed as permission to assert or imply that You 200 | are, or that Your use of the Licensed Material is, connected 201 | with, or sponsored, endorsed, or granted official status by, 202 | the Licensor or others designated to receive attribution as 203 | provided in Section 3(a)(1)(A)(i). 204 | 205 | b. Other rights. 206 | 207 | 1. Moral rights, such as the right of integrity, are not 208 | licensed under this Public License, nor are publicity, 209 | privacy, and/or other similar personality rights; however, to 210 | the extent possible, the Licensor waives and/or agrees not to 211 | assert any such rights held by the Licensor to the limited 212 | extent necessary to allow You to exercise the Licensed 213 | Rights, but not otherwise. 214 | 215 | 2. Patent and trademark rights are not licensed under this 216 | Public License. 217 | 218 | 3. To the extent possible, the Licensor waives any right to 219 | collect royalties from You for the exercise of the Licensed 220 | Rights, whether directly or through a collecting society 221 | under any voluntary or waivable statutory or compulsory 222 | licensing scheme. In all other cases the Licensor expressly 223 | reserves any right to collect such royalties. 224 | 225 | 226 | Section 3 -- License Conditions. 227 | 228 | Your exercise of the Licensed Rights is expressly made subject to the 229 | following conditions. 230 | 231 | a. Attribution. 232 | 233 | 1. If You Share the Licensed Material (including in modified 234 | form), You must: 235 | 236 | a. retain the following if it is supplied by the Licensor 237 | with the Licensed Material: 238 | 239 | i. identification of the creator(s) of the Licensed 240 | Material and any others designated to receive 241 | attribution, in any reasonable manner requested by 242 | the Licensor (including by pseudonym if 243 | designated); 244 | 245 | ii. a copyright notice; 246 | 247 | iii. a notice that refers to this Public License; 248 | 249 | iv. a notice that refers to the disclaimer of 250 | warranties; 251 | 252 | v. a URI or hyperlink to the Licensed Material to the 253 | extent reasonably practicable; 254 | 255 | b. indicate if You modified the Licensed Material and 256 | retain an indication of any previous modifications; and 257 | 258 | c. indicate the Licensed Material is licensed under this 259 | Public License, and include the text of, or the URI or 260 | hyperlink to, this Public License. 261 | 262 | 2. You may satisfy the conditions in Section 3(a)(1) in any 263 | reasonable manner based on the medium, means, and context in 264 | which You Share the Licensed Material. For example, it may be 265 | reasonable to satisfy the conditions by providing a URI or 266 | hyperlink to a resource that includes the required 267 | information. 268 | 269 | 3. If requested by the Licensor, You must remove any of the 270 | information required by Section 3(a)(1)(A) to the extent 271 | reasonably practicable. 272 | 273 | b. ShareAlike. 274 | 275 | In addition to the conditions in Section 3(a), if You Share 276 | Adapted Material You produce, the following conditions also apply. 277 | 278 | 1. The Adapter's License You apply must be a Creative Commons 279 | license with the same License Elements, this version or 280 | later, or a BY-SA Compatible License. 281 | 282 | 2. You must include the text of, or the URI or hyperlink to, the 283 | Adapter's License You apply. You may satisfy this condition 284 | in any reasonable manner based on the medium, means, and 285 | context in which You Share Adapted Material. 286 | 287 | 3. You may not offer or impose any additional or different terms 288 | or conditions on, or apply any Effective Technological 289 | Measures to, Adapted Material that restrict exercise of the 290 | rights granted under the Adapter's License You apply. 291 | 292 | 293 | Section 4 -- Sui Generis Database Rights. 294 | 295 | Where the Licensed Rights include Sui Generis Database Rights that 296 | apply to Your use of the Licensed Material: 297 | 298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 299 | to extract, reuse, reproduce, and Share all or a substantial 300 | portion of the contents of the database; 301 | 302 | b. if You include all or a substantial portion of the database 303 | contents in a database in which You have Sui Generis Database 304 | Rights, then the database in which You have Sui Generis Database 305 | Rights (but not its individual contents) is Adapted Material, 306 | 307 | including for purposes of Section 3(b); and 308 | c. You must comply with the conditions in Section 3(a) if You Share 309 | all or a substantial portion of the contents of the database. 310 | 311 | For the avoidance of doubt, this Section 4 supplements and does not 312 | replace Your obligations under this Public License where the Licensed 313 | Rights include other Copyright and Similar Rights. 314 | 315 | 316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 317 | 318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 328 | 329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 338 | 339 | c. The disclaimer of warranties and limitation of liability provided 340 | above shall be interpreted in a manner that, to the extent 341 | possible, most closely approximates an absolute disclaimer and 342 | waiver of all liability. 343 | 344 | 345 | Section 6 -- Term and Termination. 346 | 347 | a. This Public License applies for the term of the Copyright and 348 | Similar Rights licensed here. However, if You fail to comply with 349 | this Public License, then Your rights under this Public License 350 | terminate automatically. 351 | 352 | b. Where Your right to use the Licensed Material has terminated under 353 | Section 6(a), it reinstates: 354 | 355 | 1. automatically as of the date the violation is cured, provided 356 | it is cured within 30 days of Your discovery of the 357 | violation; or 358 | 359 | 2. upon express reinstatement by the Licensor. 360 | 361 | For the avoidance of doubt, this Section 6(b) does not affect any 362 | right the Licensor may have to seek remedies for Your violations 363 | of this Public License. 364 | 365 | c. For the avoidance of doubt, the Licensor may also offer the 366 | Licensed Material under separate terms or conditions or stop 367 | distributing the Licensed Material at any time; however, doing so 368 | will not terminate this Public License. 369 | 370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 371 | License. 372 | 373 | 374 | Section 7 -- Other Terms and Conditions. 375 | 376 | a. The Licensor shall not be bound by any additional or different 377 | terms or conditions communicated by You unless expressly agreed. 378 | 379 | b. Any arrangements, understandings, or agreements regarding the 380 | Licensed Material not stated herein are separate from and 381 | independent of the terms and conditions of this Public License. 382 | 383 | 384 | Section 8 -- Interpretation. 385 | 386 | a. For the avoidance of doubt, this Public License does not, and 387 | shall not be interpreted to, reduce, limit, restrict, or impose 388 | conditions on any use of the Licensed Material that could lawfully 389 | be made without permission under this Public License. 390 | 391 | b. To the extent possible, if any provision of this Public License is 392 | deemed unenforceable, it shall be automatically reformed to the 393 | minimum extent necessary to make it enforceable. If the provision 394 | cannot be reformed, it shall be severed from this Public License 395 | without affecting the enforceability of the remaining terms and 396 | conditions. 397 | 398 | c. No term or condition of this Public License will be waived and no 399 | failure to comply consented to unless expressly agreed to by the 400 | Licensor. 401 | 402 | d. Nothing in this Public License constitutes or may be interpreted 403 | as a limitation upon, or waiver of, any privileges and immunities 404 | that apply to the Licensor or You, including from the legal 405 | processes of any jurisdiction or authority. 406 | 407 | 408 | ======================================================================= 409 | 410 | Creative Commons is not a party to its public 411 | licenses. Notwithstanding, Creative Commons may elect to apply one of 412 | its public licenses to material it publishes and in those instances 413 | will be considered the “Licensor.” The text of the Creative Commons 414 | public licenses is dedicated to the public domain under the CC0 Public 415 | Domain Dedication. Except for the limited purpose of indicating that 416 | material is shared under a Creative Commons public license or as 417 | otherwise permitted by the Creative Commons policies published at 418 | creativecommons.org/policies, Creative Commons does not authorize the 419 | use of the trademark "Creative Commons" or any other trademark or logo 420 | of Creative Commons without its prior written consent including, 421 | without limitation, in connection with any unauthorized modifications 422 | to any of its public licenses or any other arrangements, 423 | understandings, or agreements concerning use of licensed material. For 424 | the avoidance of doubt, this paragraph does not form part of the 425 | public licenses. 426 | 427 | Creative Commons may be contacted at creativecommons.org. 428 | 429 | -------------------------------------------------------------------------------- /slip-0019.md: -------------------------------------------------------------------------------- 1 | # SLIP-0019 : Proof of Ownership 2 | 3 | ``` 4 | Number: SLIP-0019 5 | Title: Proof of Ownership 6 | Type: Standard 7 | Status: Accepted 8 | Authors: Andrew Kozlik 9 | Stepan Snigirev 10 | Ondrej Vejpustek 11 | Pavol Rusnak 12 | Created: 2019-04-25 13 | ``` 14 | 15 | ## Abstract 16 | 17 | This specification defines the format for a proof of ownership which can be passed to a hierarchical deterministic wallet together with each input of an unsigned transaction. This proof allows the wallet to determine whether it is able to spend the given input or not. It also allows third parties to verify that a user has the ability to spend the input. 18 | 19 | ## Motivation 20 | 21 | In certain applications like CoinJoin and Lightning, a wallet has to sign transactions containing external inputs. To calculate the actual amount the user is spending, the wallet needs to reliably determine for each input whether it belongs to the wallet or not. Without such a mechanism an attacker can deceive the wallet into displaying incorrect information about the amount being spent, which can result in theft of user funds. This was first recognized in a bitcoin-dev [mailing list discussion](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-August/014843.html). 22 | 23 | For example, in a CoinJoin transaction an attacker can construct a transaction with inputs `in1` and `in2` of identical value belonging to the user and two outputs of identical value, `user_out` belonging to the user and `attacker_out` belonging to the attacker. If such a transaction is sent to a hardware wallet twice with `in1` marked as external the first time and `in2` marked as external the second time, then the hardware wallet will display two signing requests to the user with a spending amount of `in2 - user_out` and `in1 - user_out`, respectively. The user will think that they are signing two different CoinJoin transactions and spending `in1 + in2 - 2*user_out` for the fees, while in reality they are signing two different inputs to a single transaction and sending half of the amount to the attacker. 24 | 25 | To mitigate such an attack, the hardware wallet needs to ascertain non-ownership of all inputs which are claimed to be external. In case of hierarchical deterministic wallets it is generally not feasible to ascertain this solely based on the scriptPubKey of the UTXO, because it would require searching through billions of BIP32 derivation paths. Furthermore, even though CoinJoin transactions currently work only with P2WPKH addresses, other applications may require more complicated inputs including multi-signature and Schnorr multi-signature in the future. 26 | 27 | A CoinJoin coordinator can also benefit from such a proof to verify that the CoinJoin participant is able and willing to sign the input. This verification helps to mitigate denial-of-service attacks as the attacker has to use a limited UTXO set that they control and in case of misbehavior this UTXO set gets banned. 28 | 29 | ## Proof of ownership format 30 | 31 | A proof of ownership consists of a proof body and a signature. The proof body contains one or more ownership identifiers which allow a wallet to efficiently determine whether or not it is able to spend a UTXO having a given scriptPubKey. The proof signature affirms that the proof body can be trusted to have been generated by the true owner of the UTXO. 32 | 33 | ``` 34 | proofOfOwnership = proofBody || proofSignature 35 | ``` 36 | 37 | ### Ownership identifier 38 | 39 | Let *k* be a secret *ownership identification key* derived from the wallet's master secret using the [SLIP-0021](https://github.com/satoshilabs/slips/blob/master/slip-0021.md) method for hierarchical derivation of symmetric keys as: 40 | 41 | ``` 42 | k = Key(m/"SLIP-0019"/"Ownership identification key") 43 | ``` 44 | 45 | The ownership identifier for a scriptPubKey is computed as: 46 | 47 | ``` 48 | id = HMAC-SHA256(key = k, msg = scriptPubKey) 49 | ``` 50 | 51 | In case of *m*-of-*n* multi-signature scriptPubKeys the proof of ownership SHOULD contain the ownership identifiers of all *n* co-owners of that scriptPubKey. See [Identifier inclusion](#identifier-inclusion) for further details. 52 | 53 | A wallet MUST NOT produce and reveal an ownership identifier for a scriptPubKey which it does not control. Such a fake ownership identifier can be used to mount a denial-of-service attack. 54 | 55 | ### Proof body 56 | 57 | The *proofBody* is a concatenation of the following fields: 58 | 59 | * *versionMagic* (4 bytes): b"\x53\x4c\x00\x19" (this is "SL" followed by 0019 in compressed numeric form as an abbreviation for "SLIP-0019"). 60 | * *flags* (1 byte, bit 0 is the least significant bit): 61 | * Bit 0: User confirmation 62 | * 0 means the proof was generated without user confirmation. 63 | * 1 means the user confirmed the generation of the proof. 64 | * Bits 1 to 7: Reserved for future use (all must be 0). 65 | * *n* (VarInt): the number of ownership identifiers which follow. The VarInt MUST be encoded in the fewest possible number of bytes. 66 | * *id*1 || *id*2 || ... || *id**n* (32 bytes each): concatenation of the ownership identifiers for the given scriptPubKey, one for each co-owner, see [Identifier inclusion](#identifier-inclusion) for further details. 67 | 68 | ### Proof footer 69 | 70 | The *proofFooter* is a concatenation of the following fields: 71 | 72 | * *scriptPubKey* (length-prefixed string). 73 | * *commitmentData* (length-prefixed string), any additional data to which the proof should commit, see below. 74 | 75 | The proof footer is included only in the *sighash* computation. It is not part of the proof of ownership, because the verifier of the proof should obtain these fields externally based on the context in which the proof is provided. Namely the *scriptPubKey* should be obtained by looking up the output being spent and the *commitmentData* is given by the application context. Variable-length fields are encoded the same way as in Bitcoin transactions, as a length-prefixed string, where the length is encoded as a variable-length integer (VarInt). 76 | 77 | ### Proof signature 78 | 79 | The concatenation of the *proofBody* and *proofFooter* is signed using the Generic Signed Message Format as defined in the [original BIP-0322](https://github.com/bitcoin/bips/blob/f9e95849f337358cd89c83b948fbede3875481c3/bip-0322.mediawiki) until October 2020, when the BIP-0322 specification was rewritten to use the transaction-based approach. 80 | The *proofSignature* is the `SignatureProof` container defined in the original BIP-0322 using the sighash computed as: 81 | 82 | ``` 83 | sighash = SHA-256(proofBody || proofFooter) 84 | ``` 85 | 86 | ### Additional commitment data 87 | 88 | The content of the *commitmentData* field is application-specific. If an application does not define the content of this field, then a zero-length string should be used by default. 89 | 90 | In case of CoinJoin transactions the *commitmentData* SHOULD contain a globally unique PSBT identifier (*psbtId*). The purpose of such an identifier is to prevent an attacker from causing denial of service by registering an input into a different CoinJoin transaction than the one for which the input was intended. The user should explicitly confirm the generation of the proof and the *commitmentData* value to affirm their intent to participate in the given CoinJoin transaction. 91 | 92 | The *psbtId* is not to be confused with TXID, which is the hash of a transaction's data. Since the *psbtId* needs to be known before the transaction is created, it cannot be derived from the transaction data but needs to be generated as a nonce. For example: 93 | 94 | 1. The concatenation of a globally unique CoinJoin server identifier (192 bits) with a sequential round identifier (64 bits). 95 | 2. A random 256 bit value. 96 | 97 | ## Proof construction 98 | 99 | ### Single-signature scriptPubKeys 100 | 101 | When constructing a proof of ownership for a single-signature scriptPubKey the inputs to the wallet are the *flags*, *scriptPubKey*, *commitmentData* and the BIP32 derivation path. The wallet takes the following steps: 102 | 103 | 1. Ensure that bits 1 through 7 of *flags* are clear. 104 | 2. Ensure that the wallet controls the private key to the provided *scriptPubKey*. This is typically done by using the provided BIP32 derivation path. 105 | 3. If bit 0 (user confirmation) of *flags* is set, then prompt the user to confirm generation of the ownership proof with the given *commitmentData*. If the user does not confirm, then abort. 106 | 4. Compute the ownership identifier for the scriptPubKey. 107 | 5. Compile the *proofBody* and *proofFooter*, and generate the *proofSignature*. 108 | 6. Return the *proofBody* and *proofSignature*. 109 | 110 | ### Multi-signature scriptPubKeys 111 | 112 | The construction of a proof of ownership for a *m*-of-*n* multi-signature scriptPubKey requires a signing coordinator, i.e. a watch-only software wallet. The signing coordinator is assumed to have obtained the ownership identifiers of all *n* co-owners in advance. These ownership identifiers should generally be produced at the time of the creation of the multi-signature address. 113 | 114 | When constructing a proof of ownership, the signing coordinator prepares the *proofBody* and *proofFooter* and sends these to each signer together with any other required metadata, such as the BIP32 derivation path for the input. Each of the *m* signers then takes the following steps: 115 | 116 | 1. Parse the *proofBody* and *proofFooter*. If *versionMagic* is not recognized or if any of the bits 1 through 7 of *flags* is set, then abort. 117 | 2. Derive the ownership identifier using the *scriptPubKey* provided in the *proofFooter*. 118 | 3. If the derived ownership identifier is not listed in the *proofBody*, then abort. 119 | 4. If bit 0 (user confirmation) of *flags* is set, then prompt the user to confirm generation of the ownership proof with the given *commitmentData*. If the user does not confirm, then abort. 120 | 5. Return the signature for the provided *proofBody* and *proofFooter*. 121 | 122 | The signing coordinator collects all the signatures and combines them into a `SignatureProof` container to finalize the proof. 123 | 124 | ## Proof usage 125 | 126 | ### Verifying non-ownership of transaction inputs 127 | 128 | When a wallet is requested to sign a transaction, each external input SHOULD be accompanied with a proof of ownership so that the wallet may ascertain non-ownership of such an input in order to correctly inform the user about the amount they are spending in the transaction. For each external input the wallet takes the following steps: 129 | 130 | 1. By reliable means obtain the scriptPubKey of the UTXO being spent by that input. Prior to SegWit version 1 witness programs this step involves acquiring the full transaction being spent and verifying its hash against that which is given in the outpoint. 131 | 2. Parse the *proofBody*. If *versionMagic* is not recognized or if any of the bits 1 through 7 of *flags* is set, then abort. 132 | 3. Verify that the *proofSignature* is valid in accordance with BIP-0322 using the obtained scriptPubKey and the sighash as defined in the [Proof signature](#proof-signature) section. 133 | 4. Derive the ownership identifier using the wallet's ownership identification key and the obtained scriptPubKey. 134 | 5. Verify that the derived ownership identifier is not included in the *proofBody*. 135 | 136 | ### Verifying ability and intent to sign an input 137 | 138 | Each input which is registered to take part in a CoinJoin transaction should be accompanied with a proof of ownership which affirms the owner's intent to take part, so as to mitigate denial-of-service attacks. The CoinJoin coordinator takes the following steps before registering an input: 139 | 140 | 1. By reliable means obtain the scriptPubKey of the UTXO being spent by that input. 141 | 2. Parse the *proofBody*. If *versionMagic* is not recognized or if any of the bits 1 through 7 of *flags* is set, then abort. 142 | 3. Verify that bit 0 (user confirmation) of *flags* is set. 143 | 4. Verify that the *proofSignature* is valid using the obtained scriptPubKey. 144 | 145 | A proof of ownership commits to a particular scriptPubKey, which means that the proof is replayable for UTXOs with the same address. Nevertheless, freshness of such a proof is guaranteed if a nonce (such as the *psbtId*) is included in the *commitmentData*. 146 | 147 | ## PSBT (BIP 174) extension 148 | 149 | The following new global field type is added to the BIP-0174 specification: 150 | 151 | * Type: PSBT identifier PSBT_GLOBAL_PSBT_ID = 0x0A 152 | * Key: None. The key must only contain the 1 byte type. 153 | * `{0x02}` 154 | * Value: A globally unique PSBT identifier. This value should be used as the *commitmentData* in the *proofFooter*. 155 | * `{psbtId}` 156 | 157 | The following new per-input field type is added to the BIP-0174 specification: 158 | 159 | * Type: Proof of ownership PSBT_IN_PROOF_OF_OWNERSHIP = 0x0A 160 | * Key: None. The key must only contain the 1 byte type. 161 | * `{0x0A}` 162 | * Value: The *proofOfOwnership* as defined above. 163 | * `{proofOfOwnership}` 164 | 165 | ## Implementation considerations 166 | 167 | ### Script evaluation on hardware wallets 168 | 169 | Currently most hardware wallets do not support complete Bitcoin script verification, so initial deployment of proofs of ownership can be limited to a set of known scripts. In the future hardware wallets may implement [miniscript](http://bitcoin.sipa.be/miniscript/) verification, that will cover most of the use-cases known today. 170 | 171 | ### Identifier inclusion 172 | 173 | When generating a proof of ownership for *m*-of-*n* multi-signature scriptPubKeys the proof body SHOULD contain the ownership identifiers of all *n* co-owners of that scriptPubKey. Failing to include all ownership identifiers opens the door to the following attack. 174 | 175 | For simplicity consider two equal-valued UTXOs *A* and *B*, both of which have the same 1-of-2 multi-signature scriptPubKey controlled by Users 1 and 2. The attacker requests a proof of ownership *P1* from User 1 containing only User 1's ownership identifier. Similarly the attacker requests a proof of ownership *P2* from User 2 containing only User 2's ownership identifier. The attacker then creates a CoinJoin transaction with inputs *A* and *B* and equal-valued outputs *out_user* and *out_attacker*, the former of which is a multi-signature scriptPubKey controlled by Users 1 and 2. User 1 is given the transaction to sign with proof *P2* for the input spending *B*, and User 2 is given the same transaction to sign with proof *P1* for the input spending *A*. User 1 perceives *B* as foreign, assumes they are transferring *A* to *out_user* and signs the input spending *A*. User 2 perceives *A* as foreign, assumes they are transferring *B* to *out_user* and signs the input spending *B*. As a result half of the amount from *A* and *B* is transferred to the attacker. This attack is extendable to more complex *m*-of-*n* multi-signatures. 176 | 177 | In some cases there are legitimate reasons not to include the ownership identifier of a co-owner: 178 | 179 | 1. The excluded co-owner does not support any kind of proof of ownership format and will never take part in a transaction containing external inputs. An example of this would be a cryptocurrency custody service which is included in the multi-signature setup only as a backup in case the key of one of the co-owners is lost. 180 | 2. A co-owner is intentionally excluded to avoid signing failures due to input ownership collisions. Consider a user who is participating in a CoinJoin transaction with their UTXO *A*. At the same time this user happens to be a co-owner of another UTXO *B* being spent as an input in the same transaction. The user is not meant to be cosigning *B*, because this input was registered independently by a group of co-owners who did not expect the user to participate. Thus the user's wallet will recognize *B* as an input it co-owns, but it will not be able to sign because it was not given the corresponding BIP32 derivation path. Even if the path were to be provided, the user might not be willing to cosign due to confusion at the unexpected presence of the input amount supplied by *B*. As a result the CoinJoin transaction will fail to complete. Before excluding an ownership identifier on these grounds, the likelihood of this kind of scenario needs to be carefully weighed against the risk of the attack described above. 181 | 182 | ## Test vectors 183 | 184 | ### Test vector 1 (P2WPKH) 185 | 186 | #### Input parameters 187 | 188 | Parameter | Value 189 | -----------------------|------ 190 | BIP39 seed | "all all all all all all all all all all all all" 191 | Passphrase | "" 192 | Ownership ID key (hex) | `0a115a171e30f8a740bae6c4144bec5dc1099ffa79b83dfb8aa3501d094de585` 193 | Path | m/84'/0'/0'/1/0 194 | *scriptPubKey* (hex) | `0014b2f771c370ccf219cd3059cda92bdf7f00cf2103` 195 | User confirmation | False 196 | *commitmentData* | "" 197 | 198 | #### Proof of ownership (hex) 199 | 200 | `534c00190001a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad57070002483045022100e5eaf2cb0a473b4545115c7b85323809e75cb106175ace38129fd62323d73df30220363dbc7acb7afcda022b1f8d97acb8f47c42043cfe0595583aa26e30bc8b3bb50121032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b` 201 | 202 | Split into components: 203 | 204 | Name | Value 205 | ---------------|------ 206 | *versionMagic* | `534c0019` 207 | *flags* | `00` 208 | *n* | `01` 209 | *id* | `a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad5707` 210 | *scriptSig* | `00` 211 | *witness* | `02483045022100e5eaf2cb0a473b4545115c7b85323809e75cb106175ace3812`
`9fd62323d73df30220363dbc7acb7afcda022b1f8d97acb8f47c42043cfe0595`
`583aa26e30bc8b3bb50121032ef68318c8f6aaa0adec0199c69901f0db7d3485`
`eb38d9ad235221dc3d61154b` 212 | 213 | ### Test vector 2 (P2WPKH nested in BIP16 P2SH) 214 | 215 | #### Input parameters 216 | 217 | Parameter | Value 218 | -----------------------|------ 219 | BIP39 seed | "all all all all all all all all all all all all" 220 | Passphrase | "" 221 | Ownership ID key (hex) | `0a115a171e30f8a740bae6c4144bec5dc1099ffa79b83dfb8aa3501d094de585` 222 | Path | m/49'/0'/0'/1/0 223 | *scriptPubKey* (hex) | `a914b9ddc52a7d95ad46d474bfc7186d0150e15a499187` 224 | User confirmation | True 225 | *commitmentData* | "TREZOR" 226 | 227 | #### Proof of ownership (hex) 228 | 229 | `534c0019010192caf0b8daf78f1d388dbbceaec34bd2dabc31b217e32343663667f6694a3f4617160014e0cffbee1925a411844f44c3b8d81365ab51d03602483045022100a2649df21ed61bbae9aa488f041e39cf37d82af9c1050d9477faca6a963e6b0302204b24ea33fa7232c18305521bd6dafb82828ce6baab2e770991b350f40c47cb58012103a961687895a78da9aef98eed8e1f2a3e91cfb69d2f3cf11cbd0bb1773d951928` 230 | 231 | Split into components: 232 | 233 | Name | Value 234 | ---------------|------ 235 | *versionMagic* | `534c0019` 236 | *flags* | `01` 237 | *n* | `01` 238 | *id* | `92caf0b8daf78f1d388dbbceaec34bd2dabc31b217e32343663667f6694a3f46` 239 | *scriptSig* | `17160014e0cffbee1925a411844f44c3b8d81365ab51d036` 240 | *witness* | `02483045022100a2649df21ed61bbae9aa488f041e39cf37d82af9c1050d9477`
`faca6a963e6b0302204b24ea33fa7232c18305521bd6dafb82828ce6baab2e77`
`0991b350f40c47cb58012103a961687895a78da9aef98eed8e1f2a3e91cfb69d`
`2f3cf11cbd0bb1773d951928` 241 | 242 | ### Test vector 3 (P2PKH) 243 | 244 | #### Input parameters 245 | 246 | Parameter | Value 247 | -----------------------|------ 248 | BIP39 seed | "all all all all all all all all all all all all" 249 | Passphrase | "TREZOR" 250 | Ownership ID key (hex) | `2d773852e0959b3c1bac15bd3a8ad410e2c6720befb4f7f428d74bdd5d6e4f1d` 251 | Path | m/44'/0'/0'/1/0 252 | *scriptPubKey* (hex) | `76a9145a4deff88ada6705ed70835bc0db56a124b9cdcd88ac` 253 | User confirmation | False 254 | *commitmentData* | "" 255 | 256 | #### Proof of ownership (hex) 257 | 258 | `534c00190001ccc49ac5fede0efc80725fbda8b763d4e62a221c51cc5425076cffa7722c0bda6a47304402206682f40a12f3609a308acb872888470a07760f2f4790ee4ff62665a39c02a5fc022026f3f38a7c2b2668c2eff9cc1e712c7f254926a482bae411ad18947eba9fd21c012102f63159e21fbcb54221ec993def967ad2183a9c243c8bff6e7d60f4d5ed3b386500` 259 | 260 | Split into components: 261 | 262 | Name | Value 263 | ---------------|------ 264 | *versionMagic* | `534c0019` 265 | *flags* | `00` 266 | *n* | `01` 267 | *id* | `ccc49ac5fede0efc80725fbda8b763d4e62a221c51cc5425076cffa7722c0bda` 268 | *scriptSig* | `6a47304402206682f40a12f3609a308acb872888470a07760f2f4790ee4ff626`
`65a39c02a5fc022026f3f38a7c2b2668c2eff9cc1e712c7f254926a482bae411`
`ad18947eba9fd21c012102f63159e21fbcb54221ec993def967ad2183a9c243c`
`8bff6e7d60f4d5ed3b3865` 269 | *witness* | `00` 270 | 271 | ### Test vector 4 (P2PWSH 2-of-3 multisig) 272 | 273 | #### Input parameters 274 | 275 | Parameter | Value 276 | -------------------------|------ 277 | BIP39 seed 1 | "all all all all all all all all all all all all" 278 | Passphrase 1 | "" 279 | Ownership ID key 1 (hex) | `0a115a171e30f8a740bae6c4144bec5dc1099ffa79b83dfb8aa3501d094de585` 280 | BIP39 seed 2 | "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" 281 | Passphrase 2 | "" 282 | Ownership ID key 2 (hex) | `cd50559c65666fd381e823b82fff04763465062c1ff4c93d3e147a306f884130` 283 | BIP39 seed 3 | "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong" 284 | Passphrase 3 | "" 285 | Ownership ID key 3 (hex) | `64b3e4f003fd7dea4168dd19f85410ac3b1844abd1d7f9f3a74254a7852af725` 286 | Path | m/84'/0'/0'/1/0 287 | *scriptPubKey* (hex) | `00209149b5bcaae8c876f1997ef6b60ec197475217fd3e736d4c54fcf49fe4f5213a` 288 | User confirmation | False 289 | *commitmentData* | "TREZOR" 290 | 291 | #### Proof of ownership (hex) 292 | 293 | `534c00190003309c4ffec5c228cc836b51d572c0a730dbabd39df9f01862502ac9eabcdeb94a46307177b959c48bf2eb516e0463bb651aad388c7f8f597320df7854212fa3443892f9573e08cedff9160b243759520733a980fed45b131a8bba171317ae5d94000400483045022100d2798dc4dcf90c51372141f5d870e39ae7408c72f82ab78761bf4cfa5b793d2902203962bf7d753ef2d28496b36e7153e57ab5dc5bc4de569345d4f135e8f772484101483045022100b33bee50faaefef3069d05333fbb271b7f361b95918ca0f90036b8e7af93b88d022016d86af97841e8049e065ee02608e353654e3c03f989f30f3f87fe160cce479f01695221032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b2103025324888e429ab8e3dbaf1f7802648b9cd01e9b418485c5fa4c1b9b5700e1a621033057150eb57e2b21d69866747f3d377e928f864fa88ecc5ddb1c0e501cce3f8153ae` 294 | 295 | Split into components: 296 | 297 | Name | Value 298 | -----------------|------ 299 | *versionMagic* | `534c0019` 300 | *flags* | `00` 301 | *n* | `03` 302 | *id*1 | `309c4ffec5c228cc836b51d572c0a730dbabd39df9f01862502ac9eabcdeb94a` 303 | *id*2 | `46307177b959c48bf2eb516e0463bb651aad388c7f8f597320df7854212fa344` 304 | *id*3 | `3892f9573e08cedff9160b243759520733a980fed45b131a8bba171317ae5d94` 305 | *scriptSig* | `00` 306 | *witness* | `0400483045022100d2798dc4dcf90c51372141f5d870e39ae7408c72f82ab787`
`61bf4cfa5b793d2902203962bf7d753ef2d28496b36e7153e57ab5dc5bc4de56`
`9345d4f135e8f772484101483045022100b33bee50faaefef3069d05333fbb27`
`1b7f361b95918ca0f90036b8e7af93b88d022016d86af97841e8049e065ee026`
`08e353654e3c03f989f30f3f87fe160cce479f01695221032ef68318c8f6aaa0`
`adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b2103025324888e42`
`9ab8e3dbaf1f7802648b9cd01e9b418485c5fa4c1b9b5700e1a621033057150e`
`b57e2b21d69866747f3d377e928f864fa88ecc5ddb1c0e501cce3f8153ae` 307 | 308 | ## References 309 | 310 | * [bitcoin-dev](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-August/014843.html): Original mailing list thread 311 | * [BIP-0174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): Partially Signed Bitcoin Transaction Format 312 | * [BIP-0322](https://github.com/bitcoin/bips/blob/f9e95849f337358cd89c83b948fbede3875481c3/bip-0322.mediawiki): Generic Signed Message Format from March 25th 2020 313 | --------------------------------------------------------------------------------