# Difference between revisions of "BIP 0038"

(→Reference implementation) |
|||

Line 128: | Line 128: | ||

==Reference implementation== | ==Reference implementation== | ||

− | + | Added to alpha version of Casascius Bitcoin Address Utility for Windows. | |

+ | |||

+ | |||

+ | ==Test vectors== | ||

+ | |||

+ | ===No compression, no EC multiply=== | ||

+ | |||

+ | Test 1: | ||

+ | *Passphrase: TestingOneTwoThree | ||

+ | *Encrypted: 6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg | ||

+ | *Unencrypted (WIF): 5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR | ||

+ | *Unencrypted (hex): CBF4B9F70470856BB4F40F80B87EDB90865997FFEE6DF315AB166D713AF433A5 | ||

+ | |||

+ | Test 2: | ||

+ | *Passphrase: Satoshi | ||

+ | *Encrypted: 6PRNFFkZc2NZ6dJqFfhRoFNMR9Lnyj7dYGrzdgXXVMXcxoKTePPX1dWByq | ||

+ | *Unencrypted (WIF): 5HtasZ6ofTHP6HCwTqTkLDuLQisYPah7aUnSKfC7h4hMUVw2gi5 | ||

+ | *Unencrypted (hex): 09C2686880095B1A4C249EE3AC4EEA8A014F11E6F986D0B5025AC1F39AFBD9AE | ||

+ | |||

+ | ===Compression, no EC multiply=== | ||

+ | |||

+ | Test 1: | ||

+ | *Passphrase: TestingOneTwoThree | ||

+ | *Encrypted: 6PYNKZ1EAgYgmQfmNVamxyXVWHzK5s6DGhwP4J5o44cvXdoY7sRzhtpUeo | ||

+ | *Unencrypted (WIF): L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP | ||

+ | *Unencrypted (hex): CBF4B9F70470856BB4F40F80B87EDB90865997FFEE6DF315AB166D713AF433A5 | ||

+ | |||

+ | Test 2: | ||

+ | *Passphrase: Satoshi | ||

+ | *Encrypted: 6PYLtMnXvfG3oJde97zRyLYFZCYizPU5T3LwgdYJz1fRhh16bU7u6PPmY7 | ||

+ | *Unencrypted (WIF): KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7 | ||

+ | *Unencrypted (hex): 09C2686880095B1A4C249EE3AC4EEA8A014F11E6F986D0B5025AC1F39AFBD9AE | ||

+ | |||

+ | ===EC multiply, no compression=== | ||

+ | |||

+ | Test 1: | ||

+ | *Passphrase: TestingOneTwoThree | ||

+ | *Passphrase code: passphrasepxFy57B9v8HtUsszJYKReoNDV6VHjUSGt8EVJmux9n1J3Ltf1gRxyDGXqnf9qm | ||

+ | *Encrypted key: 6PfU7JNp1Hh7quZAGxMkaW4vaVHXLG6PoUeDWfFdS4uZ3HkAJMBi5UytRL | ||

+ | *Bitcoin address: 16e6ecJdZVYz3nKBvuQZBnWcu25phBRLSN | ||

+ | *Unencrypted private key (WIF): 5KFJHvxE6XsjAtTKuTgcKfqaCrijBEijqfkRhEMxmXbLwS5xnjp | ||

+ | *Unencrypted private key (hex): BC7D4FA3F7F8D99538A213CF0D99611F443F557DE71AA40BE3420F0787A17CE4 | ||

+ | |||

+ | Test 2: | ||

+ | *Passphrase: Satoshi | ||

+ | *Passphrase code: passphraseoRDGAXTWzbp72eVbtUDdn1rwpgPUGjNZEc6CGBo8i5EC1FPW8wcnLdq4ThKzAS | ||

+ | *Encrypted key: 6PfSm3ax57sS7MwPbjaKpYMhWCYVrhrXBAWn1BVqoQtFzTq96QCWpg4g8X | ||

+ | *Bitcoin address: 1G62rdVbvMgdKGrUa7gS9wU8JwkSQKrVks | ||

+ | *Unencrypted private key (WIF): 5K3Fg3AAyXGU8tgth3F7XLKMhQtW8jSxSqFat5yPf3JhbScwxRW | ||

+ | *Unencrypted private key (hex): A123B68C240BBEE7C41C4EB1902F0B4DD692B0A770D78C72A80BD6505A143ADD |

