User:Casascius/Base58Check-encoded objects proposal

From Bitcoin Wiki
Revision as of 17:39, 2 August 2012 by Casascius (talk | contribs)
Jump to: navigation, search

Proposal for redefinition of the "version byte"

Currently, all objects in Bitcoin when encoded in Base58Check have a "version byte". For example, a Bitcoin address has a byte of 0. A private key has a byte of 0x80. Derivative "altcoins" follow the scheme as well, and therefore their addresses and other objects are easily identified programmatically.

As a result of this practice, all Base58encoded objects tend to have similar prefixes that have come to be used to identify the object by users. A Bitcoin address always starts with a '1', a private key always starts with a '5'.

I propose that the "numberspace" in this version byte as used by implementers yield its importance to the "prefixspace" as seen by users. It is much more important that users be able to grasp Bitcoin concepts than it is for us to assign "version" bytes using some sort of sequential orthodoxy.

I propose that this byte be redefined as an "object identifier prefix". Object types should be recognized by two attributes: this byte, as well as the payload length. Because the payload cannot be arbitrarily shortened or lengthened accidentally by users (the checksum will catch omissions or insertions), the payload length is a safe attribute for reliable recognition of objects.

Regular private key

Indicates an uncompressed private key. Widely accepted as "wallet import format", "sipa format".


  • Version byte (object identifier prefix): 0x80
  • Payload bytes (beyond prefix): 32
  • How the user sees it: Always 51 characters beginning with '5' (specifically: 5H, 5J, or 5K)
  • Range in base58 encoding:
    • Lowest possible value: 5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU
    • Highest possible value: 5Km2kuu7vtFDPpxywn4u3NLu8iSdrqhxWT8tUKjeEXs2f9yxoWz

Compressed private key

Present specification

  • Version byte: 0x00
  • Payload bytes (beyond prefix): 33 (32 for the key, plus the constant 0x01)
  • How the user sees it: Always 52 characters, beginning with K or L
  • Lowest possible value: KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73Nd2Mcv1
  • Highest possible value: L5oLkpV3aqBjhki6LmvChTCq73v9gyymzzMpBbhDLjDpKCuAXpsi


Rationale: Whether we like it or not, many users (particularly power users) will see base58 encoded objects, such as on paper wallets.

Since the distinction of compressed/uncompressed is of little practical difference to the user, and the question "why is this one 5 and that one K/L" an unnecessary burden that disregards simplicity, I propose a different encoding that both preserves the '5' and keeps a visual distinction there (in the second character) for those who can make use of it.

Backward compatibility with the current specification can be easily maintained under this proposal by always accepting the existing compressed private key format (0x80 + 32bytes + 0x01) as input, but applications should only output strings in the proposed format.

Proposed specification

  • Version byte (object identifier prefix): 0x82
  • Payload bytes (beyond prefix): 32
  • How the user sees it: Always 51 characters beginning with '5' (specifically: 5M, 5N, or 5P)
  • Range in base58 encoding:
    • Lowest possible value: 5Mhmw9M9nJvSXeYgrMgtzgwg3q4MWYYqJ6CziURYEBsR9t6VP82
    • Highest possible value: 5PeX7NoBdjbffU8PkwJtx1YSxwg5AFPi5jH6xd7SDqsoeMcxpoG
  • Note: By using 0x82 instead of 0x81 we ensure the second character always visually divulges the compressed status. If we used 0x81, then the prefix '5K' could belong to either, and would be ambiguous.

Proposed encoding for a passphrase-protected private key

This proposal contemplates existence of a private key that requires a decryption passphrase before it can be used.

I propose having the 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 include keys participating in multisig transactions. The second character ought to give a hint as to what is needed, and for a simple SHA256-based password, I propose the lowercase letter p.

I propose the string having an optional 15 bits of password typo resistance. That is, a 15-bit checksum of the password may be added so that the vast majority of password typos can be detected and reported to the user, rather than inadvertently accepted as correct, which will simply yield the wrong private key and frustrate the user. This checksum is optional, and a bit flag is defined for the purpose of disabling it.

To decrypt the key is to simply XOR it with the SHA256 hash of the valid passphrase.

Proposed specification

  • Object identifier prefix: 0x0205
  • Payload bytes (beyond prefix): 34
    • 2 bytes: password typo resistance
    • 32 bytes: Private key xor passphrase
  • How the user sees it: 54 characters always starting with '6p'
  • Range in base58check encoding:
    • Minimum value: 6pZbbCzeNu7567y9swhRL8zC4yXioQc6oaUmwPMof6zvChFcMrTmMp
    • Maximum value: 6ptXqrvUjVYbnPvXPrC2S4tRVvAFdXBKDUC7K96C9ukAKogUFQynhy

Password typo resistance bytes: 0x0000-0x7FFF are SHA256(correct password + "?")[0...1] & 0x7FFF. If 0x8000 is specified, then no password typo resistance is being provided. Values above 0x8000 are excluded from the definition of keys valid for this proposal. If the value were to be above 0xabb9, the prefix "6p" is lost and becomes "6q".


A Base58Check string starts with '5' when it has a version byte of 0x80 and a payload of 43 bytes. (range: 5h thru 5j - lowercase mimic!)