Greetings Everyone! I hope you're all doing well. As you all know there's been some controversy lately surrounding our keys and the methods of their generation.
Today I am going to show you how to generate secure 30 and 22 character BTCitcoin minikeys in two formats, base57 and base32.Here is an AI answering to the security of a base32 minikey:
I have played around with all kinds of key-gen stuff and originally found this script on the forums here years ago, it used a non-crypto-graphically secure random function.
https://bitcointalk.org/index.php?topic=1337457.0I updated this script to use the crypto-safe function random.SystemRandom() which is a standard python library, and have created
two three new versions.
One generates keys from base57 the other from base32, and the last creates 22 character base32 minikeys.
base57 = 23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
base32 = 23456789ABCDEFGHJKLMNPQRSTUVWXYZWhat is required?
- COMPETENCE! This is not a system, it requires focus and careful work.
- An air-gapped system running macos or a linux distribution.
- A copy of bitaddress.org source code
- These two python scripts
base57import random
import hashlib
BASE58 = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
def Candidate():
srandom = random.SystemRandom()
return('%s%s' % ('S', ''.join(
[BASE58[ srandom.randrange(0,len(BASE58)) ] for i in range(29)])))
def GenerateKeys(numKeys = 21):
"""
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
GenerateKeys()
base57 RESULT example:SmXsUbKQfLMaosBFKyJD38xiyveb7i
SHA256( ): 40253945df729cde57311cc82183ecb0f84410853ec6b79c5320889ce1f9f400
sha256(?): 00c17a8a028ecf9ccf471614900a0ebb52852d783af8f5cd186ebf1956fd7be2
Validated.
base32import random
import hashlib
BASE58 = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'
def Candidate():
srandom = random.SystemRandom()
return('%s%s' % ('S', ''.join(
[BASE58[ srandom.randrange(0,len(BASE58)) ] for i in range(29)])))
def GenerateKeys(numKeys = 21):
"""
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
GenerateKeys()
base32 RESULT example:SXRN5EH92YJDRREAX8VDZBPEUMXDMN
SHA256( ): 2fc9356894e881541865b8dca800f120cbfcac32627bf0aabba6dcaa7658b409
sha256(?): 0077992753bab69bdeb420cedad11b41bef0182b43ccb29cf4fdcb0399fbfcc2
Validated.
** UPDATE I have also added a 22 character base32 minikey script below **Multiple AI have confirmed even at 22 characters, a base32 minikey would be impossible to crack for the foreseeable future.
base32 - 22 Character Minikeyimport random
import hashlib
BASE58 = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'
def Candidate():
srandom = random.SystemRandom()
return('%s%s' % ('S', ''.join(
[BASE58[ srandom.randrange(0,len(BASE58)) ] for i in range(21)])))
def GenerateKeys(numKeys = 21):
"""
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) != 22:
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
GenerateKeys()
base32 - 22 Character Minikey RESULT example:SHAGB2RML58MRVTUZYJAGE
SHA256( ): bdae5d37db5a11fb7e5f5ac336df631f7dd9f15efc28d57b5704c1f84546bfb8
sha256(?): 00e66ee72d46056864da6ed5ec59579f302d6623958a5b0b3664af4ee8f6c0bb
Validated.
Save these scripts as minikey57.py, minikey32.py, and minikey22.py
To run the script "obviously air-gapped / offline" you simply open your terminal, navigate to your file location and type:
python minikey32.pyThe scripts will generate 21 minikeys on each run, you can edit
def GenerateKeys(numKeys = 21): <- and change the 21 to the amount you want to generate.
To discover the public addresses of the minikeys you paste the minikey into the
wallet details section of an
offline copy of bitaddress.org.
That's it! If you find this helpful throw some sats at my TIP Jar below which I generated with this script! Guess which version I used!
Thanks!
I will also be including these two script on the usb keys provided with the Cool Storage wallet kits preparation utility.
TIP Jar
1KZA2K4gEicijgK6umBdCooGnepRTPzsG3