├── .gitattributes ├── .travis.yml ├── LICENSE ├── README.md ├── check.sh ├── markdownlint.json ├── slip-0000.md ├── slip-0010.md ├── slip-0010 ├── test.py └── testvectors.py ├── slip-0011.md ├── slip-0012.md ├── slip-0013.md ├── slip-0014.md ├── slip-0014 └── addresses.md ├── slip-0015.md ├── slip-0015 ├── 1_masterkey.py ├── 2_accountkey.py ├── 3_decrypt.py └── 4_encrypt.py ├── slip-0016.md ├── slip-0017.md ├── slip-0019.md ├── slip-0020.md ├── slip-0021.md ├── slip-0022.md ├── slip-0023.md ├── slip-0024.md ├── slip-0025.md ├── slip-0032.md ├── slip-0039.md ├── slip-0039 ├── lagrange.png ├── secret_sharing_1.png ├── secret_sharing_2.png ├── secret_sharing_3.png ├── secret_sharing_4.png ├── shamir-curve.svg ├── test_wordlist.sh └── wordlist.txt ├── slip-0044.md ├── slip-0048.md ├── slip-0048 └── testvectors.py ├── slip-0077.md ├── slip-0132.md └── slip-0173.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.md linguist-detectable 2 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SatoshiLabs Improvement Proposals 2 | 3 | SatoshiLabs projects need a way how to document their technical decisions and features. 4 | For some of them Bitcoin Improvement Proposal (BIP) is not a right place because 5 | their range and implications are outside of the scope of Bitcoin and cryptocurrencies. 6 | 7 | SLIP repository is an extension to Bitcoin Improvement Proposal (BIP) process 8 | and contains the documents that are unsuitable for submission to BIP repository. 9 | 10 | Each SLIP should provide a concise technical specification of the feature and a rationale for the feature. 11 | 12 | | Number | Title | Type | Status | 13 | |---------------------------|-----------------------------------------------------------------------|---------------|----------| 14 | | [SLIP-0000](slip-0000.md) | SLIP Template | Informational | Accepted | 15 | | [SLIP-0010](slip-0010.md) | Universal private key derivation from master private key | Standard | Final | 16 | | [SLIP-0011](slip-0011.md) | Symmetric encryption of key-value pairs using deterministic hierarchy | Standard | Final | 17 | | [SLIP-0012](slip-0012.md) | Public key encryption using deterministic hierarchy | Standard | Draft | 18 | | [SLIP-0013](slip-0013.md) | Authentication using deterministic hierarchy | Standard | Final | 19 | | [SLIP-0014](slip-0014.md) | Stress Test Deterministic Wallet | Informational | Active | 20 | | [SLIP-0015](slip-0015.md) | Format for Bitcoin metadata and its encryption in HD wallets | Standard | Final | 21 | | [SLIP-0016](slip-0016.md) | Format for password storage and its encryption | Standard | Final | 22 | | [SLIP-0017](slip-0017.md) | Elliptic Curve Diffie-Hellman using deterministic hierarchy | Standard | Final | 23 | | SLIP-0018 | reserved (CoSi) | Standard | Draft | 24 | | [SLIP-0019](slip-0019.md) | Proof of Ownership | Standard | Accepted | 25 | | [SLIP-0020](slip-0020.md) | Proof of User Confirmation | Standard | Draft | 26 | | [SLIP-0021](slip-0021.md) | Hierarchical derivation of symmetric keys | Standard | Final | 27 | | [SLIP-0022](slip-0022.md) | FIDO2 Credential ID format for HD wallets | Standard | Final | 28 | | [SLIP-0023](slip-0023.md) | Cardano HD master node derivation from a master seed | Standard | Final | 29 | | [SLIP-0024](slip-0024.md) | Trezor payment request format | Standard | Draft | 30 | | [SLIP-0025](slip-0025.md) | Key derivation for CoinJoin accounts | Standard | Draft | 31 | | SLIP-0026 | reserved (CoSi) | Standard | Draft | 32 | | [SLIP-0032](slip-0032.md) | Extended serialization format for BIP-32 wallets | Standard | Draft | 33 | | [SLIP-0039](slip-0039.md) | Shamir's Secret-Sharing for Mnemonic Codes | Standard | Final | 34 | | [SLIP-0044](slip-0044.md) | Registered coin types for BIP-0044 | Standard | Active | 35 | | [SLIP-0048](slip-0048.md) | Deterministic key hierarchy for Graphene-based networks | Standard | Active | 36 | | [SLIP-0077](slip-0077.md) | Deterministic blinding key derivation for Confidential Transactions | Standard | Draft | 37 | | [SLIP-0132](slip-0132.md) | Registered HD version bytes for BIP-0032 | Standard | Active | 38 | | [SLIP-0173](slip-0173.md) | Registered human-readable parts for BIP-0173 | Standard | Active | 39 | 40 | --- 41 | 42 | This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/). 43 | -------------------------------------------------------------------------------- /check.sh: -------------------------------------------------------------------------------- 1 | echo "SLIP-0044 duplicates:" 2 | grep '^| [0-9]' slip-0044.md | cut -f 4 -d '|' | tr -d ' ' | sort | uniq -d 3 | 4 | echo "SLIP-0044 uppercase:" 5 | grep '0x80[^ ]*[A-F]' slip-0044.md 6 | -------------------------------------------------------------------------------- /markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD004": false, 3 | "MD013": false, 4 | "MD024": false, 5 | "MD029": false, 6 | "MD033": false, 7 | "MD040": false 8 | } 9 | -------------------------------------------------------------------------------- /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-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-0010/testvectors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import hashlib 4 | import hmac 5 | from cryptography.hazmat.primitives import serialization 6 | from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey 7 | from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey 8 | from cryptography.hazmat.primitives.asymmetric import ec 9 | from base58 import b58encode_check 10 | 11 | SECP256K1_ORDER = int("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) 12 | SECP256R1_ORDER = int("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16) 13 | privdev = 0x80000000 14 | 15 | # mode 0 - compatible with BIP32 private derivation 16 | def seed2hdnode(seed, curve, modifier, curve_order): 17 | k = seed 18 | while True: 19 | h = hmac.new(modifier, seed, hashlib.sha512).digest() 20 | key, chaincode = h[:32], h[32:] 21 | a = int.from_bytes(key, 'big') 22 | if (curve in ('ed25519', 'curve25519')): 23 | break 24 | if (a < curve_order and a != 0): 25 | break 26 | seed = h 27 | #print('RETRY seed: ' + seed.hex()) 28 | return (key, chaincode) 29 | 30 | def fingerprint(publickey): 31 | h = hashlib.new('ripemd160', hashlib.sha256(publickey).digest()).digest() 32 | return h[:4] 33 | 34 | def b58xprv(parent_fingerprint, private_key, chain, depth, childnr): 35 | raw = (b'\x04\x88\xad\xe4' + 36 | bytes([depth]) + parent_fingerprint + childnr.to_bytes(4, 'big') + 37 | chain + b'\x00' + private_key) 38 | return b58encode_check(raw).decode() 39 | 40 | def b58xpub(parent_fingerprint, public_key, chain, depth, childnr): 41 | raw = (b'\x04\x88\xb2\x1e' + 42 | bytes([depth]) + parent_fingerprint + childnr.to_bytes(4, 'big') + 43 | chain + public_key) 44 | return b58encode_check(raw).decode() 45 | 46 | def publickey(private_key, curve): 47 | if curve == 'ed25519': 48 | sk = Ed25519PrivateKey.from_private_bytes(private_key) 49 | key_encoding = serialization.Encoding.Raw 50 | key_format = serialization.PublicFormat.Raw 51 | prefix = b'\x00' 52 | elif curve == 'curve25519': 53 | sk = X25519PrivateKey.from_private_bytes(private_key) 54 | key_encoding = serialization.Encoding.Raw 55 | key_format = serialization.PublicFormat.Raw 56 | prefix = b'\x00' 57 | else: 58 | sk = ec.derive_private_key(int.from_bytes(private_key, 'big'), curve) 59 | key_encoding = serialization.Encoding.X962 60 | key_format = serialization.PublicFormat.CompressedPoint 61 | prefix = b'' 62 | return prefix + sk.public_key().public_bytes(key_encoding, key_format) 63 | 64 | def derive(parent_key, parent_chaincode, i, curve, curve_order): 65 | assert len(parent_key) == 32 66 | assert len(parent_chaincode) == 32 67 | k = parent_chaincode 68 | if ((i & privdev) != 0): 69 | key = b'\x00' + parent_key 70 | else: 71 | key = publickey(parent_key, curve) 72 | d = key + i.to_bytes(4, 'big') 73 | while True: 74 | h = hmac.new(k, d, hashlib.sha512).digest() 75 | key, chaincode = h[:32], h[32:] 76 | if curve in ('ed25519', 'curve25519'): 77 | break 78 | #print('I: ' + h.hex()) 79 | a = int.from_bytes(key, 'big') 80 | key = (a + int.from_bytes(parent_key, 'big')) % curve_order 81 | if (a < curve_order and key != 0): 82 | key = key.to_bytes(32, 'big') 83 | break 84 | d = b'\x01' + h[32:] + i.to_bytes(4, 'big') 85 | #print('a failed: ' + h[:32].hex()) 86 | #print('RETRY: ' + d.hex()) 87 | 88 | return (key, chaincode) 89 | 90 | def get_curve_info(curvename): 91 | if curvename == 'secp256k1': 92 | return (ec.SECP256K1(), b'Bitcoin seed', SECP256K1_ORDER) 93 | if curvename == 'nist256p1': 94 | return (ec.SECP256R1(), b'Nist256p1 seed', SECP256R1_ORDER) 95 | if curvename == 'ed25519': 96 | return ('ed25519', b'ed25519 seed', None) 97 | if curvename == 'curve25519': 98 | return ('curve25519', b'curve25519 seed', None) 99 | raise BaseException('unsupported curve: '+curvename) 100 | 101 | def show_testvector(name, curvename, seedhex, derivationpath): 102 | curve, seedmodifier, curve_order = get_curve_info(curvename) 103 | master_seed = bytes.fromhex(seedhex) 104 | k,c = seed2hdnode(master_seed, curve, seedmodifier, curve_order) 105 | p = publickey(k, curve) 106 | fpr = b'\x00\x00\x00\x00' 107 | path = 'm' 108 | print("### "+name+" for "+curvename) 109 | print() 110 | print("Seed (hex): " + seedhex) 111 | print() 112 | print('* Chain ' + path) 113 | print(' * fingerprint: ' + fpr.hex()) 114 | print(' * chain code: ' + c.hex()) 115 | print(' * private: ' + k.hex()) 116 | print(' * public: ' + p.hex()) 117 | depth = 0 118 | for i in derivationpath: 119 | if curve in ('ed25519', 'curve25519'): 120 | # no public derivation for ed25519 and curve25519 121 | i = i | privdev 122 | fpr = fingerprint(p) 123 | depth = depth + 1 124 | path = path + "/" + str(i & (privdev-1)) 125 | if ((i & privdev) != 0): 126 | path = path + "H" 127 | k,c = derive(k, c, i, curve, curve_order) 128 | p = publickey(k, curve) 129 | print('* Chain ' + path) 130 | print(' * fingerprint: ' + fpr.hex()) 131 | print(' * chain code: ' + c.hex()) 132 | print(' * private: ' + k.hex()) 133 | print(' * public: ' + p.hex()) 134 | #print(b58xprv(fpr, k, c, depth, i)) 135 | #print(b58xpub(fpr, p, c, depth, i)) 136 | print() 137 | 138 | def show_testvectors(name, curvenames, seedhex, derivationpath): 139 | for curvename in curvenames: 140 | show_testvector(name, curvename, seedhex, derivationpath) 141 | 142 | 143 | curvenames = ['secp256k1', 'nist256p1', 'ed25519', 'curve25519']; 144 | 145 | show_testvectors("Test vector 1", curvenames, 146 | '000102030405060708090a0b0c0d0e0f', 147 | [privdev + 0, 1, privdev + 2, 2, 1000000000]) 148 | show_testvectors("Test vector 2", curvenames, 149 | 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', 150 | [0, privdev + 2147483647, 1, privdev + 2147483646, 2]) 151 | 152 | show_testvectors("Test derivation retry", ['nist256p1'], 153 | '000102030405060708090a0b0c0d0e0f', 154 | [privdev + 28578, 33941]) 155 | 156 | show_testvectors("Test seed retry", ['nist256p1'], 157 | 'a7305bc8df8d0951f0cb224c0e95d7707cbdf2c6ce7e8d481fec69c7ff5e9446', 158 | []) 159 | 160 | -------------------------------------------------------------------------------- /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-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-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 SLIP-0010. 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. `HD 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-0043: Purpose Field for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) 100 | * [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax](https://tools.ietf.org/html/rfc3986) 101 | * [SLIP-0010: Universal private key derivation from master private key](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) 102 | -------------------------------------------------------------------------------- /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 | ## Bitcoin Wallets 27 | 28 | root node: 29 | 30 | ``` 31 | mnemonic: all all all all all all all all all all all all 32 | 33 | xprv9s21ZrQH143K2rbkN6QpF6ZB3QQcyJA6aYbagMp6i8y831VVvpfcWNWqg5DM6GxSn66UDQUrgRgQEsLPZJC3APkPsQjxB7ndNMgj5R5HLmo 34 | ``` 35 | 36 | ### Bitcoin: Legacy / P2PKH / BIP44 37 | 38 | ``` 39 | m/44'/0'/0' 40 | 41 | xprv9xj9UhHNKHr6kJKJBVj82ZxFrbfhczBDUHyVj7kHGAiZqAeUenz2JhrphnMMYVKcWcVPFJESngtKsVa4FYEvFfWUTtZThCoZdwDeS9qQnqm 42 | xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy 43 | 44 | pkh([5c9e228d/44'/0'/0']xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy/0/*)#vzuemqzv 45 | pkh([5c9e228d/44'/0'/0']xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy/1/*)#akecx4j5 46 | 47 | pkh([5c9e228d/44'/0'/0']xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy/<0;1>/*)#t3pfpx6p 48 | ``` 49 | 50 | [link to btc1.trezor.io](https://btc1.trezor.io/xpub/xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy) 51 | 52 | #### Addresses 53 | 54 | index | address | private key 55 | ------|--------------------------------------|------------ 56 | 0 | `1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL` | `L1KjqxZkUwdXaKNL15F2jJZVZpgi2HkHPHGyqTrQNNegyZez3A7Z` 57 | 1 | `1GWFxtwWmNVqotUPXLcKVL2mUKpshuJYo` | `KyBcuurcaJw6NqnZsmtpDqjbsS67PTXEZAK9QyFEDsyYjmNJJozj` 58 | 2 | `1Eni8JFS4yA2wJkicc3yx3QzCNzopLybCM` | `L3yYwqub7bYq6qKkPf9UAE7uuZYV8adAHvEaceXY9fKX8G7FDCoZ` 59 | 3 | `124dT55Jqpj9AKTyJnTX6G8RkUs7ReTzun` | `L2SNnZeTNHwgr9mayyHLZxmpyQN4SNbrxjBf9Rwq5Fvu2wwTm476` 60 | 4 | `15T9DSqc6wjkPxcr2MNVSzF9JAePdvS3n1` | `L4jzKXRhQXesPeUSUNi7EMHAEBFzwJuAkZsNi5tja9rLxgGajwPv` 61 | 5 | `1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ` | `L1N67rzEMn6fqvhkFeDnt11LMxYdGZtGQgdYVuASNpmQRawgbJEN` 62 | 6 | `1PogPE3bXc84abzEuM2rJEZf2vCbCEZzXz` | `L3Y5pgT2ewKqdqh6kcGDQ7YHFoW5Vh4xErrPqb4Yjb5re9QYZw7D` 63 | 7 | `176U2WABbj4h5PCrxE963wmxzXd2Mw6bP4` | `L2RpVajejxusxUXqLHTFJAyp1nzJnT2xuJpfm7Uah4GGUHz7XD58` 64 | 8 | `1HRZDR7CmLnq59w6mtzNa7SHtVWPSxdgKA` | `Kx8nBDjAkXkykD62AF8XjP8W5Z4a79iZC8Z7axyDWXsZTcn5agzM` 65 | 9 | `1MPdvYLzcekvEzAB7DmiHa1oU8Foh4KUw8` | `L1xWyxmCkjsB2Z9wnjoZ5TGabeg8KbpZt1PjgVsKA9pn3L7JCiTs` 66 | 67 | ### Bitcoin: Legacy SegWit / P2SH-P2WPKH / BIP49 68 | 69 | ``` 70 | m/49'/0'/0' 71 | 72 | xprv9yVyTu1dmn2ekCQYnV4FhXrVNbnJKBbAwXgDaqmhcjyxHaz31UTdLYGqdwFCBv8LA1BafJUWeiQ6J1uUSU5ebGK6GmcFiJsb3bYfpfpLyva 73 | xpub6CVKsQYXc9awxgV1tWbG4foDvdcnieK2JkbpPEBKB5WwAPKBZ1mstLbKVB4ov7QzxzjaxNK6EfmNY5Jsk2cG26EVcEkycGW4tchT2dyUhrx 74 | 75 | yprvAJLEmZgYvTa8bVbfcqqsucwzYZvkFoafreCSNEfazkMqLgoGG8dBxbvyf9CnBpnFZeJPQn557NkeBJX3AAVfPVzh97JgJDh5KKcKDCEbbzm 76 | ypub6XKbB5DSkq8Royg8isNtGktj6bmEfGJXDs83Ad5CZ5tpDV8QofwSWQFTWP2Pv24vNdrPhquehL7vRMvSTj2GpKv6UaTQCBKZALm6RJAmxG6 77 | 78 | sh(wpkh([5c9e228d/49'/0'/0']xpub6CVKsQYXc9awxgV1tWbG4foDvdcnieK2JkbpPEBKB5WwAPKBZ1mstLbKVB4ov7QzxzjaxNK6EfmNY5Jsk2cG26EVcEkycGW4tchT2dyUhrx/0/*))#jkfqtdfw 79 | sh(wpkh([5c9e228d/49'/0'/0']xpub6CVKsQYXc9awxgV1tWbG4foDvdcnieK2JkbpPEBKB5WwAPKBZ1mstLbKVB4ov7QzxzjaxNK6EfmNY5Jsk2cG26EVcEkycGW4tchT2dyUhrx/1/*))#8h8knju3 80 | 81 | sh(wpkh([5c9e228d/49'/0'/0']xpub6CVKsQYXc9awxgV1tWbG4foDvdcnieK2JkbpPEBKB5WwAPKBZ1mstLbKVB4ov7QzxzjaxNK6EfmNY5Jsk2cG26EVcEkycGW4tchT2dyUhrx/<0;1>/*))#a49xle58 82 | ``` 83 | 84 | [link to btc1.trezor.io](https://btc1.trezor.io/xpub/ypub6XKbB5DSkq8Royg8isNtGktj6bmEfGJXDs83Ad5CZ5tpDV8QofwSWQFTWP2Pv24vNdrPhquehL7vRMvSTj2GpKv6UaTQCBKZALm6RJAmxG6) 85 | 86 | #### Addresses 87 | 88 | index | address | private key 89 | ------|--------------------------------------|------------ 90 | 0 | `3L6TyTisPBmrDAj6RoKmDzNnj4eQi54gD2` | `L1xY6RmpnGn7r5bhQCrDXFTqVGFY7e1p62Rw5yw6bNzKUzRLD1tw` 91 | 1 | `3GMMgFUQiYTYQhuHQuZfQoXPvW3GPqfGmD` | `Kx2KfpCa6Aewb1zxPBt5ex8MFNKk3SrJaeYRVjNRCUg7zALXDy8w` 92 | 2 | `3BKbtvJtLSjnSoGUYTeQ17tMKTuyqbUV7P` | `L3L1oYXQbPmgpgvyB6BzM5PihfAvZfi3pFMZfppVQscM1zQokdtg` 93 | 3 | `3Dyf1D6pVR6ZAQYN1th6ehgS1uqgGk1TGh` | `L3w2TxQpwJCkEhM96o3DTFTC1Pv67kpQ4Nwp4jD9n8oHvFQ7KsSB` 94 | 4 | `33wLRyxHFtrXLF7Aun38Dctw5QyiBdruK2` | `L1K9dsgY46AgcGsNYdqJCEQbKBvvSuRz1MrWu3ATgyRaq3vVprtn` 95 | 5 | `32pKKUD5TKyqb4kzPorJnY8XhiLaHBKni1` | `L2ET81wAcxm4vU22w7mEU2EC9bf5aNr1XaMNA1B9GkMHr5YT99a5` 96 | 6 | `3NCRi181wMB1v9gPyms9WDruKemBfrE9rQ` | `KzyfHMxPYBmwgy3pJtqj2UK6xbqzA8TDZUdapXMCQidk2zLg1zVC` 97 | 7 | `32d6ze9Be4J45ERomziXxGWXxLobAAQq85` | `L3i75zyVQKi5ZBjHMghQSgCx1HYQnYjZh1N2Y6gBLciEa7mqYqvN` 98 | 8 | `3FNTNKoAcXDUTUSNAtVTcvAehwQLyJSmP9` | `L5SXQN7L1KNFTVurn4xaevP494RYRWNSqVUE2cUFMFnpQTSPHNYG` 99 | 9 | `3L55P4LZsyKYUw5Aqy6DPky6ySw3g34TQS` | `Kzi8YhDogNJKVis8r5z4Lq8M6rSNudAG5p63pF45i9fQQb3KCAeC` 100 | 101 | ### Bitcoin: SegWit / P2WPKH / BIP84 102 | 103 | ``` 104 | m/84'/0'/0' 105 | 106 | xprv9zE7ynHaxhGKkZyFCd2jEJYmiZ5X2tdvYHhkVKsHBybspXSX4GTeD9BcR2b4PmvKShEQtFh6L8pRyu8SxPdumPhaQiBUQQiCSsEhnaadaYm 107 | xpub6DDUPHpUo4pcy43iJeZjbSVWGav1SMMmuWdMHiGtkK8rhKmfbomtkwW6GKs1GGAKehT6QRocrmda3WWxXawpjmwaUHfFRXuKrXSapdckEYF 108 | 109 | zprvAdteb7dRG4MHTAMUsLbyeUjn4VNQv8cvNWkC47f3wzMdvj4yZanmTGVtTSWEPbEAFyU2PCtDFTXXkUMaPnTwMs4n9PaKaEMAzKMzZguzwHG 110 | zpub6rszzdAK6RuafeRwyN8z1cgWcXCuKbLmjjfnrW4fWKtcoXQ8787214pNJjnBG5UATyghuNzjn6Lfp5k5xymrLFJnCy46bMYJPyZsbpFGagT 111 | 112 | wpkh([5c9e228d/84'/0'/0']xpub6DDUPHpUo4pcy43iJeZjbSVWGav1SMMmuWdMHiGtkK8rhKmfbomtkwW6GKs1GGAKehT6QRocrmda3WWxXawpjmwaUHfFRXuKrXSapdckEYF/0/*)#l4dc6ccr 113 | wpkh([5c9e228d/84'/0'/0']xpub6DDUPHpUo4pcy43iJeZjbSVWGav1SMMmuWdMHiGtkK8rhKmfbomtkwW6GKs1GGAKehT6QRocrmda3WWxXawpjmwaUHfFRXuKrXSapdckEYF/1/*)#wpge8dgm 114 | 115 | wpkh([5c9e228d/84'/0'/0']xpub6DDUPHpUo4pcy43iJeZjbSVWGav1SMMmuWdMHiGtkK8rhKmfbomtkwW6GKs1GGAKehT6QRocrmda3WWxXawpjmwaUHfFRXuKrXSapdckEYF/<0;1>/*)#tdqj4vr6 116 | ``` 117 | 118 | [link to btc1.trezor.io](https://btc1.trezor.io/xpub/zpub6rszzdAK6RuafeRwyN8z1cgWcXCuKbLmjjfnrW4fWKtcoXQ8787214pNJjnBG5UATyghuNzjn6Lfp5k5xymrLFJnCy46bMYJPyZsbpFGagT) 119 | 120 | #### Addresses 121 | 122 | index | address | private key 123 | ------|----------------------------------------------|------------ 124 | 0 | `bc1qannfxke2tfd4l7vhepehpvt05y83v3qsf6nfkk` | `Kycvq5CiKukoBWJjN3WEduoHnE6pKWrQPM7XuiLEkbgLuQgEzZPu` 125 | 1 | `bc1q7e6qu5smalrpgqrx9k2gnf0hgjyref5p36ru2m` | `Kz4p2JcERCPT6LADX5pDmV1XNtnskABTaCFQb1hyNuWDqY43HuwE` 126 | 2 | `bc1q5f2lvs7t29wv8nwssse6a4f6099sc3nagchqyc` | `KxXM7XXwK8G1yZpw5o8tqaA5Ria5R3WxX78zbdPdg3Ncp9mgHiur` 127 | 3 | `bc1q6hr68ewf72l6r7cj6ut286x0xkwg5706jq450u` | `KyGV2ApxE2gLmCukQbjKAKKrcGKBCGSRy2itnyXDoxcdjsdd9vXH` 128 | 4 | `bc1q7zql632newlfv9rt269jyxdn30370rh4kp23pd` | `L5gUrfBMftHbbn6tUaHNHkNcPxpz6niJsdCubAMHTaxU759RDY6N` 129 | 5 | `bc1qfcjv620stvtzjeelg26ncgww8ks49zy8lracjz` | `L3YbRwxjxLx9SwcKYyaKXWPtR3pqbPdzMjaTHv6oi62jETv6VNvC` 130 | 6 | `bc1quqgq44wq0zjh6d920zs42nsy4n4ev5vt8nxke4` | `L1i1MqdvaTpcaPaHXfgMkxLU7Mq6DZHRzs54AmdAYNstE4vRRT2i` 131 | 7 | `bc1qunyzxr3gfcg7ggxp5vpxwm3q7t3xc52rcaupu4` | `KzkvQCu5ERcFcd6HBicdcDEom3MEaP3ptRLeHqnG6X1LU3jj7vjh` 132 | 8 | `bc1q2glg28yag4rdgrd0hj5ntdvva8cgrjdsku5prc` | `KyQf4uHNM1eskde2jJ7XwrXDe8TD9DAML5UTp3uxA7uzbWSY1NzZ` 133 | 9 | `bc1q9z4cdmrgtfjsp34dmtvha98shje83jjn2t27z5` | `L5o7HpPciFxK9QrJu2tWg6aVTK89KjLHizHPwwAfqVX2qyzxqmrB` 134 | 135 | ### Bitcoin: Taproot / P2TR / BIP86 136 | 137 | ``` 138 | m/86'/0'/0' 139 | 140 | xprv9xwmiZmq343K7HjUZAPMQ51qhFy8vKHeTYWApWMgkTp9LFtrRqkam7p5mwDVcXiaK97CMumfGTqmSgxpWE2yb9LTxmbT1Cnrvq4dYthBjxm 141 | xpub6Bw885JisRbcKmowfBvMmCxaFHodKn1VpmRmctmJJoM8D4DzyP4qJv8ZdD9V9r3SSGjmK2KJEDnvLH6f1Q4HrobEvnCeKydNvf1eir3RHZk 142 | 143 | tr([5c9e228d/86'/0'/0']xpub6Bw885JisRbcKmowfBvMmCxaFHodKn1VpmRmctmJJoM8D4DzyP4qJv8ZdD9V9r3SSGjmK2KJEDnvLH6f1Q4HrobEvnCeKydNvf1eir3RHZk/0/*)#d8jj22qr 144 | tr([5c9e228d/86'/0'/0']xpub6Bw885JisRbcKmowfBvMmCxaFHodKn1VpmRmctmJJoM8D4DzyP4qJv8ZdD9V9r3SSGjmK2KJEDnvLH6f1Q4HrobEvnCeKydNvf1eir3RHZk/1/*)#unhnhlsm 145 | 146 | tr([5c9e228d/86'/0'/0']xpub6Bw885JisRbcKmowfBvMmCxaFHodKn1VpmRmctmJJoM8D4DzyP4qJv8ZdD9V9r3SSGjmK2KJEDnvLH6f1Q4HrobEvnCeKydNvf1eir3RHZk/<0;1>/*)#4swej4wz 147 | ``` 148 | 149 | [link to btc1.trezor.io](https://btc1.trezor.io/xpub/tr(xpub6Bw885JisRbcKmowfBvMmCxaFHodKn1VpmRmctmJJoM8D4DzyP4qJv8ZdD9V9r3SSGjmK2KJEDnvLH6f1Q4HrobEvnCeKydNvf1eir3RHZk)) 150 | 151 | #### Addresses 152 | 153 | index | address | private key 154 | ------|------------------------------------------------------------------|------------ 155 | 0 | `bc1ptxs597p3fnpd8gwut5p467ulsydae3rp9z75hd99w8k3ljr9g9rqx6ynaw` | TBD 156 | 1 | `bc1plca7n9vs7d906nwlqyvk0d0jxnxss6x7w3x2y879quuvj8xn3p3s7vrrl2` | TBD 157 | 2 | `bc1pks4em3l8vg4zyk5xpcmgygh7elkhu03z3fqj48a2a2lv948cn4hsyltl3h` | TBD 158 | 3 | `bc1pvlme5mvcme0mqvfxknqr4mmcajthd9c9vqwknfghgvnsdt0ghtyquf66nq` | TBD 159 | 4 | `bc1pu4kdwq4jvpk3psqt6tw38fax7l20xj8y6gtzdgm9dj2amgy6t77sn420ak` | TBD 160 | 5 | `bc1p4w7pr3hx7ufuwpl7wj8z70kcdgu3uz5rnunhqv242629xskngyhstt8kny` | TBD 161 | 6 | `bc1p6rna8q8jpqj88pc0na5y4c2t574xrr6r4vfl7pw3zfmt0fyvyweskhh52w` | TBD 162 | 7 | `bc1pfqpkg5evfvqu0yjczwrm8vr8dzxmg8cpr8t5fw0whcv8r68tvx0swws8nt` | TBD 163 | 8 | `bc1pqveghnerewvk8frrs9s4ha5ta8yzycu5zfdmez4jp4dxkdvpaspqenr5dy` | TBD 164 | 9 | `bc1pkef3scnk7prtlpklpk586u3n3fvhe4hv2lvmggf8dx7sdwk6l6pq7j6u8q` | TBD 165 | 166 | ## Bitcoin Testnet Wallets 167 | 168 | root node: 169 | 170 | ``` 171 | mnemonic: all all all all all all all all all all all all 172 | 173 | tprv8ZgxMBicQKsPdfqH2fGKQkBAMXpqCpC6v6WhYnEZC7TbpcEavC1N27tHbFP16eLm9XdFDW6cqnGChit8gWXyyT1zQ3xFqUWgHTS9XBQw3j5 174 | ``` 175 | 176 | ### Bitcoin Testnet: Legacy / P2PKH / BIP44 177 | 178 | ``` 179 | m/44'/1'/0' 180 | 181 | tprv8gdjtqr3TjNXgxpdi4LurDeG1Z8rQR2cGXYbaifKAPypiaF8hG5k5XxT7bTsjdkN9ERUkLVb47tvJ7sYRsJrkbbFf2UTRqAkkGRcaWEhRuY 182 | tpubDDKn3FtHc74CaRrRbi1WFdJNaaenZkDWqq9NsEhcafnDZ4VuKeuLG2aKHm5SuwuLgAhRkkfHqcCxpnVNSrs5kJYZXwa6Ud431VnevzzzK3U 183 | 184 | pkh([5c9e228d/44'/1'/0']tpubDDKn3FtHc74CaRrRbi1WFdJNaaenZkDWqq9NsEhcafnDZ4VuKeuLG2aKHm5SuwuLgAhRkkfHqcCxpnVNSrs5kJYZXwa6Ud431VnevzzzK3U/0/*)#k65gljcw 185 | pkh([5c9e228d/44'/1'/0']tpubDDKn3FtHc74CaRrRbi1WFdJNaaenZkDWqq9NsEhcafnDZ4VuKeuLG2aKHm5SuwuLgAhRkkfHqcCxpnVNSrs5kJYZXwa6Ud431VnevzzzK3U/1/*)#8w3fz8gk 186 | 187 | pkh([5c9e228d/44'/1'/0']tpubDDKn3FtHc74CaRrRbi1WFdJNaaenZkDWqq9NsEhcafnDZ4VuKeuLG2aKHm5SuwuLgAhRkkfHqcCxpnVNSrs5kJYZXwa6Ud431VnevzzzK3U/<0;1>/*)#jlq3k5tw 188 | ``` 189 | 190 | [link to tbtc1.trezor.io](https://tbtc1.trezor.io/xpub/tpubDDKn3FtHc74CaRrRbi1WFdJNaaenZkDWqq9NsEhcafnDZ4VuKeuLG2aKHm5SuwuLgAhRkkfHqcCxpnVNSrs5kJYZXwa6Ud431VnevzzzK3U) 191 | 192 | #### Addresses 193 | 194 | index | address | private key 195 | ------|--------------------------------------|------------ 196 | 0 | `mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q` | `cPigoY3hubxpXad1t5WmxpcQpmezLeCcbpA7EpyhDofFnein2wF5` 197 | 1 | `mopZWqZZyQc3F2Sy33cvDtJchSAMsnLi7b` | `cVN8eHRQh8r9THM2Mu5HCSjx6cfVdssqGL1KeiCKBwUouyf6K5F5` 198 | 2 | `mgswWyysmViMqYmn5XEj1pVz7rVUftVEBP` | `cUCiXe6qNE43rEJkSR9e1Tt37W5gQmmGeBiSmXzDbZgxbs5Z5nvK` 199 | 3 | `momtnzR3XqXgDSsFmd8gkGxUiHZLde3RmA` | `cTAi8RAF2htyUn3F921npbuJLSVdYfpfwqjwLEAPkqvFxLAF716k` 200 | 4 | `moE1dVYvebvtaMuNdXQKvu4UxUftLmS1Gt` | `cUmGFJMq5Vkh4rjKHe4J4S5adJH1E8xFJJ2ZARBSZNBVzYwj1RvH` 201 | 5 | `muXZYKRJFJ2qPegzV2GEzLqHxngJpzMrmT` | `cRHMG1RjgVWTdUNEgDD5oNEvQvBAha5N3YntnT7rC8yekePLGQwR` 202 | 6 | `mnY26FLTzfC94mDoUcyDJh1GVE3LuAUMbs` | `cS9rFFu8douRgweuQKLdF4QXpS3H1UeoNxZWTt6K874nt4sy56HX` 203 | 7 | `mgV9Z3YuSbxGb2b2Y1T6VCqtU2osui7vhG` | `cQ1Uh9vXLhaoEgPGUEGMoWACpzrVesmB8G4KdK5vZBnLBifyB29Q` 204 | 8 | `miLqfMwzis98J5vkjjhTiXVsrkAYwuxmts` | `cPwi3WVwjgr422fBeLa22UHwRkQEMZqoJBjevuosqd25yyYekEkF` 205 | 9 | `mhAacBq3SnXEpoxzEwKqfnQz1iYjxmGg9V` | `cRkkmKXgTmq3Je2B71Rn4HQxeo2hEqvtUeQ5r4Q7eKr5qtq6vzu4` 206 | 207 | ### Bitcoin Testnet: Legacy SegWit / P2SH-P2WPKH / BIP49 208 | 209 | ``` 210 | m/49'/1'/0' 211 | 212 | tprv8fbPeVsyzhdBvmTfb8BShTevk7eHVig91hJ3FUHqCXPFMxyMytfYDFLZvLc6C6xvbFRsa26tZXFLDLHigKKwZ1wbHMX9cFfQ2HHQh63C3k3 213 | tpubDCHRnuvE95JrpEVTUmr36sK3K9ADf3s3aztpXzL8coBeCTE8cHV8PjxS6SjWJM3GfPn798gyEa3dRPgjoUDSuNfuC9xz4PHznwKEk2XL7X1 214 | 215 | uprv8zRexAYu9PAfn4enRUy4uYkRv5njSLfdvopG2sBiaXm8R4nbEYq6qJzhwYZgC1cqztYgKVhT2Bbt6cuHQ1jxMFdC9hDaCAUtJ1M45hTgJAA 216 | upub5DR1Mg5nykixzYjFXWW5GghAU7dDqoPVJ2jrqFbL8sJ7Hs7jn69MP7KBnnmxn88GeZtnH8PRKV9w5MMSFX8AdEAoXY8Qd8BJPoXtpMeHMxJ 217 | 218 | sh(wpkh([5c9e228d/49'/1'/0']tpubDCHRnuvE95JrpEVTUmr36sK3K9ADf3s3aztpXzL8coBeCTE8cHV8PjxS6SjWJM3GfPn798gyEa3dRPgjoUDSuNfuC9xz4PHznwKEk2XL7X1/0/*))#qfh8hjq8 219 | sh(wpkh([5c9e228d/49'/1'/0']tpubDCHRnuvE95JrpEVTUmr36sK3K9ADf3s3aztpXzL8coBeCTE8cHV8PjxS6SjWJM3GfPn798gyEa3dRPgjoUDSuNfuC9xz4PHznwKEk2XL7X1/1/*))#4ge30d4c 220 | 221 | sh(wpkh([5c9e228d/49'/1'/0']tpubDCHRnuvE95JrpEVTUmr36sK3K9ADf3s3aztpXzL8coBeCTE8cHV8PjxS6SjWJM3GfPn798gyEa3dRPgjoUDSuNfuC9xz4PHznwKEk2XL7X1/<0;1>/*))#egxlxhl0 222 | ``` 223 | 224 | [link to tbtc1.trezor.io](https://tbtc1.trezor.io/xpub/upub5DR1Mg5nykixzYjFXWW5GghAU7dDqoPVJ2jrqFbL8sJ7Hs7jn69MP7KBnnmxn88GeZtnH8PRKV9w5MMSFX8AdEAoXY8Qd8BJPoXtpMeHMxJ) 225 | 226 | #### Addresses 227 | 228 | index | address | private key 229 | ------|---------------------------------------|------------ 230 | 0 | `2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp` | `cRgRJFubBbGF7mrYxbtVfYvRTw7nTuwAgCxQxW8sz7J3GUaFDpXy` 231 | 1 | `2Mt7P2BAfE922zmfXrdcYTLyR7GUvbwSEns` | `cNzuaocakTkP3uTfFeyxJaatdFFEi3eEXSeckjrPubeEtLc6LgKN` 232 | 2 | `2N6aUMgQk8y1zvoq6FeWFyotyj75WY9BGsu` | `cRFggMzpii7ZyrnvBaqyq1DE3Aw7yxeT2ZjaJ48GRzcWZYegWaxE` 233 | 3 | `2NA7tbZWM9BcRwBuebKSQe2xbhhF1paJwBM` | `cQEuKiCruVH89JimwRT7LkjPTJKDPRU5FLrzEoEUQqRDJbvVeEaV` 234 | 4 | `2N8RZMzvrUUnpLmvACX9ysmJ2MX3GK5jcQM` | `cUBFS7oSvLg5Lt3jx148obE4dPc3EU8hiwta11LXJipYHE1xD79m` 235 | 5 | `2MvUUSiQZDSqyeSdofKX9KrSCio1nANPDTe` | `cUfaGYiJKGBNawCzm7q4xbCzr3dwpTckdaMLxiNrEHoxQZWCGA6h` 236 | 6 | `2NBXaWu1HazjoUVgrXgcKNoBLhtkkD9Gmet` | `cNzV3JvVCSPsyh34NveJ5YCSE65QWyJNSTGr5LsMtEzgXmsncos5` 237 | 7 | `2N791Ttf89tMVw2maj86E1Y3VgxD9Mc7PU7` | `cNu1yCSQZuUo3qweP73EUu1peVh29xchhwbyBuqWgcAoho2AX9sE` 238 | 8 | `2NCJmwEq8GJm8t8GWWyBXAfpw7F2qZEVP5Y` | `cQjPz5n3UMGY6f2ZTY4EfC5mF7qpcrBXQfFW23xNNxTsUCc4pAse` 239 | 9 | `2NEgW71hWKer2XCSA8ZCC2VnWpB77L6bk68` | `cPb7wNHh9eQqECVdGFCLGTKkmdUjyk2FRdJspBAbKaNAvstZzNzZ` 240 | 241 | ### Bitcoin Testnet: SegWit / P2WPKH / BIP84 242 | 243 | ``` 244 | m/84'/1'/0' 245 | 246 | tprv8fs8xTNozVNnBjpLwdox39a8dNqR86VDbVtYDFtJk7HCbSrQDpW4ctKSz9f7J6MTYiHhRANPjvknG2RN5XtxaKmMdW18WUvZiQhHX1s8jmt 247 | tpubDCZB6sR48s4T5Cr8qHUYSZEFCQMMHRg8AoVKVmvcAP5bRw7ArDKeoNwKAJujV3xCPkBvXH5ejSgbgyN6kREmF7sMd41NdbuHa8n1DZNxSMg 248 | 249 | vprv9KXfZnieHrTjtLCacMPCTKm8yK8K1LUDRivyn3g5W82xheUrj8qBs1dj2ZaHHufJMzXJv7ZWfFTt2beVWvizAo8ZNBPygJZYFrpaJAwg3nA 250 | vpub5YX1yJFY8E236pH3iNvCpThsXLxoQoC4nwraaS5h4TZwaSp1Gg9SQoxCsrumxjh7nZRQQkNfH29TEDeMvAZVmD3rpmsDnFc5Sj4JgJG6m4b 251 | 252 | wpkh([5c9e228d/84'/1'/0']tpubDCZB6sR48s4T5Cr8qHUYSZEFCQMMHRg8AoVKVmvcAP5bRw7ArDKeoNwKAJujV3xCPkBvXH5ejSgbgyN6kREmF7sMd41NdbuHa8n1DZNxSMg/0/*)#rn0zejch 253 | wpkh([5c9e228d/84'/1'/0']tpubDCZB6sR48s4T5Cr8qHUYSZEFCQMMHRg8AoVKVmvcAP5bRw7ArDKeoNwKAJujV3xCPkBvXH5ejSgbgyN6kREmF7sMd41NdbuHa8n1DZNxSMg/1/*)#j82ry8g0 254 | 255 | wpkh([5c9e228d/84'/1'/0']tpubDCZB6sR48s4T5Cr8qHUYSZEFCQMMHRg8AoVKVmvcAP5bRw7ArDKeoNwKAJujV3xCPkBvXH5ejSgbgyN6kREmF7sMd41NdbuHa8n1DZNxSMg/<0;1>/*)#egs8kz3g 256 | ``` 257 | 258 | [link to tbtc1.trezor.io](https://tbtc1.trezor.io/xpub/vpub5YX1yJFY8E236pH3iNvCpThsXLxoQoC4nwraaS5h4TZwaSp1Gg9SQoxCsrumxjh7nZRQQkNfH29TEDeMvAZVmD3rpmsDnFc5Sj4JgJG6m4b) 259 | 260 | #### Addresses 261 | 262 | index | address | private key 263 | ------|----------------------------------------------|------------ 264 | 0 | `tb1qkvwu9g3k2pdxewfqr7syz89r3gj557l3uuf9r9` | `cPSW1uTU2dmrJTgFoiAoZva3iZfyhjdT5y8agNzpMKa4c7qFPgrG` 265 | 1 | `tb1qldlynaqp0hy4zc2aag3pkenzvxy65saesxw3wd` | `cRyA1t3w1ytsAiDKsvdeePqESnQBKk8TbftWUPkAGQ4utCZ3Dg42` 266 | 2 | `tb1q9l0rk0gkgn73d0gc57qn3t3cwvucaj3h8wtrlu` | `cSskN3UgpZpMSc828a3EZYocJt1XBdEuPaCqkGh6WFa9yxRxN3vs` 267 | 3 | `tb1qtxe2hdle9he8hc2xds7yl2m8zutjksv02jf0er` | `cSGF69RZV9Q3kMRRmruArTHr21eSGZ1N1NJAFR7bx29PQLhYq22v` 268 | 4 | `tb1qglrv8xrtf68udd5pxj2pxyq5s7lynq20h9nq2w` | `cQjQZvK1kGQBTRMs7Ei5UybGM28qWTUMUrPy41NovrvC6BbcqqK4` 269 | 5 | `tb1qds6ygc07t7d8prjs60qnx0nv4gexx9heyx8rek` | `cRJVMp8dUK7ABt6FcxVz3kLLHr2bh4tHeYiZttGibnGSZHsERxDE` 270 | 6 | `tb1q86udlgffezp9kgjvqlfah7a6c8dpepamm43yea` | `cW7FNz2pYQchTZHccRQkYZyEEAFB2VyxRBuuwnNGkNoa75jzrRLz` 271 | 7 | `tb1q503m8pxyvf7ypurcvwv2kp0ajyjumsjqk55n3f` | `cTX4ewf6JzypdZ4ipLKV4dBCBjyTdHwQ7bgNZDYXduG889te2CoM` 272 | 8 | `tb1qg805w4uhsz3sy9stasdx2rkwp4haf446m8ker9` | `cTZX79TBoyzkGjMRAN7AfzUURD7iCjBw6ZPYxHVW4vMSeX8rHyhN` 273 | 9 | `tb1qy2f6mkfa3aaecqz2s2xr0utf6edza7qz4h37y6` | `cTpLEpKdrSKsrRjKguU2PKxbKNKPuTvTvFAYGi9X1AMzsoKwiDaH` 274 | 275 | ### Bitcoin Testnet: Taproot / P2TR / BIP86 276 | 277 | ``` 278 | m/86'/1'/0' 279 | 280 | tprv8fS6YLYKZhcFQovUKifZpMGn4oGmtS9sNoL4jokEMEYsJWQyZ2s6hTfd1amgKc7PVHdyfkdRgJL7S2DnRtrKczyUq6ZPXWqg5RmFKC51jzh 281 | tpubDC88gkaZi5HvJGxGDNLADkvtdpni3mLmx6vr2KnXmWMG8zfkBRggsxHVBkUpgcwPe2KKpkyvTJCdXHb1UHEWE64vczyyPQfHr1skBcsRedN 282 | 283 | tr([5c9e228d/86'/1'/0']tpubDC88gkaZi5HvJGxGDNLADkvtdpni3mLmx6vr2KnXmWMG8zfkBRggsxHVBkUpgcwPe2KKpkyvTJCdXHb1UHEWE64vczyyPQfHr1skBcsRedN/0/*)#4rqwxvej 284 | tr([5c9e228d/86'/1'/0']tpubDC88gkaZi5HvJGxGDNLADkvtdpni3mLmx6vr2KnXmWMG8zfkBRggsxHVBkUpgcwPe2KKpkyvTJCdXHb1UHEWE64vczyyPQfHr1skBcsRedN/1/*)#yh90mef2 285 | 286 | tr([5c9e228d/86'/1'/0']tpubDC88gkaZi5HvJGxGDNLADkvtdpni3mLmx6vr2KnXmWMG8zfkBRggsxHVBkUpgcwPe2KKpkyvTJCdXHb1UHEWE64vczyyPQfHr1skBcsRedN/<0;1>/*)#rlla6vx8 287 | ``` 288 | 289 | [link to tbtc1.trezor.io](https://tbtc1.trezor.io/xpub/tr(tpubDC88gkaZi5HvJGxGDNLADkvtdpni3mLmx6vr2KnXmWMG8zfkBRggsxHVBkUpgcwPe2KKpkyvTJCdXHb1UHEWE64vczyyPQfHr1skBcsRedN)) 290 | 291 | #### Addresses 292 | 293 | index | address | private key 294 | ------|------------------------------------------------------------------|------------ 295 | 0 | `tb1pswrqtykue8r89t9u4rprjs0gt4qzkdfuursfnvqaa3f2yql07zmq8s8a5u` | TBD 296 | 1 | `tb1p8tvmvsvhsee73rhym86wt435qrqm92psfsyhy6a3n5gw455znnpqm8wald` | TBD 297 | 2 | `tb1p537ddhyuydg5c2v75xxmn6ac64yz4xns2x0gpdcwj5vzzzgrywlqlqwk43` | TBD 298 | 3 | `tb1pdsepw2hky9etm9d3yfumyq9g25xwys6d0jysstaaymgc6nheggasgamqts` | TBD 299 | 4 | `tb1p7dh7sgd570satc42lfsverp00x97gg7u2xu539ea4xt2mwh2p70q48dg3r` | TBD 300 | 5 | `tb1puyst6yj0x3w5z253k5xt0crk2zjy36g0fzhascd4wknxfwv9h9lszyhefk` | TBD 301 | 6 | `tb1pz9mehv82d3ujcw3zhqfn2pvlfu6ayzcm936tv9vu32ca0dsymlxs8nhr3m` | TBD 302 | 7 | `tb1ppq3xlfze03f0wzp8unyyz4le2fkpx62urz4wppnaty25c2adwljquymj9d` | TBD 303 | 8 | `tb1pxveqzq6hgy0dwdehtlhplgrtvu7t83hfr9gkhaxxtjucmwefr2psc49t6a` | TBD 304 | 9 | `tb1pwfygp66acq6c3uyuqtjcmmkaahfw543elpyrtfav8dkpv7uy3sxqvkv0j9` | TBD 305 | 306 | ## References 307 | 308 | - [BIP-0032: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 309 | - [BIP-0039: Mnemonic code for generating deterministic keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) 310 | - [BIP-0044: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) 311 | - [BIP-0049: Derivation scheme for P2WPKH-nested-in-P2SH based accounts](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki) 312 | - [BIP-0084: Derivation scheme for P2WPKH based accounts](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) 313 | - [BIP-0086: Key Derivation for Single Key P2TR Outputs](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki) 314 | -------------------------------------------------------------------------------- /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 | ## Groestlcoin 57 | 58 | `m/44'/17'/0'/0/i` 59 | 60 | index | address | public key | private key 61 | ------|--------------------------------------|----------------------------------------------------------------------|------------ 62 | 0 | `Fj62rBJi8LvbmWu2jzkaUX1NFXLEqDLoZM` | `03b85cc59b67c35851eb5060cfc3a759a482254553c5857075c9e247d74d412c91` | `KyEjYKtiAqyERxq6f9SMQ29GinrThjVrEmfdUrKZz6ZPnPxr8Hor` 63 | 1 | `FYy3bTDYJiSaNhh4d2ptHGwAPNRc6heKy2` | `02cf5126ff54e38a80a919579d7091cafe24840eab1d30fe2b4d59bdd9d267cad8` | `KyYazbWftZUkCf2k9YFQr6UXtfjAw3vnZXyep6pz9PWATWm6wKaL` 64 | 2 | `FXHDsC5ZqWQHkDmShzgRVZ1MatpWhwxTAA` | `0331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67` | `L189RB5TvaJX6p3mnjaoJ12R2GGzdxu1iDUvJPdT3d9Wh8c3g9q9` 65 | 3 | `FtM4zAn9aVYgHgxmamWBgWPyZsb6RhvkA9` | `0286b2a6246bfed0f9a3a4e2ccb49b6989fe078177580b763bbe01e3d4fdfecacd` | `KwwoyZrELnXJc1mvuviWCWc3xSZDBUfnpgwee81B6H83myTQ43y9` 66 | 4 | `FjE6TV6jcN12fbrzwn44GFDcmFQvU9driV` | `03c20962ab16f4d97a4f6f8b83f73a05457794ced25debbf8299336e6ac48bf40d` | `L3rGDCVjokG5caEwpxkQSUuDAQc7arsHCzSiFgzqMpJckyVVXAv9` 67 | 5 | `FqN585nhGJGcNohLffk9qc1X6qZjuqxQhQ` | `021283eb77c39b69a4a5920191e884b71d202fe658057b5b2258db357b8731e707` | `KwhgmgqhztPTRKSTwnYz6QpFVQNL9BGfgvfHLxsQrvuAZb4kDhRR` 68 | 6 | `FjuS7xtFhn1KK5jgiTTtVuYiiDivv6heAh` | `03b66c434a1981f85fdb1c8aaa8f6fd2e02dd267b72f832f3fb2a82b25c24c7d41` | `KxtPi5etKLJcF2tzis3ENn8LSCXy36qU6pJqD5J6C9TwYP3qnsFm` 69 | 7 | `Fe9N7LyoTE58PmQ9N2nSAEeeDEbBhS1NLt` | `0344853499594b040ca8c4f605b5f5005d0c4fdf475cd75f158444c6d86b11f3ca` | `Kx4cu3FjSujkjTQVz8LDArXkpScgyMbtJDHEWWaHsrmnTXmtW9M5` 70 | 8 | `FhuvBfBm8gBfhqM93NzPaVXef9Fv95j2rG` | `03331f59b83c3e2274d4b25ca7643f55822e217339132f26e6ce2db82b6e1f8062` | `L3UA7k9U8x5PTc7XQoDtzM5qisNF7XrEkhufF6X73D4iahSMn7t2` 71 | 9 | `Fn5sfR7FifuLYuBjnAtwreGxNqY4bKbS7g` | `03530992c2f712825050f987aa98b2b7cacd4fbd007aef453675afcc1d750c456a` | `KxvLzbDGH6xL92nHVn4kBAHMaEdRJneqhfiF7btgKT5oa6D1KwWx` 72 | 73 | ## Groestlcoin Testnet 74 | 75 | `m/44'/1'/0'/0/i` 76 | 77 | index | address | public key | private key 78 | ------|--------------------------------------|----------------------------------------------------------------------|------------ 79 | 0 | `mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y` | `030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0` | `cPigoY3hubxpXad1t5WmxpcQpmezLeCcbpA7EpyhDofFnedLHBaT` 80 | 1 | `mopZWqZZyQc3F2Sy33cvDtJchSAMw6psrt` | `0294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852` | `cVN8eHRQh8r9THM2Mu5HCSjx6cfVdssqGL1KeiCKBwUouyeX5wXZ` 81 | 2 | `mgswWyysmViMqYmn5XEj1pVz7rVUhwLwmT` | `03f5008445568548bd745a3dedccc6048969436bf1a49411f60938ff1938941f14` | `cUCiXe6qNE43rEJkSR9e1Tt37W5gQmmGeBiSmXzDbZgxbs6qx83w` 82 | 3 | `momtnzR3XqXgDSsFmd8gkGxUiHZLdGuwNb` | `029ad0b9519779c540b34fa8d11d24d14a5475546bfa28c7de50573d22a503ce21` | `cTAi8RAF2htyUn3F921npbuJLSVdYfpfwqjwLEAPkqvFxL9w2gMf` 83 | 4 | `moE1dVYvebvtaMuNdXQKvu4UxUftHrxubx` | `0313a443e806f25052ac7363adc689fcfa72893f2a51a35ab5e096ed5e6cd8517e` | `cUmGFJMq5Vkh4rjKHe4J4S5adJH1E8xFJJ2ZARBSZNBVzYwFUfyE` 84 | 5 | `muXZYKRJFJ2qPegzV2GEzLqHxngJpGE1rY` | `02e35cca50cb2626212bce8fdfb988bb33f303b15536e9f84f018e63045dbb84ac` | `cRHMG1RjgVWTdUNEgDD5oNEvQvBAha5N3YntnT7rC8yekeHrXcuQ` 85 | 6 | `mnY26FLTzfC94mDoUcyDJh1GVE3Lt4iVCd` | `0344e14b3da8f5fe77a5465d0f8fe089d64ed5517d1f1f989edd00f530938a2c22` | `cS9rFFu8douRgweuQKLdF4QXpS3H1UeoNxZWTt6K874nt4vDYQJp` 86 | 7 | `mgV9Z3YuSbxGb2b2Y1T6VCqtU2osx6mqvs` | `035169c4d6a36b6c4f3e210f46d329efa1cb7a67ffce7d62062d4a8a17c23756e1` | `cQ1Uh9vXLhaoEgPGUEGMoWACpzrVesmB8G4KdK5vZBnLBifd1t1d` 87 | 8 | `miLqfMwzis98J5vkjjhTiXVsrkAYyMik61` | `03260dc4925b14addb52b4e62c698b99d2318f3d909477a081ae8e5d94dc3c66d8` | `cPwi3WVwjgr422fBeLa22UHwRkQEMZqoJBjevuosqd25yyZB6Yk5` 88 | 9 | `mhAacBq3SnXEpoxzEwKqfnQz1iYjxvqrcP` | `02b3397d76b093624981b3c3a279c79496d16820f821528b9e403bdfc162b34c3c` | `cRkkmKXgTmq3Je2B71Rn4HQxeo2hEqvtUeQ5r4Q7eKr5qtnuEeMs` 89 | 90 | ## Litecoin 91 | 92 | `m/44'/2'/0'/0/i` 93 | 94 | index | address | public key | private key 95 | ------|--------------------------------------|----------------------------------------------------------------------|------------ 96 | 0 | `LcubERmHD31PWup1fbozpKuiqjHZ4anxcL` | `021239d8b20ad1f83d34383e82075d0e11f7a98d06f9e015b56cff61db1e4f8c25` | `T5wTndHdQ1sDnQhApMnDrbQV56PEnjZeRMq9ao2aRJALyUdjdExP` 97 | 1 | `LVWBmHBkCGNjSPHucvL2PmnuRAJnucmRE6` | `02c88e3d1c97fe3ff8eb2f51c37ca66cbfabb6404ddf8158478fae3b8a90e98035` | `TAZnJTHBjN7UoXV6v1aGhVkgq7kBbtXe9h1oKND7LHGS4FC5wnKQ` 98 | 2 | `LUQ91iCfoayy3G3rrFtmF6eVzKQyFSdi2T` | `02df4513e0faae40c6e1dbca606c4fe6c3e22d00a30024ea2b01b7da0097a97f82` | `T3bxs7ZtsnCrXn1dhYJeRBu2FkLFLf8oyhiahMkhdJwxiDVAUP1e` 99 | 3 | `LNk7cQvGW5LPgkii3RUX7YQWtX6HjmLbB4` | `03a69bec3139474eec35f7c87d59f8b6ec37423dbcfce5c5d090bd26de604a2b70` | `T3SQgQ4byehx5ayT98PE7ZDPr68taysoW2Hm6FyDNWuyKiBpWa3L` 100 | 4 | `Laz1nYzJwrGcaZDEERENpNVbgte1n3vWLJ` | `03ed59a1f1b1e2af17ae00ff373a3cedd8b7bd3c4723a76d469e52ec8caba09337` | `T5HGaZgAs35kWheKDFDhdHz1sqNgo3FitUaeBegugamfFxRSjYga` 101 | 5 | `LcBMCi1mQ71LLvFqN2TMgEgomoc9yqEFzg` | `0279224038c76ffcfd1a95ca5d93bcb15c426e18776362fcddd76ff7cc60b9a25d` | `TAdPGc81ANgVhvEVyK5K5DQee4DEv1dDeXAUCBqn6ocPx5Wdi7qc` 102 | 6 | `LfyFtx6XekFZ54gATTjrgeFFmMqAboZwvi` | `0284b369982fba3be2ef729a96b13806b2372c6f3b5209c44fd5ce29c0a1eca976` | `T8WecZVp58aYSvtaw8PAhhx2hxMRBUuvT25dtDyk4x6vE97PHnAY` 103 | 7 | `Le2twPHqkDEiPrY4uZw6Ufes3e7t4VUZ68` | `032e030b64a7de06fc972b7fb82ca4392c4e5a535ce942f32d6b660b1d58b5176c` | `T5ojDJgMa3QYZkst9po2B6P5SXyP4vFuBFZBhvyp8E9Ek74yCzoE` 104 | 8 | `LViaNcv7TTQv8yFFvBnjC63dwVNL3e21c1` | `026b9d73e88ecbcd55a68e0a8e6c651e2543075b85fc6e85386e1a8009e9a55abe` | `T7YQp9UidMzNSRJHPpCVWeANPpDK5Nz1MhfWuP5sy6YFUB5VJiat` 105 | 9 | `LfritJSaLhmsRDaZwYSnfpUMNTA8kTweHa` | `030ad428a32f117f21cbf581630858b28baa957cb475ac43b7536b1a1da3d00293` | `T3WSZzJmXPZB7Mr5vAQ5qmi2b9zFww5oLHqUcyy7371d9ujZb8Kb` 106 | 107 | ## Ethereum 108 | 109 | `m/44'/60'/0'/0/i` 110 | 111 | index | address | public key | private key 112 | ------|----------------------------------------------|----------------------------------------------------------------------|------------ 113 | 0 | `0x73d0385F4d8E00C5e6504C6030F47BF6212736A8` | `03ad8e7eb4f3a7d1a409fa7bdc7b79d8840fe746d3fa9ee17fee4f84631ec1430b` | `759e46263f1505994d11142d70027975c9b9fef15489b09bd987eb8a31aba0db` 114 | 1 | `0xFA01a39f8Abaeb660c3137f14A310d0b414b2A15` | `03ddeae7da4e54757d3f3038315344709971849a971d2619797d9b8574e373ae9b` | `616883a861adaab932634c283e294bcfdc9797757984bc4a15a9484ada947177` 115 | 2 | `0x574BbB36871bA6b78E27f4B4dCFb76eA0091880B` | `039d09121b995a1f7fe5d30996f6a66fff4688f8eee096faea2957e1fe53923860` | `4f74b7bb78734476e41caa28a397493260103f4ccf0b8a14fe340da5a8a7e22c` 116 | 3 | `0xba98D6a5ac827632E3457De7512d211e4ff7e8bD` | `0307b32cc46360c9acf750da7acf7dce918aee97dd383236248c9c79b8efbd98fc` | `a02122e1ac06fb63da2fd293706c91b5839108de765dc9ce3e2d3fb1573bafd4` 117 | 4 | `0x1f815D67006163E502b8eD4947C91ad0A62De24e` | `03d26a9f183bbb531e140ab3d87bca361706b4c4be7c731e29160cab833e7a9282` | `f686b6033ef11ad995ff93b240bd28b04c6dc3a24cb35861b642f7ba969564e0` 118 | 5 | `0xf69619a3dCAA63757A6BA0AF3628f5F6C42c50d2` | `02ae8cef29ef6d2ad9b98af746589743c510e4b49784ec1181a079b4b1df3c5211` | `945f0973cd011048b56bb87887ad782c72b09ff181f4af97ad033581ea009a74` 119 | 6 | `0xA8664Df3D5E74BE57c19fC7005BBcd0F5328041e` | `023ed2881ee76991dafd40e33df96a88a5e929869635cdfc261e947d1e9ca31be9` | `7226389c1de87a3498234ad49e00e48060609b839616de313b341c6245142993` 120 | 7 | `0xf2252f414e727d652d5a488fE4BFf7e64478737F` | `03b765e9b8ba13ffb45e69f038bf1506aa2ecf1f1824c88551f98e93026c06e6b4` | `640dfbf3d433c548d0a1b9d0d5dc824f72d631cdfca0902ad16788b6b3081067` 121 | 8 | `0x5708Ae081b48ad7bA8c50ca3D4fa0238d544D6FA` | `031acf557e85d59e0305b8b79d4a5cc5077d09811206be208c00c4e457e7017ac1` | `728a3bd762ac7a25d58eafcd3240bb783304cd323e78b5967a8ecdb4c1e1a982` 122 | 9 | `0x12eF7dfb86f6D5E3e0521b72472ca02D2a3814F4` | `02c9f2bf6bbf6244eec9866ad6eb6dec628cbf71f2e2cb77c25d72baeca2c32f61` | `9ee5234da5069eede6135c0f684fd0b633504a04614c740aef47a57a28c0384d` 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-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-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/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-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 because 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 because otherwise somebody could rob us! 158 | ``` 159 | 160 | 2. Other steps are the same as in entry encryption, we just symmetrically 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-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 SLIP-0010. 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 | ## Worked example 69 | 70 | 1. `index + uri`=`42` + `https://nvsaberhagen@getmonero.org/login` 71 | 72 | 2. `sha256(index + uri)` = `f8be2155d1323418dc94a20c74bfdb7ab418eb7b061b38729193870405dd3875` 73 | 74 | 3. `hash128` = `f8be2155d1323418dc94a20c74bfdb7a` 75 | 76 | 4. `A` = 1428274936 (0x5521bef8), `B` = 406074065 (0x0x183432d1), `C` = 211981532 (0x0ca294dc), `D` = 2061221748 (0x7adbbf74) 77 | 78 | 5. `A'` = 3575758584, `B'` = 2553557713, `C'` = 2359465180, `D'` = 4208705396 79 | 80 | 6. `HD node path` = `m/2147483665/3575758584/2553557713/2359465180/4208705396` 81 | 82 | ## References 83 | 84 | * [BIP-0043: Purpose Field for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) 85 | * [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax](https://tools.ietf.org/html/rfc3986) 86 | * [SLIP-0010: Universal private key derivation from master private key](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) 87 | -------------------------------------------------------------------------------- /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-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-0011.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-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://datatracker.ietf.org/doc/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-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://doi.org/10.1109/EuroSPW.2017.47) and also described in the [Cardano documentation](https://github.com/input-output-hk/technical-docs/blob/main/cardano-components/cardano-wallet/doc/Wallet-Cryptography-and-Encoding.md#hierarchical-deterministic-wallets). 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://doi.org/10.1109/EuroSPW.2017.47) 123 | -------------------------------------------------------------------------------- /slip-0024.md: -------------------------------------------------------------------------------- 1 | # SLIP-0024 : Trezor payment request format 2 | 3 | ``` 4 | Number: SLIP-0024 5 | Title: Trezor payment request format 6 | Type: Standard 7 | Status: Draft 8 | Authors: Andrew Kozlik 9 | Created: 2021-12-09 10 | ``` 11 | 12 | ## Abstract 13 | 14 | A Trezor payment request is a message that is signed by a trusted party requesting payment of a specified amount to one or more addresses, similar in principle to [BIP-0070](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki). 15 | This message can be processed by a payer's wallet in such a way that the payer does not have to inspect the destination address and only needs to confirm the payment of the requested amount to the recipient that is named in the payment request. 16 | 17 | ## Motivation 18 | 19 | Before a cryptocurrency payment can be made, the recipient of the payment needs to securely communicate their receiving address to the payer. If the communication channel between the two parties is not well secured or if one of the endpoints is compromised by malware, then an attacker may modify the address, changing it to the attacker's own address in order to receive the payment instead of the legitimate recipient. This type of attack is known as *address spoofing*. 20 | 21 | Hardware wallets are known to be the most secure solution to cryptocurrency payments. They are generally very resilient to malware, but they do not protect the payer from address spoofing outside of the wallet. The task of authenticating the address is up to the payer who should ideally verify the correctness of the address by means of a second channel. Using multiple channels to communicate the address reduces the likelihood of an attacker being able to compromise all of them at once, but at the same time it hinders the user experience. 22 | 23 | This specification defines a new format of payment requests which aim to make cryptocurrency payments in hardware wallets safer and more user-friendly by allowing automated authentication of merchant's addresses using digital signatures. 24 | 25 | ### Differences over BIP-0070 26 | 27 | The Trezor payment request format is heavily inspired by the earlier [BIP-0070](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) specification. The main ways in which the present specification differs over BIP-0070 are summarized below. 28 | 29 | * Adapted to the needs of hardware wallets. 30 | * A nonce challenge is used to guarantee freshness instead of creation/expiry time, since the current time is not reliably available in hardware wallets. 31 | * The way in which the payment request data is hashed is optimized for memory-constrained environments. 32 | * PKI is considered out of scope of this specification, thus X.509 support is not required. 33 | * Designed for use with multiple cryptocurrencies. 34 | * Defines new types of memo fields, which allow for new use-cases. 35 | * The signature is required. 36 | 37 | ## Payment request items 38 | 39 | ### Recipient name 40 | 41 | The recipient name is shown to the payer instead of the address or addresses which the payment request represents. The payer must however have the option of inspecting the addresses on the wallet's screen if they wish. 42 | 43 | ### Memos 44 | 45 | Memos are used to provide additional information to the payer about the purpose of the payment request. 46 | A memo may also contain information that needs to be verified by the payer or their wallet. By making the payment to the specified address the payer confirms that the information in the memo is correct. 47 | 48 | A payment request may contain multiple instances of the same memo type. 49 | For a memo type that is displayed to the payer, all instances of that memo type MUST be displayed in the same order as they are listed in the payment request. 50 | 51 | The following types of memos are defined. 52 | 53 | #### Text memo 54 | 55 | A text memo is a UTF-8 encoded, plain-text note explaining the purpose of the payment request. 56 | The note MUST be displayed to the payer in full. 57 | 58 | #### Refund memo 59 | 60 | A refund memo specifies the address where the payment should be refunded to the customer if necessary. 61 | The customer's wallet MUST verify that it controls this address, see [Verifying address ownership](#verifying-address-ownership). 62 | The wallet does not have to display this information on the screen. 63 | 64 | #### Text details memo 65 | 66 | A text details memo is a plain-text note containing additional details about the payment request. It consists of a title and a text body. 67 | The note MAY be displayed to the payer either automatically, upon their request, or not displayed at all, namely if the device has limited capabilities. 68 | 69 | #### Coin purchase memo 70 | 71 | A coin purchase memo can be used by a cryptocurrency exchange service to inform their customer about the cryptocurrency and amount that the customer will receive in exchange for the payment they make. The customer's wallet MUST display this information on the screen. The coin purchase memo also specifies the address to which the exchange will send the cryptocurrency purchased by the customer. The customer's wallet MUST verify that it controls this address, see [Verifying address ownership](#verifying-address-ownership). 72 | 73 | ### Nonce 74 | 75 | A unique challenge generated by the payer's wallet. The nonce guarantees freshness of the payment request and prevents replaying the payment request to the wallet or to another wallet. A nonce SHOULD be present whenever one or more memos are present in the payment request. 76 | 77 | ### Requested outputs 78 | 79 | A list of destination addresses with requested amounts. The payer is requested to pay the specified amount to each of the listed addresses. 80 | 81 | ### Payment request signature 82 | 83 | A digital signature of the payment request issued by a party which is trusted by the payer. 84 | 85 | ## Trusted party 86 | 87 | The definition of a trusted party is out of scope of this specification. It is up to the wallet vendor to choose how trusted parties are defined. For example, they may be defined by one or more pinned public keys in the wallet's firmware or the trusted public keys may be user-defined. Trust can also be derived from a PKI scheme, such as X.509 in the BIP-0070 specification. However, it should be noted that X.509 is not very well suited for use in hardware wallets due to its excessive complexity, e.g. certificate extensions, expiry dates or certificate validation and revocation rules. Each trusted party may be restricted to signing payment requests only for particular recipient names. 88 | 89 | ## Workflows 90 | 91 | The following describes several scenarios involving a customer paying a merchant using cryptocurrency. The customer has a hardware wallet and a wallet application running on their computer which controls the hardware wallet. The merchant has access to a signing server whose signatures are trusted by the customer's wallet. 92 | 93 | ### Basic scenario 94 | 95 | 1. The customer creates an order with the merchant and chooses to pay using Bitcoin. 96 | 2. The merchant generates a unique receiving address for the customer's order. 97 | 3. The merchant authenticates itself to the signing server and sends it the receiving address and amount to be paid. 98 | 4. The signing server returns a signed payment request to the merchant containing the merchant's name, receiving address and amount to be paid. 99 | 5. The merchant verifies that the signature matches the provided data and generates a BIP-0021 URI with the payment request signature in `slip24sig` as described [below](#usage-with-the-bip-0021-uri-scheme). 100 | 6. The customer clicks the BIP-0021 URI which opens their wallet application. 101 | 7. The wallet application creates a transaction transferring the requested amount to the merchant's address. 102 | 8. The wallet application requests a transaction signature from the hardware wallet, providing the payment request data. 103 | 9. The hardware wallet verifies that the payment request signature was issued by a trusted party and displays a confirmation dialog to the user stating the merchant's name and amount to be sent. 104 | 10. The customer confirms the dialog and the hardware wallet generates the transaction signature. 105 | 11. The wallet application broadcasts the signed transaction. 106 | 12. The merchant monitors the blockchain for a transaction transferring the requested amount to its receiving address. 107 | 108 | If the trusted signing server is operated by a hardware wallet vendor, then in step 1 the customer may need to select the vendor of their wallet. The server may also be operated by the merchant itself, in which case the customer will have had to load the merchant's public key into their hardware wallet in advance. 109 | 110 | ### Scenario with a refund memo 111 | 112 | 1. The customer's wallet application selects an address which belongs to the customer and is suitable for receiving the refund of a payment. 113 | 2. The wallet application obtains two items from the hardware wallet: 114 | * an address authentication code for the selected refund address and 115 | * a nonce challenge, which the hardware wallet also records in a nonce cache in its volatile memory. 116 | 3. The wallet application provides the customer's refund address and nonce challenge to the merchant who will be receiving the payment. 117 | 4. The merchant generates a unique receiving address for the payment request. 118 | 5. The merchant authenticates itself to the signing server and sends it its receiving address, the amount to be paid, the customer's refund address and nonce challenge. 119 | 6. The signing server returns a signed payment request to the merchant. 120 | 7. The merchant verifies that the signature matches the provided data and returns the payment request to the customer's wallet application. 121 | 8. The wallet application creates a transaction transferring the requested amount to the merchant's address. 122 | 9. The wallet application requests a transaction signature from the hardware wallet, providing the payment request data together with the address authentication code of the refund address. 123 | 10. The hardware wallet takes the following steps: 124 | * Verifies that it issued the nonce challenge by checking its nonce cache and removes it from the cache so that the payment request cannot be reused in the future. 125 | * Verifies that it controls the refund address by validating the address authentication code. 126 | * Verifies that the payment request signature was issued by a trusted party. 127 | * Displays a confirmation dialog to the user stating the merchant's name and amount to be sent. 128 | 11. The customer confirms the dialog and the hardware wallet generates the transaction signature. 129 | 12. The wallet application broadcasts the signed transaction. 130 | 13. The merchant monitors the blockchain for a transaction transferring the requested amount to its receiving address. 131 | 14. If the merchant needs to refund the payment, then it may send it to the refund address that was specified in the payment request without any further interaction with the customer. 132 | 133 | ## Signature generation 134 | 135 | The payment request signature is generated by signing the *paymentRequestDigest* using the private key of the trusted party. 136 | The default signature scheme is ECDSA with SHA-256 and the curve secp256k1, but any other suitable signature scheme may be chosen by the trusted party instead. In case of the default scheme the signature is encoded in 64 bytes. The first 32 bytes encode the *r* component of the signature and the second 32 bytes encode the *s* component, both in big-endian byte order. 137 | 138 | The *paymentRequestDigest* is computed by hashing the concatenation of the following fields: 139 | 140 | * *versionMagic* (4 bytes): b"\x53\x4c\x00\x24" (this is "SL" followed by 0024 in compressed numeric form as an abbreviation for "SLIP-0024"). 141 | * *nonce* (length-prefixed binary string): an optional nonce challenge from the wallet. If a nonce is not used, then a zero-length string should be provided. 142 | * *recipientName* (length-prefixed UTF-8 string): a human-readable string identifying the recipient of the payment. 143 | * *n* (CompactSize integer): the number of memos which follow. The CompactSize integer MUST be encoded in the fewest possible number of bytes. 144 | * *memo*1 || *memo*2 || ... || *memo**n* (variable length): concatenation of the binary encoding of the memos, see below. 145 | * *coinType* (4 bytes): 32-bit encoding of the SLIP-0044 coin type of the outputs in little-endian byte order. 146 | * *outputsHash* (32 bytes): the hash of the binary encodings of all requested outputs, see below. 147 | 148 | A text memo is encoded as the concatenation of the following fields: 149 | 150 | * *memoType* (4 bytes): b"\x01\x00\x00\x00" (32-bit encoding of the integer 1 in little-endian byte order). 151 | * *text* (length-prefixed UTF-8 string): a human-readable string providing information about the purpose of the payment. 152 | 153 | A refund memo is encoded as the concatenation of the following fields: 154 | 155 | * *memoType* (4 bytes): b"\x02\x00\x00\x00" (32-bit encoding of the integer 2 in little-endian byte order). 156 | * *address* (length-prefixed string): the address where the payment should be refunded if necessary. 157 | 158 | A coin purchase memo is encoded as follows: 159 | 160 | * *memoType* (4 bytes): b"\x03\x00\x00\x00" (32-bit encoding of the integer 3 in little-endian byte order). 161 | * *coinType* (4 bytes): 32-bit encoding of the SLIP-0044 coin type of the address where the coin purchase will be delivered in little-endian byte order. 162 | * *amount* (length-prefixed UTF-8 string): the human-readable amount the address will receive including units, e.g. "0.025 BTC". 163 | * *address* (length-prefixed string): the address where the coin purchase will be delivered. 164 | 165 | A text details memo is encoded as the concatenation of the following fields: 166 | 167 | * *memoType* (4 bytes): b"\x04\x00\x00\x00" (32-bit encoding of the integer 4 in little-endian byte order). 168 | * *title* (length-prefixed UTF-8 string): a human-readable heading for the text. 169 | * *text* (length-prefixed UTF-8 string): a human-readable string containing additional details about the payment. 170 | 171 | The value of *outputsHash* is computed as the hash of the concatenation of the binary encodings of the requested outputs. The binary encoding of an output is the concatenation of the following fields: 172 | 173 | * *amount* (8 bytes): 64-bit encoding of the amount of the requested output in little-endian byte order, expressed in the smallest unit of the given cryptocurrency (satoshis). 174 | * *address* (length-prefixed string): the address of the requested output. 175 | 176 | All variable-length fields are encoded the same way as in Bitcoin transactions, as a [length-prefixed string](https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_string), where the length is encoded as a variable-length CompactSize integer. 177 | 178 | ### Coin-specific encoding rules 179 | 180 | In case of *coinType* 144 (XRP), if a requested output includes a destination tag, then the address field in the binary encoding of the output is appended with the string `?dt=`, followed by the destination tag formatted as a decimal integer in the fewest possible number of characters. 181 | 182 | ## Usage with the BIP-0021 URI scheme 183 | 184 | [BIP-0021](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki) specifies a URI scheme for encoding Bitcoin payment requests. The present specification defines a new query key `slip24sig` for BIP-0021 URIs, allowing the URI to encode a basic Trezor payment request. If the `slip24sig` field is specified in the URI the `amount` and `label` fields MUST also be specified. 185 | 186 | The value of `slip24sig` is the base64 encoding of the SLIP-0024 payment request signature. Note that any `=` characters in the base64 encoding must be percent-encoded as `%3D`. When computing the hash of the payment request the *recipientName* is taken from the`label` field of the URI. If the `message` field is specified in the URI, then the message is processed as a text memo. The *outputsHash* value is the hash of exactly one output specified by the `address` and `amount` fields of the URI. A nonce is not used and the *coinType* is 0. 187 | 188 | ## JSON schema 189 | 190 | Use-cases involving multiple outputs or nonces require a more complex protocol than BIP-0021. For this purpose a JSON schema will be defined to document the data interchange format between the merchant and customer's wallet application. The same format may also be used for communicating payment requests between the merchant and the signing server. 191 | 192 | TODO 193 | 194 | ## Verifying address ownership 195 | 196 | This section is non-normative. One of the requirements in processing a refund memo or a coin purchase memo is that the customer's wallet must verify that the specified address is controlled by the wallet. The most common way of verifying address ownership by a wallet is to provide the BIP-0032 derivation path leading from the wallet's seed to the address. In cases where the address belongs to another coin type or uses non-standard parameters, address derivation can be more complicated. 197 | 198 | In order to simplify the communication protocol with the wallet, it is more convenient to verify address ownership by means of an address authentication code. When getting an address from the hardware wallet, the wallet can return an authentication code together with the address. This authentication code is saved by the calling application and used at a later point in time to prove to a stateless hardware wallet that the address was derived from its seed. 199 | 200 | ### Address authentication code in Trezor 201 | 202 | The address authentication code defined in this section should only be issued for addresses that are fully controlled by the wallet, i.e. only for non-multisig addresses. 203 | 204 | Let *k* be a secret *address authentication 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: 205 | 206 | ``` 207 | k = Key(m/"SLIP-0024"/"Address MAC key") 208 | ``` 209 | 210 | The address authentication code is computed as: 211 | 212 | ``` 213 | mac = HMAC-SHA256(key = k, msg = addressInfo) 214 | ``` 215 | 216 | where `addressInfo` is the concatenation of the following fields: 217 | 218 | * *coinType* (4 bytes): 32-bit encoding of the SLIP-0044 coin type of the address in little-endian byte order. 219 | * The BIP-0032 path to derive the address from the master node, which consists of: 220 | * *n* (CompactSize integer): the path length. 221 | * *i*1 || *i*2 || ... || *i**n* (variable length): concatenation of the 32-bit encodings of the child indices, each in little-endian byte order. 222 | * *address* (length-prefixed string): the address being authenticated. 223 | 224 | ## Test vectors 225 | 226 | TODO 227 | 228 | ## References 229 | 230 | * [BIP-0021](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki): URI Scheme 231 | * [BIP-0070](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki): Payment Protocol 232 | -------------------------------------------------------------------------------- /slip-0025.md: -------------------------------------------------------------------------------- 1 | # SLIP 25 : Key derivation for CoinJoin accounts 2 | 3 | ``` 4 | Number: SLIP-0025 5 | Title: Key derivation for CoinJoin accounts 6 | Type: Standard 7 | Status: Draft 8 | Authors: Andrew R. Kozlik 9 | Created: 2022-04-04 10 | ``` 11 | 12 | ## Abstract 13 | 14 | This document defines a logical hierarchy for deterministic wallets based on the algorithm defined in [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [SLIP 10](https://github.com/satoshilabs/slips/blob/master/slip-0010.md) and the scheme described in [BIP 43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki). 15 | The purpose of this document is largely the same as [BIP 86](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki), however the keys derived using the present hierarchy are meant to be used in so called *CoinJoin accounts*, which are managed by CoinJoin wallets. 16 | 17 | ## Motivation 18 | 19 | A CoinJoin wallet allows its users to participate in a special kind of transaction which mixes the user's UTXOs with the UTXOs of other participants in order to obfuscate the ownership of the resulting CoinJoin outputs to external observers. 20 | Each user receives the same amount from the CoinJoin transaction as they put in, minus a small coordination and mining fee. 21 | Each UTXO that is managed by a CoinJoin wallet is assigned an anonymity rating based on its CoinJoin history and the user typically chooses to spend only those UTXOs which have achieved a sufficient level of anonymity. 22 | The way in which the account keys and XPUBs are managed requires greater care than in the case of ordinary cryptocurrency accounts based on BIPs [44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki), [49](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki), [84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) or [86](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki), which is why we define this domain-separated hierarchy. 23 | 24 | ## Public key derivation 25 | 26 | We define the following 6 levels in the BIP 32 derivation path: 27 | 28 | ``` 29 | m / 10025' / coin_type' / account' / script_type' / change / address_index 30 | ``` 31 | 32 | `'` in the path indicates that hardened derivation is used. 33 | A key derived with this derivation path pattern will be referred to as `derived_key` further in this document. 34 | 35 | ### Coin type field 36 | 37 | The value of `coin_type` MUST be one of the coin types defined in [SLIP 44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md). 38 | The keys derived for a particular coin type SHOULD only be used in connection with the cryptocurrency specified in SLIP 44. 39 | 40 | One master node (seed) can be used for multiple cryptocurrency networks. 41 | Sharing keys between different cryptocurrency networks or between mainnet and testnet may be especially dangerous if the cryptocurrency does not implemented strong replay protection, e.g. via `SIGHASH_FORKID`. 42 | For example if a testnet application is allowed to access mainnet keys, then an attacker may be able to coerce the user into spending Bitcoin by signing a seemingly harmless testnet transaction. 43 | 44 | This level creates a separate subtree for every cryptocurrency, avoiding key reuse between networks and improving privacy. 45 | 46 | ### Account field 47 | 48 | The value of `account` SHOULD be in the range from `0` to `100`. 49 | Accounts are numbered from index `0` in a sequentially increasing manner. 50 | 51 | This level splits the key space into independent user identities. 52 | Users can use these accounts to organize their funds in the same fashion as bank accounts for better overview of their operations, e.g. a business account and a personal account. 53 | Some users may also choose to segregate coins into multiple identities as a fail-safe in case CoinJoin doesn't offer the advertised level of anonymity. 54 | 55 | Wallet software should prevent spending coins from different accounts in one transaction. 56 | It should also prevent the creation of an account, i.e. accessing the new account's addresses, if a previous account does not have any transaction history. 57 | 58 | ### Script type field 59 | 60 | The value of `script_type` MUST be `1`. 61 | All other values are reserved for future use. 62 | 63 | The inclusion of this field is inspired by [BIP 48](https://github.com/bitcoin/bips/blob/master/bip-0048.mediawiki). 64 | Being able to manage multiple script types under a single account may be especially useful in other privacy-focused applications such as [BIP 78](https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki) PayJoin when the sender's script type needs to be matched by the receiving wallet. 65 | 66 | ### Change field 67 | 68 | The value of `change` MUST be `0` or `1`. 69 | All other values are reserved for future use. 70 | 71 | The value `0` is used for the *external chain* and the value `1` for the *internal chain* (also known as change addresses or internal addresses). 72 | The external chain is used for addresses that are meant to be visible outside of the wallet, e.g. for receiving payments. 73 | The Internal chain is used for addresses which are not meant to be visible outside of the wallet and is used either for returning transaction change or for outputs of CoinJoin transactions. 74 | 75 | ### Address index field 76 | 77 | The value of `address_index` SHOULD be an integer in the range from `0` to `1000000` (inclusive). 78 | Addresses are numbered from index `0` in a sequentially increasing manner. 79 | 80 | ## Address derivation 81 | 82 | ### Script type 1: P2TR 83 | 84 | If `script_type = 1` then the derived key MUST be used to generate a P2TR address. 85 | The scriptPubKey is defined exactly as specified in the [Address derivation](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#address-derivation) section of BIP 86: 86 | 87 | ``` 88 | internal_key: lift_x(derived_key) 89 | 32_byte_output_key: internal_key + int(HashTapTweak(bytes(internal_key)))G 90 | scriptPubKey: 0x51 0x20 {32_byte_output_key} 91 | ``` 92 | 93 | ## Handling XPUBs and addresses 94 | 95 | The UTXOs from a CoinJoin account SHOULD only be spent by a wallet that is able to rate the anonymity of the UTXOs and select the ones satisfying the user's anonymity threshold. 96 | 97 | Wallets MUST require user confirmation before releasing the XPUB to any node in the BIP 32 subtree of `m / 10025'`. 98 | 99 | Wallets SHOULD NOT display an address belonging to the internal chain (`change = 1`) of a CoinJoin account. 100 | 101 | ## Backwards Compatibility 102 | 103 | This SLIP is not backwards compatible with earlier derivation schemes by design due to the special requirements for handling XPUBs and addresses. 104 | An incompatible wallet will not discover these accounts, however the scheme is sufficiently similar to existing schemes, so that adding it to current implementations does not require any significant amount of new code. 105 | 106 | ## Test vectors 107 | 108 | TODO 109 | 110 | ## References 111 | 112 | * [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki): Hierarchical Deterministic Wallets 113 | * [SLIP 10](https://github.com/satoshilabs/slips/blob/master/slip-0010.md): Universal private key derivation from master private key 114 | * [BIP 44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki): Multi-Account Hierarchy for Deterministic Wallets 115 | * [SLIP 44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md): Registered coin types for BIP 44 116 | * [BIP 48](https://github.com/bitcoin/bips/blob/master/bip-0048.mediawiki): Multi-Script Hierarchy for Multi-Sig Wallets 117 | * [BIP 49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki): Derivation scheme for P2WPKH-nested-in-P2SH based accounts 118 | * [BIP 84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki): Derivation scheme for P2WPKH based accounts 119 | * [BIP 86](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki): Deterministic Entropy From BIP32 Keychains 120 | * [BIP 78](https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki): A Simple Payjoin Proposal 121 | -------------------------------------------------------------------------------- /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/lagrange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satoshilabs/slips/df16de16a1cd80556fba2786c3ae12816b8d7ff6/slip-0039/lagrange.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satoshilabs/slips/df16de16a1cd80556fba2786c3ae12816b8d7ff6/slip-0039/secret_sharing_1.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satoshilabs/slips/df16de16a1cd80556fba2786c3ae12816b8d7ff6/slip-0039/secret_sharing_2.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satoshilabs/slips/df16de16a1cd80556fba2786c3ae12816b8d7ff6/slip-0039/secret_sharing_3.png -------------------------------------------------------------------------------- /slip-0039/secret_sharing_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/satoshilabs/slips/df16de16a1cd80556fba2786c3ae12816b8d7ff6/slip-0039/secret_sharing_4.png -------------------------------------------------------------------------------- /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-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-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 | 0x00000bee | Hive | `0x0`: owner, `0x1`: active, `0x3`: memo, `0x4`: posting 142 | 0x00001388 | Vet The Vote | `0x0`: owner, `0x1`: active, `0x3`: memo, `0x4`: posting, `0x5`: comms 143 | 0x000014da | Keet | `0x0`: owner 144 | 145 | ## Examples 146 | 147 | Network | Role | Account-index | Key-Index | Path 148 | -----------|---------------|----------------|-----------|---------------------------- 149 | Steem | active | first | first | m / 48' / 0' / 1' / 0' / 0' 150 | BitShares | owner | forth | forth | m / 48' / 1' / 0' / 3' / 3' 151 | EOS | owner | first | first | m / 48' / 4' / 0' / 0' / 0' 152 | FIBOS | owner | first | first | m / 48' / 5' / 0' / 0' / 0' 153 | BOS | owner | first | first | m / 48' / 9' / 0' / 0' / 0' 154 | ONEGRAM | owner | first | first | m / 48' / 10' / 0' / 0' / 0' 155 | HIVE | active | first | first | m / 48' / 3054' / 1' / 0' / 0' 156 | V12 | comms | first | first | m / 48' / 5000' / 5' / 0' / 0' 157 | 158 | 159 | ## References 160 | 161 | * [BIP-0044: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) 162 | * [Graphene Wiki](https://github.com/cryptonomex/graphene/wiki) 163 | 164 | ## Updates 165 | 166 | 2017/09/07: In the hierarchy, the key role and the account index are swapped to allow separation of roles in sub-trees. 167 | -------------------------------------------------------------------------------- /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-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-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 | `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 | Groestlcoin | `0x0488b21e` - `xpub` | `0x0488ade4` - `xprv` | P2PKH or P2SH | m/44'/17' | 43 | Groestlcoin | `0x049d7cb2` - `ypub` | `0x049d7878` - `yprv` | P2WPKH in P2SH | m/49'/17' | 44 | Groestlcoin | `0x04b24746` - `zpub` | `0x04b2430c` - `zprv` | P2WPKH | m/84'/17' | 45 | Groestlcoin | `0x0295b43f` - `Ypub` | `0x0295b005` - `Yprv` | Multi-signature P2WSH in P2SH | - | 46 | Groestlcoin | `0x02aa7ed3` - `Zpub` | `0x02aa7a99` - `Zprv` | Multi-signature P2WSH | - | 47 | Groestlcoin Testnet | `0x043587cf` - `tpub` | `0x04358394` - `tprv` | P2PKH or P2SH | m/44'/1' | 48 | Groestlcoin Testnet | `0x044a5262` - `upub` | `0x044a4e28` - `uprv` | P2WPKH in P2SH | m/49'/1' | 49 | Groestlcoin Testnet | `0x045f1cf6` - `vpub` | `0x045f18bc` - `vprv` | P2WPKH | m/84'/1' | 50 | Groestlcoin Testnet | `0x024289ef` - `Upub` | `0x024285b5` - `Uprv` | Multi-signature P2WSH in P2SH | - | 51 | Groestlcoin Testnet | `0x02575483` - `Vpub` | `0x02575048` - `Vprv` | Multi-signature P2WSH | - | 52 | Kylacoin | `0x038f332e` - `kpub` | `0x038f2ef4` - `kprv` | P2PKH or P2SH | - | 53 | Kylacoin Testnet | `0x045f1cf6` - `vpub` | `0x045f18bc` - `vprv` | P2PKH or P2SH | - | 54 | Litecoin | `0x019da462` - `Ltub` | `0x019d9cfe` - `Ltpv` | P2PKH or P2SH | m/44'/2' | 55 | Litecoin | `0x01b26ef6` - `Mtub` | `0x01b26792` - `Mtpv` | P2WPKH in P2SH | m/49'/2' | 56 | Litecoin Testnet | `0x0436f6e1` - `ttub` | `0x0436ef7d` - `ttpv` | P2PKH or P2SH | m/44'/1' | 57 | Lyncoin | `0x019c354f` - `Lpub` | `0x019c3115` - `Lprv` | P2PKH or P2SH | - | 58 | Lyncoin Testnet | `0x022dbf5b` - `Tpub` | `0x022dbb21` - `Tprv` | P2PKH or P2SH | - | 59 | Nexa | `0x42696720` - `xpub` | `0x426c6b73` - `xprv` | P2PKT or P2PKH or P2SH | m/44'/29223'| 60 | Nexa Testnet | `0x043587cf` - `xpub` | `0x04358394` - `xprv` | P2PKT or P2PKH or P2SH | m/44'/1' | 61 | Vertcoin | `0x0488b21e` - `vtcp` | `0x0488ade4` - `vtcv` | P2PKH or P2SH | m/44'/28' | 62 | Polis | `0x03e25d7e` - `ppub` | `0x03e25945` - `pprv` | P2PKH | m/44'/1997' | 63 | Syscoin | `0x04b24746` - `zpub` | `0x04b2430c` - `zprv` | P2WPKH | m/84'/57' | 64 | Syscoin | `0x02aa7ed3` - `Zpub` | `0x02aa7a99` - `Zprv` | Multi-signature P2WSH | - | 65 | 66 | ## Bitcoin Test Vectors 67 | 68 | ``` 69 | Mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about 70 | 71 | m/44'/0'/0' 72 | xprv9xpXFhFpqdQK3TmytPBqXtGSwS3DLjojFhTGht8gwAAii8py5X6pxeBnQ6ehJiyJ6nDjWGJfZ95WxByFXVkDxHXrqu53WCRGypk2ttuqncb 73 | xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj 74 | m/44'/0'/0'/0/0 address: 75 | 1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA 76 | 77 | m/49'/0'/0' 78 | yprvAHwhK6RbpuS3dgCYHM5jc2ZvEKd7Bi61u9FVhYMpgMSuZS613T1xxQeKTffhrHY79hZ5PsskBjcc6C2V7DrnsMsNaGDaWev3GLRQRgV7hxF 79 | ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP 80 | m/49'/0'/0'/0/0 address: 81 | 37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf 82 | 83 | m/84'/0'/0' 84 | zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE 85 | zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs 86 | m/84'/0'/0'/0/0 address: 87 | bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu 88 | ``` 89 | 90 | [Test vectors generation code](https://gist.github.com/clarkmoody/0a788d2e012ffe339bb7d3873e47c081) 91 | 92 | ## References 93 | 94 | * [BIP-0032: Hierarchical Deterministic Wallets # Serialization](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#serialization-format) 95 | * [SLIP-0032: Extended serialization format for BIP-32 wallets](https://github.com/satoshilabs/slips/blob/master/slip-0032.md) 96 | --------------------------------------------------------------------------------