Goal
Convert a Bitcoin private key into a different alphabet.
Contents
- Goal
- Contents
- Brief Summary
- Summary
- Downloadable Assets
- How To Use The Tools
- Project Log
Brief Summary
I designed a modified English alphabet, called the Murphy alphabet. Bitcoin private keys can be converted into it for storage, so that they are less recognisable. I developed tools for performing this conversion.
Summary
I designed a modified English alphabet, called the Murphy alphabet. Hex data can be converted into and out of this alphabet.
English alphabet:
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
Murphy alphabet:
m, u, r, p, h, y, s, l, i, w, a, b, c, d, e, f, g, j, k, n, o, q, t, v, x, z
Hex alphabet:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
Advantages of the Murphy alphabet:
- Keeps characters a-f in the same positions as they are in the hex alphabet. This makes comparing hex data and Murphy data much easier.
- Memorable structure: The first 10 characters are "Murphy's Law", with 'a' changed to 'i' (which is appropriate acknowledgement of the law itself).
- Uses relatively common English characters, so that a future book cipher does not need to rely on finding rare characters (e.g. j, k).
- Bitcoin private keys can be converted into the Murphy alphabet so that they are less recognisable when written in a notebook.
Example Bitcoin private key in storage format:
9
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
The same key converted into the Murphy alphabet:
w
abpu
wsed mmrw cbyl ubym
lwlr bshu umuc mads
lbme hmub imma wbsf
prry cwlf csbi uuym
hrcf ssws icrf brey
abpu
wsed mmrw cbyl ubym
lwlr bshu umuc mads
lbme hmub imma wbsf
prry cwlf csbi uuym
hrcf ssws icrf brey
The same approach could be used with a different alphabet. For example, a Bitcoin private key could be converted into a modified Russian, Greek, Japanese, or Sanskrit alphabet. Be sure to first check relative character frequencies in the available text corpora for those languages, so that future book ciphers are easier to develop.
I developed tools for converting hex data (e.g. a Bitcoin private key) into Murphy data. Each has a useful command-line interface and an accompanying test suite.
Please see the Downloadable Assets section for the tool and the test suite, and the How To Use The Tools section for instructions and examples.
Downloadable Assets
Assets of this article:
List:
- hex_to_murphy.py
- test_hex_to_murphy.py
- murphy_to_hex.py
- test_murphy_to_hex.py
- test_hex_to_murphy.py
- murphy_to_hex.py
- test_murphy_to_hex.py
Asset: A tool that converts hex data into Murphy data. Python 2.7.12.
hex_to_murphy.py
Asset: A test suite for the hex-to-Murphy conversion tool. Python 2.7.12, Pytest 4.6.11.
test_hex_to_murphy.py
Asset: A tool that converts Murphy data into hex data. Python 2.7.12.
murphy_to_hex.py
Asset: A test suite for the Murphy-to-hex conversion tool. Python 2.7.12, Pytest 4.6.11.
test_murphy_to_hex.py
How To Use The Tools
Help:
python hex_to_murphy.py --help
python murphy_to_hex.py --help
python murphy_to_hex.py --help
Main:
python hex_to_murphy.py -f storageKey.txt
python murphy_to_hex.py -f murphyKey.txt
python murphy_to_hex.py -f murphyKey.txt
Test:
pytest -q test_hex_to_murphy.py
pytest -q test_murphy_to_hex.py
pytest -q test_murphy_to_hex.py
Note: The test suite file needs to be in the same directory as the tool file.
Examples:
stjohn@judgement:work$ cat storageKey.txt
9
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
stjohn@judgement:work$ python hex_to_murphy.py -f storageKey.txt
w
abpu
wsed mmrw cbyl ubym
lwlr bshu umuc mads
lbme hmub imma wbsf
prry cwlf csbi uuym
hrcf ssws icrf brey
stjohn@judgement:work$ python hex_to_murphy.py -f storageKey.txt > murphyKey.txt
stjohn@judgement:work$ python murphy_to_hex.py -f murphyKey.txt
9
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
stjohn@judgement:work$ python murphy_to_hex.py -f murphyKey.txt > storageKey2.txt
stjohn@judgement:work$ diff storageKey.txt storageKey2.txt
stjohn@judgement:work$ pytest -q test_hex_to_murphy.py
....................... [100%]
23 passed in 0.07 seconds
Project Log
Example Bitcoin private key (64 characters, 32 bytes):
7972b641101c0ad67b0e401b800a9b6f3225c97fc6b8115042cf66968c2fb2e5
The corresponding Bitcoin address is:
16ASCUS3s7D4UQh6J9oHGuT19agPvD3PFj
Private key in grid format:
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
Private key in storage format (grid format with added checksum tree):
9
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
Click here for an explanation of the checksum tree.
A problem with the storage key format:
- It's fairly recognisable. If another person sees this formatted pattern of numbers, they might correctly guess that it's a Bitcoin private key.
A partial solution is to convert the characters of the key into a different alphabet. The key will hopefully be less immediately recognisable as a key. Text doesn't jump out to the eye as much as numbers do.
An alphabet is a standardized sequence of characters.
The hex alphabet is:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
I have tried out several approaches.
Approach 1: Convert hex to English alphabet.
So:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
becomes
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p
Problem:
- It's confusing for characters a-f to appear in both alphabets at different positions. Comparing the data from before and after the conversion is difficult.
Approach 2: Convert hex to re-ordered English alphabet.
We keep characters a-f in their original positions, and change other hex characters (the numbers 0-9) to the English characters that come after a-f.
So:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
becomes
g, h, i, j, k, l, m, n, o, p, a, b, c, d, e, f
Problem:
- j and k are relatively rare in English text. In a future project, I would like to use a book cipher to encipher the converted key. This will be easier if all the characters in the converted key are relatively common.
From previous work by Peter Norvig, I know that the character frequencies in English text are:
E: 12.49%
T: 9.28%
A: 8.04%
O: 7.64%
I: 7.57%
N: 7.23%
S: 6.51%
R: 6.28%
H: 5.05%
L: 4.07%
D: 3.82%
C: 3.34%
U: 2.73%
M: 2.51%
F: 2.40%
P: 2.14%
G: 1.87%
W: 1.68%
Y: 1.66%
B: 1.48%
V: 1.05%
K: 0.54%
X: 0.23%
J: 0.16%
Q: 0.12%
Z: 0.09%
For a book cipher, I think that a frequency of 1% or greater is probably acceptable. J's frequency is 0.16% and K's is 0.54%.
Approach 3: Convert hex to a second re-ordered English alphabet.
From relatively common English characters, not including a-f, I have formed this sequence:
m, u, r, p, h, y, s, l, i, w
This is "Murphy's Law", where the 'a' has been replaced with 'i' (which I think is an appropriate nod to the law itself).
This avoids the use of any characters whose frequency of occurrence is less than 1% in English text.
So:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
becomes
m, u, r, p, h, y, s, l, i, w, a, b, c, d, e, f
I've called this modified alphabet "The Murphy Alphabet".
If the remaining characters of the English alphabet were included, in their standard order, it would be:
m, u, r, p, h, y, s, l, i, w, a, b, c, d, e, f, g, j, k, n, o, q, t, v, x, z
I've written tools that convert hex data into the Murphy alphabet and back again.
Work machine:
- Name: Judgement
- Windows 10
- Windows Subsystem for Linux (WSL): Ubuntu 16.04
- I'm working in the WSL Ubuntu terminal.
My Python version:
stjohn@judgement:work$ python --version
Python 2.7.12
My Pytest version:
stjohn@judgement:work$ pytest --version
This is pytest version 4.6.11, imported from /home/stjohn/.local/lib/python2.7/site-packages/pytest.pyc
I'm working in a project directory, called:
"converting_a_Bitcoin_private_key_to_a_different_alphabet"
In it, there is a work directory named "work". The following files are in the work directory:
hex_to_murphy.py
murphy_to_hex.py
storageKey.txt
test_hex_to_murphy.py
test_murphy_to_hex.py
murphy_to_hex.py
storageKey.txt
test_hex_to_murphy.py
test_murphy_to_hex.py
storageKey.txt contains the example Bitcoin private key from earlier.
stjohn@judgement:work$ pytest -q test_hex_to_murphy.py
....................... [100%]
23 passed in 0.07 seconds
stjohn@judgement:work$ pytest -q test_murphy_to_hex.py
....................... [100%]
23 passed in 0.07 seconds
stjohn@judgement:work$ cat storageKey.txt
9
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
stjohn@judgement:work$ python hex_to_murphy.py --help
usage: hex_to_murphy.py [-h] [-f HEXDATAFILEPATH] [-s HEXDATASTRING]
[-l {debug,info,warning,error}] [-d]
Convert hex data into the Murphy alphabet.
optional arguments:
-h, --help show this help message and exit
-f HEXDATAFILEPATH, --hexDataFilePath HEXDATAFILEPATH
path to file containing hex data (default:
'hexData.txt').
-s HEXDATASTRING, --hexDataString HEXDATASTRING
hex data string passed as a direct argument. This
overrides --hexDataFilePath.
-l {debug,info,warning,error}, --logLevel {debug,info,warning,error}
Choose logging level (default: 'error').
-d, --debug Sets logLevel to 'debug'. This overrides --logLevel.
stjohn@judgement:work$ python hex_to_murphy.py --hexDataFilePath storageKey.txt
w
abpu
wsed mmrw cbyl ubym
lwlr bshu umuc mads
lbme hmub imma wbsf
prry cwlf csbi uuym
hrcf ssws icrf brey
stjohn@judgement:work$ python hex_to_murphy.py -f storageKey.txt --logLevel=info
INFO [hex_to_murphy: 78 (hexToMurphy)] Hex data contains 108 characters.
w
abpu
wsed mmrw cbyl ubym
lwlr bshu umuc mads
lbme hmub imma wbsf
prry cwlf csbi uuym
hrcf ssws icrf brey
stjohn@judgement:work$ python hex_to_murphy.py -f storageKey.txt > murphyKey.txt
stjohn@judgement:work$ python murphy_to_hex.py --help
usage: murphy_to_hex.py [-h] [-f MURPHYDATAFILEPATH] [-s MURPHYDATASTRING]
[-l {debug,info,warning,error}] [-d]
Convert Murphy data into hex data.
optional arguments:
-h, --help show this help message and exit
-f MURPHYDATAFILEPATH, --murphyDataFilePath MURPHYDATAFILEPATH
path to file containing Murphy data (default:
'murphyData.txt').
-s MURPHYDATASTRING, --murphyDataString MURPHYDATASTRING
murphy data string passed as a direct argument. This
overrides --murphyDataFilePath.
-l {debug,info,warning,error}, --logLevel {debug,info,warning,error}
Choose logging level (default: 'error').
-d, --debug Sets logLevel to 'debug'. This overrides --logLevel.
stjohn@judgement:work$ python murphy_to_hex.py -f murphyKey.txt
9
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
stjohn@judgement:work$ python murphy_to_hex.py -f murphyKey.txt > storageKey2.txt
stjohn@judgement:work$ diff storageKey.txt storageKey2.txt
So: A key can be converted into and out of the Murphy alphabet.
Storage key:
9
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
ab31
96ed 0029 cb57 1b50
7972 b641 101c 0ad6
7b0e 401b 800a 9b6f
3225 c97f c6b8 1150
42cf 6696 8c2f b2e5
Murphy storage key:
w
abpu
wsed mmrw cbyl ubym
lwlr bshu umuc mads
lbme hmub imma wbsf
prry cwlf csbi uuym
hrcf ssws icrf brey
abpu
wsed mmrw cbyl ubym
lwlr bshu umuc mads
lbme hmub imma wbsf
prry cwlf csbi uuym
hrcf ssws icrf brey
The Murphy storage key, if written on a page in a notebook, would be less likely to be immediately recognised by another person as a Bitcoin private key.
The same approach could be used with a different alphabet. For example, a Bitcoin private key could be converted into a modified Russian, Greek, Japanese, or Sanskrit alphabet.
Good. That's the end of this project.