## Revision as of 05:29, 22 November 2012

BIP: draft Title: Passphrase-protected private key Author: Mike Caldwell Status: Draft Type: Standards Track Created: 20-11-2012

## Contents

## Abstract

A method is proposed for encrypting and encoding a passphrase-protected Bitcoin private key record in the form of a 58-character Base58Check-encoded printable string. Encrypted private key records are intended for use on paper wallets and physical Bitcoins. Each record string contains all the information needed to reconstitute the private key except for a passphrase, and the methodology uses salting and *scrypt* to resist brute-force attacks.

The method provides two encoding methodologies - one permitting any known private key to be encrypted with any passphrase, and another permitting a shared private key generation scheme where the party generating the final key string and its associated Bitcoin address (such as a physical bitcoin manufacturer) knows only a string derived from the original passphrase, and where the original passphrase is needed in order to actually redeem funds sent to the associated Bitcoin address.

A 32-bit hash of the resulting Bitcoin address is encoded in plaintext within each encrypted key, so it can be correlated to a Bitcoin address with reasonable probability by someone not knowing the passphrase. The complete Bitcoin address can be derived through successful decryption of the key record.

## Copyright

This proposal is hereby placed in the public domain.

## Rationale

**User story:**As a Bitcoin user who uses paper wallets, I would like the ability to add encryption, so that my Bitcoin paper storage can be two factor: something I have plus something I know.**User story:**As a Bitcoin user who would like to pay a person or a company with a private key, I do not want to worry that any part of the communication path may result in the interception of the key and theft of my funds. I would prefer to offer an encrypted private key, and then follow it up with the password using a different communication channel (e.g. a phone call or SMS).**User story:**(EC-multiplied keys) As a user of physical bitcoins, I would like a third party to be able to create password-protected Bitcoin private keys for me, without them knowing the password, so I can benefit from the physical bitcoin without the issuer having access to the private key. I would like to be able to choose a password whose minimum length and required format does not preclude me from memorizing it or engraving it on my physical bitcoin, without exposing me to an undue risk of password cracking and/or theft by the manufacturer of the item.

## Specification

This proposal makes use of the following functions and definitions:

**AES256Encrypt, AES256Decrypt**: the simple form of the well-known AES block cipher without consideration for initialization vectors or block chaining. Each of these functions takes a 256-bit key and 16 bytes of input, and deterministically yields 16 bytes of output.**SHA256**, a well-known hashing algorithm that takes an arbitrary number of bytes as input and deterministically yields a 32-byte hash.**scrypt**: A well-known key derivation algorithm. It takes the following parameters: (string) password, (string) salt, (int) n, (int) r, (int) p, (int) length, and deterministically yields an array of bytes whose length is equal to the length parameter.**ECMultiply**: Multiplication of an elliptic curve point by a scalar integer with respect to the secp256k1 elliptic curve.**G, N**: Constants defined as part of the secp256k1 elliptic curve. G is an elliptic curve point, and N is a large positive integer.**Base58Check**: a method for encoding arrays of bytes using 58 alphanumeric characters commonly used in the Bitcoin ecosystem.

### Prefix

It is proposed that the resulting Base58Check-encoded string start with a '6'. The number '6' is intended to represent, from the perspective of the user, "a private key that needs something else to be usable" - an umbrella definition that could be understood in the future to include keys participating in multisig transactions, and was chosen with deference to the existing prefix '5' most commonly observed in Wallet Import Format which denotes an unencrypted private key.

It is proposed that the second character ought to give a hint as to what is needed as a second factor, and for an encrypted key requiring a passphrase, the uppercase letter P is proposed.

To keep the size of the encrypted key down, no initialization vectors (IVs) are used in the AES encryption. Rather, suitable values for IV-like use are derived using scrypt from the passphrase and from using a 32-bit hash of the resulting Bitcoin address as salt.

### Proposed specification

- Object identifier prefix: 0x0142 (non-EC-multiplied) or 0x0143 (EC-multiplied). These are constant bytes that appear at the beginning of the Base58Check-encoded record, and their presence causes the resulting string to have a predictable prefix.
- How the user sees it: 58 characters always starting with '6P'
- Visual cues are present in the third character for visually identifying the EC-multiply and compress flag.

