Difference between revisions of "Mini private key format"

From Bitcoin Wiki
Jump to: navigation, search
(Decoding: REmoving the PBKDF2 stuff (not implemented in practice) and switching the sample to a 30-char key)
m
 
(27 intermediate revisions by 9 users not shown)
Line 1: Line 1:
[[Image:QR-privkeys-sidebyside.png|thumb|right|QR codes of the same private key, in mini versus regular private key format. Both codes have the same dot density and error correction level, but the mini key is 57% of the full code's size.]]
+
[[Image:QR-privkeys-sidebyside.png|thumb|right|Comparison of QR codes of the same private key, encoded in mini private key format (left) and [[wallet import format]] (right). Both codes have the same dot density and error correction level, but the mini key is 57% of the full code's size.]]
The '''mini private key format''' is a method of encoding a Bitcoin private key in as few as 22 characters so that it can be embedded in a small space. This private key format was first used in Casascius physical bitcoins, and is also favorable for use in QR codes.  The fewer characters encoded in a QR code, the lower dot density can be used, as well as more dots allocated to error correction in the same space, significantly improving readability and resistance to damage. The mini private key format offers its own built-in check code as a small margin of protection against typos.
+
[[Image:Redeemed Denarium physical bitcoin.jpg|thumb|right|A minikey in a small space on a physical bitcoin]]
 +
{{sample}}
 +
The '''mini private key format''' is a method of encoding a Bitcoin private key in as few as 30 characters for the purpose of being embedded in a small space. A private key encoded in this format is called a '''minikey'''. This private key format was designed for and first used in [[Casascius physical bitcoins]], and is also favorable for use in QR codes.  The fewer characters encoded in a QR code, the lower dot density can be used, as well as more dots allocated to error correction in the same space, significantly improving readability and resistance to damage. The mini private key format offers its own built-in check code as a small margin of protection against typos.
  
An example key using this encoding is '''S4b3N3oGqDqR5jNuxEvDwf'''.
+
Casascius Series 1 holograms use a 22-character variant of the minikey format, instead of 30 characters. Everything is the same other than the length. To properly implement minikey redemption, services and clients must support the 30-character format, but may optionally support the 22-character format as well to allow redemption of old Casascius coins. Use of the 22-character format for future applications is discouraged due to security considerations; the standard 30-character format should be used instead.
  
==Usage on a physical bitcoin==
+
An example key using this encoding is '''S6c56bnXQiBjk9m{{taggant private key}}qSYE7ykVQ7NzrRy'''.
The way it might appear within a physical bitcoin is on a round card printed as follows:
 
  
<center>S4b3N<br/>3oGqDq<br/>R5jNux<br/>EvDwf</center>
+
==Usage==
 +
===Physical bitcoins===
 +
{{multiple image|align=vertical|width=300
 +
|image1=Miniprivkeys.jpg
 +
|image2=Minipubkeys.jpg
 +
|footer=Paper disc inserts for [[Casascius physical bitcoins|Casascius coins]] with minikeys on the obverse (top) and corresponding address prefixes on the reverse (bottom)
 +
}}
 +
Minikeys are used extensively on physical bitcoins, because their small size allows them to be printed and read easily even on tiny surfaces inside the coins. Typically, a small paper or plastic disc is placed behind a tamper-evident security hologram on the back of a metal coin or bar, with the minikey printed on the inside such that it can only be read if the security hologram is removed.
 +
 
 +
Some physical bitcoins include a window in the security hologram to view the back of this disc, which includes the prefix of the address corresponding to the hidden minikey.
 +
 
 +
===1D barcodes===
 +
The mini private key is small enough to fit in a one-dimensional barcode while still remaining practical.  Among the most popular one-dimensional barcode symbologies, the one known as "Code 128" is best suited for encoding a minikey due to its favorable data density and support for mixed case strings.  The variant known as "Code 128-B" produces the shortest code for strings containing lowercase characters.
 +
 
 +
The sample private minikey encoded with Code 128-B looks like this:
 +
 
 +
[[Image:Private_minikey_in_1D_barcode.gif]]
 +
 
 +
===2D barcodes===
 +
The mini private key is suitable for use in QR codes.  The recommended settings for maximizing readability are: QR version 3, error correction level Q (near highest, 25% possible lost codeword recovery).  This results in a 29x29 grid.  A minikey QR code can also fit in a 25x25 grid with QR version 2, error correction level L (lowest, 7% possible lost codeword recovery).
 +
 
 +
The sample private minikey encoded as a QR code on a 29x29 grid looks like this:
 +
 
 +
[[Image:Private_minikey_in_2D_barcode.gif]]
  
 
==Import==
 
==Import==
 
Mini private keys can be imported through the following clients/services:
 
Mini private keys can be imported through the following clients/services:
  
* [[Blockchain.info]]
+
===Applications===
* [[Strongcoin]]
 
 
* [[Armory]]
 
* [[Armory]]
* [[Mt. Gox]]
 
  
 
The current mainline ("Satoshi") client cannot currently be used to import minikeys.
 
The current mainline ("Satoshi") client cannot currently be used to import minikeys.
 +
 +
===Web===
 +
 +
* [[BlockChain.info]]
 +
** Private keys can be imported into a Blockchain.info wallet and bitcoins can be sent to another address immediately upon import without needing to wait for any confirmations.  Even after import, funds remain associated with the private key until they are actually spent to a different address.
 +
* [[StrongCoin]]
  
 
==Decoding==
 
==Decoding==
The private key encoding consists of 22, 26, or 30 alphanumeric characters from the [[base58]] alphabet used in Bitcoin.  The first of the characters is always the uppercase letter S.
+
The private key encoding consists of 30 alphanumeric characters from the [[base58]] alphabet used in Bitcoin.  The first of the characters is always the uppercase letter S.
  
A simple test must be performed to determine which method shall be used:
+
To determine whether the minikey is valid:
  
 
# Add a question mark to the end of the mini private key string.
 
# Add a question mark to the end of the mini private key string.
# Take the SHA256 hash of the entire string.  However, we will only looking at the first two bytes of the result.
+
# Take the SHA256 hash of the entire string.  However, we will only look at the first byte of the result.
 
# If the first byte is 00, the string is a well-formed minikey.  If the first byte is not 00, the string should be rejected as a minikey.
 
# If the first byte is 00, the string is a well-formed minikey.  If the first byte is not 00, the string should be rejected as a minikey.
  
 
===Example with SHA256===
 
===Example with SHA256===
Here is an example with the sample private key Sz9vkwiuc5ghNWKcemKoNi66pJ6AgM.
+
Here is an example with the sample private key <tt>S6c56bnXQiBjk9mq{{taggant private key}}SYE7ykVQ7NzrRy</tt>.
 +
 
 +
The string "<tt>S6c56bnXQiBjk9{{taggant private key}}mqSYE7ykVQ7NzrRy?</tt>" has a SHA256 value that begins with 00, so it is well-formed.
 +
 
 +
To obtain the full 256-bit private key, simply take the SHA256 hash of the entire string.  There is no encoding for line breaks in the string, even if the key is broken into multiple lines for printing.  The SHA256 should be taken of exactly thirty bytes.
 +
 
 +
SHA256("S6c56bnXQiBjk9{{taggant private key}}mqSYE7ykVQ7NzrRy") = 4C7A9640C72DC2099F23715D0C8A0D8A35F8906E3CAB61DD3F78B67BF887C9AB 
  
The string "Sz9vkwiuc5ghNWKcemKoNi66pJ6AgM?" has a SHA256 value that begins with 00, so it is well-formed.
+
This sample key in [[wallet import format]] is <tt>5JPy8Zg7z4P7RSLsiqcqyeAF1{{taggant private key}}935zjNUdMxcDeVrtU1oarrgnB7</tt>, and the corresponding [[Bitcoin address]] is <tt>1CciesT23BNionJe{{taggant address}}Xrbxmjc7ywfiyM4oLW</tt>.
  
To obtain the full 256-bit private key, simply take the SHA256 hash of the entire string.  There is no encoding for breaks in the string even if printed that way - the SHA256 should be taken of exactly thirty bytes.
+
==== Command line verification ====
 +
To calculate SHA256 from the command line on OSX or Linux devices:
  
  SHA256("Sz9vkwiuc5ghNWKcemKoNi66pJ6AgM") = 68DD9613911D884866A613EE909A8C3B1877D47BF4B59350AA44ED1687FA5127
+
  echo -n "S6c56bnXQiBjk9{{taggant private key}}mqSYE7ykVQ7NzrRy?" | shasum -a 256
  
This sample key in [[wallet export format]] is 5JcUEPy6ZNEU2beoyAZdPwjtZWPeiU2j2nDwMjGXWeoD87LrURL, and the corresponding [[Bitcoin address]] is 1HwWMmDFaFLDBt3XRfCce3kA1rR2Syb1W2.
+
That should output a line of text like "<tt>000f2453798ad4f951eecced2242eaef3e1cbc8a7c813c203ac7ffe57060355d  -</tt>". Since the first two characters are <tt>00</tt> the verification passes for the mini key <tt>S6c56bnXQiBjk9{{taggant private key}}mqSYE7ykVQ7NzrRy</tt>
  
 
==Check code==
 
==Check code==
The mini private key format offers a simple typo check code.  Mini private keys must be generated in a "brute force" fashion, keeping only keys that conform to the format's rules.  If a key is well-formed (22, 26, or 30 Base58 characters starting with S), but fails the hash check, then it probably contains a typo.
+
The mini private key format offers a simple typo check code.  Mini private keys must be generated in a "brute force" fashion, keeping only keys that conform to the format's rules.  If a key is well-formed (30 Base58 characters starting with S), but fails the hash check, then it probably contains a typo.
 
 
If the SHA256 hash of the string followed by '?' doesn't result in something that begins with 0x00 or 0x01, the mini private key is not valid.
 
  
If it starts with 0x01, but the second byte is higher than the allowed maximum (0x30), the mini private key is invalid.  Note that the maximum is likely to be increased as computing power advances.
+
If the SHA256 hash of the string followed by '?' doesn't result in something that begins with 0x00, the string is not a valid mini private key.
  
 
==Creating mini private keys==
 
==Creating mini private keys==
Line 53: Line 86:
 
To create mini private keys, simply create random strings that satisfy the well-formedness requirement, and then eliminate the ones that do not pass the typo check.  (This means eliminating more than 99% of the candidates.)  Then use the appropriate algorithm to compute the corresponding private key, and in turn, the matching Bitcoin address.  The Bitcoin address can always be computed from just the private key.
 
To create mini private keys, simply create random strings that satisfy the well-formedness requirement, and then eliminate the ones that do not pass the typo check.  (This means eliminating more than 99% of the candidates.)  Then use the appropriate algorithm to compute the corresponding private key, and in turn, the matching Bitcoin address.  The Bitcoin address can always be computed from just the private key.
  
It is '''highly recommended''' to use the PBKDF2 function and select at least 4096 rounds.  (This means selecting strings as keys whose SHA256(string+"?") begins with 0x0128).  Mini private keys offer a minimum of entropy, so the more rounds you choose, the stronger your keys will resist advances in technology to do brute-force cracks.
+
It is strongly advisable to avoid using the digit "1" in minikeys unless it is being printed in such a way where a user is unlikely to mistake it for the lowercase letter "l"Few clients and redemption tools are prepared to tell the user that their entry containing the letter "l" should actually be the number "1" - rather, they will simply reject the code and may leave the user confused.
 
 
The SHA256 function is provided for the convenience of hardware and software environments that offer very limited computational power, such as microcontrollers.  It provides for the ability to generate a valid mini private key with, on average, 256 operations of SHA256.  However, it also offers the lowest brute force attack resistanceSuch keys are only suitable for situations where a "throwaway" Bitcoin address is needed, such as on a coupon or ticket where the amount will be spent soon, as opposed to an address where bitcoins will be kept long term.  The strongest possible PBKDF2-based keys should always be preferred in any environment where generating them is possible.
 
  
 
In all cases, you '''must''' use a secure cryptographic random number generator to eliminate risks of predictability of the random strings.
 
In all cases, you '''must''' use a secure cryptographic random number generator to eliminate risks of predictability of the random strings.
 
==Entropy considerations==
 
The 22-character mini private key code appears to offer about 123 bits of entropy, determined as log2(58^21).  (Because the first character is fixed, there are 21 symbols which can each have one of 58 values).
 
 
The 26-character version offers about 146 bits of entropy by the same calculation.  The 30-character version offers over 169 bits, which exceeds the 160-bits found in a Bitcoin address.
 
  
 
==Python Code==
 
==Python Code==
The following code produces sample SHA256-based mini private keys in Python.  For real-world use, ''random'' must be replaced with a better source of entropy, as the Python documentation for ''random'' states the function ''"is completely unsuitable for cryptographic purposes"''.
+
The following code produces sample 30-character SHA256-based mini private keys in Python.  For real-world use, ''random'' must be replaced with a better source of entropy, as the Python documentation for ''random'' states the function ''"is completely unsuitable for cryptographic purposes"''.
  
 
<source lang="python">
 
<source lang="python">
Line 71: Line 97:
 
import hashlib
 
import hashlib
  
BASE58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
+
BASE58 = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
  
 
def Candidate():
 
def Candidate():
Line 78: Line 104:
 
     """
 
     """
 
     return('%s%s' % ('S', ''.join(
 
     return('%s%s' % ('S', ''.join(
         [BASE58[ random.randrange(0,len(BASE58)) ] for i in range(21)])))
+
         [BASE58[ random.randrange(0,len(BASE58)) ] for i in range(29)])))
  
 
def GenerateKeys(numKeys = 10):
 
def GenerateKeys(numKeys = 10):
Line 107: Line 133:
 
         except KeyboardInterrupt:
 
         except KeyboardInterrupt:
 
             break
 
             break
     print('\n%s: %i\n%s: %i\n%s: %r\n%s: %.1f' %
+
     print('\n%s: %i\n%s: %i\n%s: %.1f' %
 
           ('Keys Generated', keysGenerated,
 
           ('Keys Generated', keysGenerated,
 
           'Total Candidates', totalCandidates,
 
           'Total Candidates', totalCandidates,
          'Additional Security', additionalSecurity,
 
 
           'Reject Percentage',
 
           'Reject Percentage',
 
           100*(1.0-keysGenerated/float(totalCandidates))))
 
           100*(1.0-keysGenerated/float(totalCandidates))))
Line 129: Line 154:
 
     Checks for typos in the short key.
 
     Checks for typos in the short key.
 
     """
 
     """
     if len(shortKey) != 22:
+
     if len(shortKey) != 30:
 
         return False
 
         return False
 
     t = '%s?' % shortKey
 
     t = '%s?' % shortKey

Latest revision as of 03:03, 10 August 2017

Comparison of QR codes of the same private key, encoded in mini private key format (left) and wallet import format (right). Both codes have the same dot density and error correction level, but the mini key is 57% of the full code's size.
A minikey in a small space on a physical bitcoin

This page contains sample addresses and/or private keys. Do not send bitcoins to or import any sample keys; you will lose your money.

The mini private key format is a method of encoding a Bitcoin private key in as few as 30 characters for the purpose of being embedded in a small space. A private key encoded in this format is called a minikey. This private key format was designed for and first used in Casascius physical bitcoins, and is also favorable for use in QR codes. The fewer characters encoded in a QR code, the lower dot density can be used, as well as more dots allocated to error correction in the same space, significantly improving readability and resistance to damage. The mini private key format offers its own built-in check code as a small margin of protection against typos.

Casascius Series 1 holograms use a 22-character variant of the minikey format, instead of 30 characters. Everything is the same other than the length. To properly implement minikey redemption, services and clients must support the 30-character format, but may optionally support the 22-character format as well to allow redemption of old Casascius coins. Use of the 22-character format for future applications is discouraged due to security considerations; the standard 30-character format should be used instead.

An example key using this encoding is S6c56bnXQiBjk9m_SAMPLE_PRIVATE_KEY_DO_NOT_IMPORT_qSYE7ykVQ7NzrRy.

Usage

Physical bitcoins

Paper disc inserts for Casascius coins with minikeys on the obverse (top) and corresponding address prefixes on the reverse (bottom)

Minikeys are used extensively on physical bitcoins, because their small size allows them to be printed and read easily even on tiny surfaces inside the coins. Typically, a small paper or plastic disc is placed behind a tamper-evident security hologram on the back of a metal coin or bar, with the minikey printed on the inside such that it can only be read if the security hologram is removed.

Some physical bitcoins include a window in the security hologram to view the back of this disc, which includes the prefix of the address corresponding to the hidden minikey.

1D barcodes

The mini private key is small enough to fit in a one-dimensional barcode while still remaining practical. Among the most popular one-dimensional barcode symbologies, the one known as "Code 128" is best suited for encoding a minikey due to its favorable data density and support for mixed case strings. The variant known as "Code 128-B" produces the shortest code for strings containing lowercase characters.

The sample private minikey encoded with Code 128-B looks like this:

Private minikey in 1D barcode.gif

2D barcodes

The mini private key is suitable for use in QR codes. The recommended settings for maximizing readability are: QR version 3, error correction level Q (near highest, 25% possible lost codeword recovery). This results in a 29x29 grid. A minikey QR code can also fit in a 25x25 grid with QR version 2, error correction level L (lowest, 7% possible lost codeword recovery).

The sample private minikey encoded as a QR code on a 29x29 grid looks like this:

Private minikey in 2D barcode.gif

Import

Mini private keys can be imported through the following clients/services:

Applications

The current mainline ("Satoshi") client cannot currently be used to import minikeys.

Web

  • BlockChain.info
    • Private keys can be imported into a Blockchain.info wallet and bitcoins can be sent to another address immediately upon import without needing to wait for any confirmations. Even after import, funds remain associated with the private key until they are actually spent to a different address.
  • StrongCoin

Decoding

The private key encoding consists of 30 alphanumeric characters from the base58 alphabet used in Bitcoin. The first of the characters is always the uppercase letter S.

To determine whether the minikey is valid:

  1. Add a question mark to the end of the mini private key string.
  2. Take the SHA256 hash of the entire string. However, we will only look at the first byte of the result.
  3. If the first byte is 00, the string is a well-formed minikey. If the first byte is not 00, the string should be rejected as a minikey.

Example with SHA256

Here is an example with the sample private key S6c56bnXQiBjk9mq_SAMPLE_PRIVATE_KEY_DO_NOT_IMPORT_SYE7ykVQ7NzrRy.

The string "S6c56bnXQiBjk9_SAMPLE_PRIVATE_KEY_DO_NOT_IMPORT_mqSYE7ykVQ7NzrRy?" has a SHA256 value that begins with 00, so it is well-formed.

To obtain the full 256-bit private key, simply take the SHA256 hash of the entire string. There is no encoding for line breaks in the string, even if the key is broken into multiple lines for printing. The SHA256 should be taken of exactly thirty bytes.

SHA256("S6c56bnXQiBjk9_SAMPLE_PRIVATE_KEY_DO_NOT_IMPORT_mqSYE7ykVQ7NzrRy") = 4C7A9640C72DC2099F23715D0C8A0D8A35F8906E3CAB61DD3F78B67BF887C9AB  

This sample key in wallet import format is 5JPy8Zg7z4P7RSLsiqcqyeAF1_SAMPLE_PRIVATE_KEY_DO_NOT_IMPORT_935zjNUdMxcDeVrtU1oarrgnB7, and the corresponding Bitcoin address is 1CciesT23BNionJe_SAMPLE_ADDRESS_DO_NOT_SEND_Xrbxmjc7ywfiyM4oLW.

Command line verification

To calculate SHA256 from the command line on OSX or Linux devices:

echo -n "S6c56bnXQiBjk9_SAMPLE_PRIVATE_KEY_DO_NOT_IMPORT_mqSYE7ykVQ7NzrRy?" | shasum -a 256

That should output a line of text like "000f2453798ad4f951eecced2242eaef3e1cbc8a7c813c203ac7ffe57060355d -". Since the first two characters are 00 the verification passes for the mini key S6c56bnXQiBjk9_SAMPLE_PRIVATE_KEY_DO_NOT_IMPORT_mqSYE7ykVQ7NzrRy

Check code

The mini private key format offers a simple typo check code. Mini private keys must be generated in a "brute force" fashion, keeping only keys that conform to the format's rules. If a key is well-formed (30 Base58 characters starting with S), but fails the hash check, then it probably contains a typo.

If the SHA256 hash of the string followed by '?' doesn't result in something that begins with 0x00, the string is not a valid mini private key.

Creating mini private keys

Creating mini private keys is relatively simple. One program which can create such keys is Casascius Bitcoin Utility.

Mini private keys must be created "from scratch", as the conversion from mini private key to full-size private key is one-way. In other words, there is no way to convert an existing full-size private key into a mini private key.

To create mini private keys, simply create random strings that satisfy the well-formedness requirement, and then eliminate the ones that do not pass the typo check. (This means eliminating more than 99% of the candidates.) Then use the appropriate algorithm to compute the corresponding private key, and in turn, the matching Bitcoin address. The Bitcoin address can always be computed from just the private key.

It is strongly advisable to avoid using the digit "1" in minikeys unless it is being printed in such a way where a user is unlikely to mistake it for the lowercase letter "l". Few clients and redemption tools are prepared to tell the user that their entry containing the letter "l" should actually be the number "1" - rather, they will simply reject the code and may leave the user confused.

In all cases, you must use a secure cryptographic random number generator to eliminate risks of predictability of the random strings.

Python Code

The following code produces sample 30-character SHA256-based mini private keys in Python. For real-world use, random must be replaced with a better source of entropy, as the Python documentation for random states the function "is completely unsuitable for cryptographic purposes".

import random
import hashlib

BASE58 = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def Candidate():
    """
    Generate a random, well-formed mini private key.
    """
    return('%s%s' % ('S', ''.join(
        [BASE58[ random.randrange(0,len(BASE58)) ] for i in range(29)])))

def GenerateKeys(numKeys = 10):
    """
    Generate mini private keys and output the mini key as well as the full
    private key. numKeys is The number of keys to generate, and 
    """
    keysGenerated = 0
    totalCandidates = 0
    while keysGenerated < numKeys:
        try:
            cand = Candidate()
            # Do typo check
            t = '%s?' % cand
            # Take one round of SHA256
            candHash = hashlib.sha256(t).digest()
            # Check if the first eight bits of the hash are 0
            if candHash[0] == '\x00':
                privateKey = GetPrivateKey(cand)
                print('\n%s\nSHA256( ): %s\nsha256(?): %s' %
                      (cand, privateKey, candHash.encode('hex_codec')))
                if CheckShortKey(cand):
                    print('Validated.')
                else:
                    print('Invalid!')
                keysGenerated += 1
            totalCandidates += 1
        except KeyboardInterrupt:
            break
    print('\n%s: %i\n%s: %i\n%s: %.1f' %
          ('Keys Generated', keysGenerated,
           'Total Candidates', totalCandidates,
           'Reject Percentage',
           100*(1.0-keysGenerated/float(totalCandidates))))

def GetPrivateKey(shortKey):
    """
    Returns the hexadecimal representation of the private key corresponding
    to the given short key.
    """
    if CheckShortKey(shortKey):
        return hashlib.sha256(shortKey).hexdigest()
    else:
        print('Typo detected in private key!')
        return None

def CheckShortKey(shortKey):
    """
    Checks for typos in the short key.
    """
    if len(shortKey) != 30:
        return False
    t = '%s?' % shortKey
    tHash = hashlib.sha256(t).digest()
    # Check to see that first byte is \x00
    if tHash[0] == '\x00':
        return True
    return False