2018-02-02 17:29:52 +00:00
|
|
|
#!/usr/bin/env python3
|
2016-05-20 20:27:20 +00:00
|
|
|
from __future__ import print_function
|
2016-05-26 15:20:44 +00:00
|
|
|
import binascii
|
|
|
|
import hashlib
|
|
|
|
import mnemonic
|
2016-05-20 20:27:20 +00:00
|
|
|
|
2014-02-03 10:36:56 +00:00
|
|
|
__doc__ = '''
|
2014-02-02 14:24:47 +00:00
|
|
|
Use this script to cross-check that TREZOR generated valid
|
|
|
|
mnemonic sentence for given internal (TREZOR-generated)
|
|
|
|
and external (computer-generated) entropy.
|
2014-02-02 14:29:07 +00:00
|
|
|
|
|
|
|
Keep in mind that you're entering secret information to this script.
|
2014-02-03 10:36:56 +00:00
|
|
|
Leaking of these information may lead to stealing your bitcoins
|
2014-02-02 14:29:07 +00:00
|
|
|
from your wallet! We strongly recommend to run this script only on
|
2014-02-03 10:36:56 +00:00
|
|
|
highly secured computer (ideally live linux distribution
|
|
|
|
without an internet connection).
|
2014-02-02 14:24:47 +00:00
|
|
|
'''
|
|
|
|
|
2016-05-20 11:36:17 +00:00
|
|
|
# Python2 vs Python3
|
|
|
|
try:
|
|
|
|
input = raw_input
|
|
|
|
except NameError:
|
|
|
|
pass
|
|
|
|
|
2017-06-23 19:31:42 +00:00
|
|
|
|
2014-02-02 14:24:47 +00:00
|
|
|
def generate_entropy(strength, internal_entropy, external_entropy):
|
|
|
|
'''
|
|
|
|
strength - length of produced seed. One of 128, 192, 256
|
|
|
|
random - binary stream of random data from external HRNG
|
|
|
|
'''
|
|
|
|
if strength not in (128, 192, 256):
|
2017-11-06 10:09:54 +00:00
|
|
|
raise ValueError("Invalid strength")
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
if not internal_entropy:
|
2017-11-06 10:09:54 +00:00
|
|
|
raise ValueError("Internal entropy is not provided")
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
if len(internal_entropy) < 32:
|
2017-11-06 10:09:54 +00:00
|
|
|
raise ValueError("Internal entropy too short")
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
if not external_entropy:
|
2017-11-06 10:09:54 +00:00
|
|
|
raise ValueError("External entropy is not provided")
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
if len(external_entropy) < 32:
|
2017-11-06 10:09:54 +00:00
|
|
|
raise ValueError("External entropy too short")
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
entropy = hashlib.sha256(internal_entropy + external_entropy).digest()
|
2016-05-20 20:27:20 +00:00
|
|
|
entropy_stripped = entropy[:strength // 8]
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
if len(entropy_stripped) * 8 != strength:
|
2017-11-06 10:09:54 +00:00
|
|
|
raise ValueError("Entropy length mismatch")
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
return entropy_stripped
|
|
|
|
|
2017-06-23 19:31:42 +00:00
|
|
|
|
2014-02-02 14:24:47 +00:00
|
|
|
def main():
|
2016-05-20 11:36:17 +00:00
|
|
|
print(__doc__)
|
2014-02-03 10:36:56 +00:00
|
|
|
|
2016-05-20 11:36:17 +00:00
|
|
|
comp = binascii.unhexlify(input("Please enter computer-generated entropy (in hex): ").strip())
|
|
|
|
trzr = binascii.unhexlify(input("Please enter TREZOR-generated entropy (in hex): ").strip())
|
|
|
|
word_count = int(input("How many words your mnemonic has? "))
|
2014-02-02 14:24:47 +00:00
|
|
|
|
2016-05-20 20:27:20 +00:00
|
|
|
strength = word_count * 32 // 3
|
2014-02-02 14:24:47 +00:00
|
|
|
|
|
|
|
entropy = generate_entropy(strength, trzr, comp)
|
|
|
|
|
|
|
|
words = mnemonic.Mnemonic('english').to_mnemonic(entropy)
|
|
|
|
if not mnemonic.Mnemonic('english').check(words):
|
2016-05-20 11:36:17 +00:00
|
|
|
print("Mnemonic is invalid")
|
2014-02-02 14:24:47 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
if len(words.split(' ')) != word_count:
|
2016-05-20 11:36:17 +00:00
|
|
|
print("Mnemonic length mismatch!")
|
2014-02-02 14:24:47 +00:00
|
|
|
return
|
|
|
|
|
2016-05-20 11:36:17 +00:00
|
|
|
print("Generated mnemonic is:", words)
|
2014-02-02 14:24:47 +00:00
|
|
|
|
2017-06-23 19:31:42 +00:00
|
|
|
|
2014-02-02 14:24:47 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|