- Count of payload bytes (beyond prefix): 37
- 1 byte (
*flagbyte*):- the most significant two bits are set as follows to preserve the visibility of the compression flag in the prefix, as well as to keep the payload within the range of allowable values that keep the "6P" prefix intact. For non-EC-multiplied keys, the bits are 11. For EC-multiplied keys, the bits are 00.
- the bit with value 0x20 when set indicates the key should be converted to a bitcoin address using the compressed public key format.
- the bits with values 0x10 and 0x08 are reserved for a future specification that contemplates using multisig as a way to combine the factors such that parties in possession of the separate factors can independently sign a proposed transaction without requiring that any party possess both factors. These bits must be 0 to comply with this version of the specification.
- remaining bits are reserved for future use and must all be 0 to comply with this version of the specification.

- 4 bytes: SHA256(SHA256(expected_bitcoin_address))[0...3], used both for typo checking and as salt
- 16 bytes: firsthalf: An AES-encrypted key material record (contents depend on whether EC multiplication is used)
- 16 bytes: lasthalf: An AES-encrypted key material record (contents depend on whether EC multiplication is used)

- 1 byte (
- Range in base58check encoding for non-EC-multiplied keys without compression (prefix 6PR):
- Minimum value: 6PRHv1jg1ytiE4kT2QtrUz8gEjMQghZDWg1FuxjdYDzjUkcJeGdFj9q9Vi (based on 01 42 C0 plus thirty-six 00's)
- Maximum value: 6PRWdmoT1ZursVcr5NiD14p5bHrKVGPG7yeEoEeRb8FVaqYSHnZTLEbYsU (based on 01 42 C0 plus thirty-six FF's)

- Range in base58check encoding for non-EC-multiplied keys with compression (prefix 6PY):
- Minimum value: 6PYJxKpVnkXUsnZAfD2B5ZsZafJYNp4ezQQeCjs39494qUUXLnXijLx6LG (based on 01 42 E0 plus thirty-six 00's)
- Maximum value: 6PYXg5tGnLYdXDRZiAqXbeYxwDoTBNthbi3d61mqBxPpwZQezJTvQHsCnk (based on 01 42 E0 plus thirty-six FF's)

- Range in base58check encoding for EC-multiplied keys without compression (prefix 6Pf):
- Minimum value: 6PfKzduKZXAFXWMtJ19Vg9cSvbFg4va6U8p2VWzSjtHQCCLk3JSBpUvfpf (based on 01 43 00 plus thirty-six 00's)
- Maximum value: 6PfYiPy6Z7BQAwEHLxxrCEHrH9kasVQ95ST1NnuEnnYAJHGsgpNPQ9dTHc (based on 01 43 00 plus thirty-six FF's)

- Range in base58check encoding for non-EC-multiplied keys with compression (prefix 6Pn):
- Minimum value: 6PnM2wz9LHo2BEAbvoGpGjMLGXCom35XwsDQnJ7rLiRjYvCxjpLenmoBsR (based on 01 43 20 plus thirty-six 00's)
- Maximum value: 6PnZki3vKspApf2zym6Anp2jd5hiZbuaZArPfa2ePcgVf196PLGrQNyVUh (based on 01 43 20 plus thirty-six FF's)

#### Encryption when EC multiply flag is not used

Encrypting a private key without the EC multiplication offers the advantage that any known private key can be encrypted. The party performing the encryption must know the passphrase.

Encryption steps:

- Compute the Bitcoin address (ASCII), and take the first four bytes of SHA256(SHA256()) of it. Let's call this "addresshash".
- Derive a key from the passphrase using scrypt
- Parameters:
*passphrase*is the passphrase itself encoded in UTF-8.*addresshash*came from the earlier step, n=16384, r=8, p=8, length=64 (n, r, p are provisional and subject to consensus) - Let's split the resulting 64 bytes in half, and call them
*derivedhalf1*and*derivedhalf2*.

- Parameters:
- Do AES256Encrypt(bitcoinprivkey[0...15] xor derivedhalf1[0...15], derivedhalf2), call the 16-byte result
*encryptedhalf1* - Do AES256Encrypt(bitcoinprivkey[16...31] xor derivedhalf1[16...31], derivedhalf2), call the 16-byte result
*encryptedhalf2*

The encrypted private key is the Base58Check-encoded concatenation of the following:

- 0x0142 +
*flagbyte*+*salt*+*encryptedhalf1*+*encryptedhalf2*

Decryption steps:

- Collect encrypted private key and passphrase from user.
- Derive
*derivedhalf1*and*derivedhalf2*by passing the passphrase and*addresshash*into scrypt function. - Decrypt
*encryptedhalf1*and*encryptedhalf2*using AES256Decrypt, merge them to form the encrypted private key. - Convert that private key into a Bitcoin address, honoring the compression preference specified in
*flagbyte*of the encrypted key record. - Hash the Bitcoin address, and verify that
*addresshash*from the encrypted private key record matches the hash. If not, report that the passphrase entry was incorrect.

#### Encryption when EC multiply mode is used

Encrypting a private key with EC multiplication offers the ability for someone to generate encrypted keys knowing only an EC point derived from the original passphrase and some salt generated by the passphrase's owner, and without knowing the passphrase itself. Only the person who knows the original passphrase can decrypt the private key. This methodology does not offer the ability to encrypt a known private key - this means that the process of creating encrypted keys is also the process of generating new addresses.

Steps performed by the person with the passphrase (call him the *owner*):

- Generate 8 random bytes, call this
*ownersalt* - Derive a key from the passphrase using scrypt
- Parameters:
*passphrase*is the passphrase itself encoded in UTF-8. salt is*ownersalt*. n=16384, r=8, p=8, length=32. (parameters n, r, p are provisional and subject to consensus-seeking) - Call the resulting 32 bytes
*passfactor*.

- Parameters:
- Compute the elliptic curve point G *
*passfactor*, and convert the result to compressed notation (33 bytes). Call this*passpoint*. Compressed notation is used for this purpose regardless of whether the intent is to create Bitcoin addresses with or without compressed public keys. - Convey
*ownersalt*and*passpoint*to the party generating the keys, along with a checksum to ensure integrity.- The following Base58Check-encoded format is recommended for this purpose: bytes "2C E9 B3 E1 FF 39 E2 53" followed by
*ownersalt*and then*passpoint*. The resulting string will start with the word "passphrase" due to the constant bytes, will be 72 characters in length, and encodes 49 bytes (8 bytes constant + 8 bytes*ownersalt*+ 33 bytes*passpoint*). The checksum is handled in the Base58Check encoding.

- The following Base58Check-encoded format is recommended for this purpose: bytes "2C E9 B3 E1 FF 39 E2 53" followed by

Steps to create new encrypted private keys given an encrypted password string from *owner* (so we have *ownersalt* and *passpoint*, but we do not have *passfactor* or the passphrase):

- Generate 24 random bytes, call this
*seedb*. Take SHA256(SHA256(*seedb*)) to yield 32 bytes, call this*factorb*. - ECMultiply
*passpoint*by*factorb*. Use the resulting EC point as a public key and hash it into a Bitcoin address using either compressed or uncompressed public key methodology (specify which methodology is used inside*flagbyte*). This is the generated Bitcoin address, call it*generatedaddress*. - Take the first four bytes of SHA256(SHA256(
*generatedaddress*)) and call it*addresshash*. - Now we will encrypt
*seedb*. Derive a second key from*passpoint*using scrypt- Parameters:
*passphrase*is*passpoint*provided from the first party (expressed in binary as 33 bytes).*salt*is*addresshash*+*ownersalt*(concatenation), n=16384, r=8, p=8, length=64 (n, r, p are provisional and subject to consensus) - Split the result into two 16-byte halves and call them
*derivedhalf1*and*derivedhalf2*.

- Parameters:
- Do AES256Encrypt(seedb[0...15]] xor derivedhalf1[0...15], derivedhalf2), call the 16-byte result
*encryptedpart1* - Do AES256Encrypt((encryptedpart1[8...15] + seedb[16...23]) xor derivedhalf1[16...31], derivedhalf2), call the 16-byte result
*encryptedseedb*. + is concatenation.

The encrypted private key is the Base58Check-encoded concatenation of the following:

- 0x0143 +
*flagbyte*+*addresshash*+*ownersalt*+*encryptedpart1*[0...7] +*encryptedpart2*

Decryption steps:

- Collect encrypted private key and passphrase from user.
- Derive
*passfactor*using scrypt with*ownersalt*and the user's passphrase and use it to recompute*passpoint* - Derive decryption key for
*seedb*using scrypt with*passpoint*,*addresshash*, and*ownersalt* - Decrypt
*encryptedpart2*using AES256Decrypt to yield the last 8 bytes of*seedb*and the last 8 bytes of*encryptedpart1*. - Decrypt
*encryptedpart1*to yield the remainder of*seedb*. - Use
*seedb*to compute*factorb*. - Multiply
*passfactor*by*factorb*mod N to yield the private key associated with*generatedaddress*. - Convert that private key into a Bitcoin address, honoring the compression preference specified in the encrypted key.
- Hash the Bitcoin address, and verify that
*addresshash*from the encrypted private key record matches the hash. If not, report that the passphrase entry was incorrect.

## Backwards compatibility

Backwards compatibility is minimally applicable since this is a new standard that at most extends Wallet Import Format. It is assumed that an entry point for private key data may also accept existing formats of private keys (such as hexadecimal and Wallet Import Format); this draft uses a key format that cannot be mistaken for any existing one and preserves auto-detection capabilities.

## Reference implementation

Added to alpha version of Casascius Bitcoin Address Utility for Windows.

## Test vectors

### No compression, no EC multiply

Test 1:

- Passphrase: TestingOneTwoThree
- Encrypted: 6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg
- Unencrypted (WIF): 5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR
- Unencrypted (hex): CBF4B9F70470856BB4F40F80B87EDB90865997FFEE6DF315AB166D713AF433A5

Test 2:

- Passphrase: Satoshi
- Encrypted: 6PRNFFkZc2NZ6dJqFfhRoFNMR9Lnyj7dYGrzdgXXVMXcxoKTePPX1dWByq
- Unencrypted (WIF): 5HtasZ6ofTHP6HCwTqTkLDuLQisYPah7aUnSKfC7h4hMUVw2gi5
- Unencrypted (hex): 09C2686880095B1A4C249EE3AC4EEA8A014F11E6F986D0B5025AC1F39AFBD9AE

### Compression, no EC multiply

Test 1:

- Passphrase: TestingOneTwoThree
- Encrypted: 6PYNKZ1EAgYgmQfmNVamxyXVWHzK5s6DGhwP4J5o44cvXdoY7sRzhtpUeo
- Unencrypted (WIF): L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP
- Unencrypted (hex): CBF4B9F70470856BB4F40F80B87EDB90865997FFEE6DF315AB166D713AF433A5

Test 2:

- Passphrase: Satoshi
- Encrypted: 6PYLtMnXvfG3oJde97zRyLYFZCYizPU5T3LwgdYJz1fRhh16bU7u6PPmY7
- Unencrypted (WIF): KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7
- Unencrypted (hex): 09C2686880095B1A4C249EE3AC4EEA8A014F11E6F986D0B5025AC1F39AFBD9AE

### EC multiply, no compression

Test 1:

- Passphrase: TestingOneTwoThree
- Passphrase code: passphrasepxFy57B9v8HtUsszJYKReoNDV6VHjUSGt8EVJmux9n1J3Ltf1gRxyDGXqnf9qm
- Encrypted key: 6PfU7JNp1Hh7quZAGxMkaW4vaVHXLG6PoUeDWfFdS4uZ3HkAJMBi5UytRL
- Bitcoin address: 16e6ecJdZVYz3nKBvuQZBnWcu25phBRLSN
- Unencrypted private key (WIF): 5KFJHvxE6XsjAtTKuTgcKfqaCrijBEijqfkRhEMxmXbLwS5xnjp
- Unencrypted private key (hex): BC7D4FA3F7F8D99538A213CF0D99611F443F557DE71AA40BE3420F0787A17CE4

Test 2:

- Passphrase: Satoshi
- Passphrase code: passphraseoRDGAXTWzbp72eVbtUDdn1rwpgPUGjNZEc6CGBo8i5EC1FPW8wcnLdq4ThKzAS
- Encrypted key: 6PfSm3ax57sS7MwPbjaKpYMhWCYVrhrXBAWn1BVqoQtFzTq96QCWpg4g8X
- Bitcoin address: 1G62rdVbvMgdKGrUa7gS9wU8JwkSQKrVks
- Unencrypted private key (WIF): 5K3Fg3AAyXGU8tgth3F7XLKMhQtW8jSxSqFat5yPf3JhbScwxRW
- Unencrypted private key (hex): A123B68C240BBEE7C41C4EB1902F0B4DD692B0A770D78C72A80BD6505A143ADD