def test_utf8_nfkd(self): # The same sentence in various UTF-8 forms words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" words_nfkc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" words_nfd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" passphrase_nfkd = ( u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko" ) passphrase_nfc = ( u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko" ) passphrase_nfkc = ( u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko" ) passphrase_nfd = ( u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko" ) seed_nfkd = Mnemonic.to_seed(words_nfkd, passphrase_nfkd) seed_nfc = Mnemonic.to_seed(words_nfc, passphrase_nfc) seed_nfkc = Mnemonic.to_seed(words_nfkc, passphrase_nfkc) seed_nfd = Mnemonic.to_seed(words_nfd, passphrase_nfd) self.assertEqual(seed_nfkd, seed_nfc) self.assertEqual(seed_nfkd, seed_nfkc) self.assertEqual(seed_nfkd, seed_nfd)
def from_seed(seed, passphrase): t = seed_type(seed) if t == 'old': keystore = Old_KeyStore({}) keystore.add_seed(seed) elif t in ['standard', 'segwit']: keystore = BIP32_KeyStore({}) keystore.add_seed(seed) keystore.passphrase = passphrase bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase) xtype = 0 if t == 'standard' else 1 keystore.add_xprv_from_seed(bip32_seed, xtype, "m/") return keystore
def load_device_by_mnemonic(self, mnemonic, pin, passphrase_protection, label, language, skip_checksum=False): m = Mnemonic("english") if not skip_checksum and not m.check(mnemonic): raise Exception("Invalid mnemonic checksum") # Convert mnemonic to UTF8 NKFD mnemonic = Mnemonic.normalize_string(mnemonic) # Convert mnemonic to ASCII stream mnemonic = unicode(str(bytearray(mnemonic, "utf-8")), "utf-8") if self.features.initialized: raise Exception("Device is initialized already. Call wipe_device() and try again.") resp = self.call( proto.LoadDevice( mnemonic=mnemonic, pin=pin, passphrase_protection=passphrase_protection, language=language, label=label, skip_checksum=skip_checksum, ) ) self.init_device() return resp
def _check_list(self, language, vectors): mnemo = Mnemonic(language) for v in vectors: code = mnemo.to_mnemonic(unhexlify(v[0])) seed = hexlify(Mnemonic.to_seed(code, passphrase = 'TREZOR')) self.assertIs(mnemo.check(v[1]), True) self.assertEqual(v[1], code) self.assertEqual(v[2], seed)
def test_to_entropy(self): data = [ bytearray((random.getrandbits(8) for _ in range(32))) for _ in range(1024) ] data.append(b"Lorem ipsum dolor sit amet amet.") m = Mnemonic("english") for d in data: self.assertEqual(m.to_entropy(m.to_mnemonic(d).split()), d)
def restore(ctx): """ Restore a wallet from a mnemonic \b If you accidently deleted your wallet file or the file became corrupted, use this command to restore your wallet. You must have your 12 word phrase (mnemonic) that was displayed when you created your wallet. """ # Stop daemon if it's running. d = None try: d = get_daemonizer() except OSError as e: pass if d: try: d.stop() except exceptions.DaemonizerError as e: click.echo("ERROR: Couldn't stop daemon: %s" % e) ctx.exit(code=4) # Check to see if the current wallet path exists if os.path.exists(ctx.obj['wallet_path']): if click.confirm("Wallet file already exists and may have a balance. Do you want to delete it?"): os.remove(ctx.obj['wallet_path']) else: click.echo("Not continuing.") ctx.exit(code=4) # Ask for mnemonic mnemonic = click.prompt("Please enter the wallet's 12 word mnemonic") # Sanity check the mnemonic m = Mnemonic(language='english') if not m.check(mnemonic): click.echo("ERROR: Invalid mnemonic.") ctx.exit(code=5) if click.confirm("Did the wallet have a passphrase?"): passphrase = get_passphrase() else: passphrase = '' # Try creating the wallet click.echo("\nRestoring...") wallet = Two1Wallet.import_from_mnemonic( data_provider=ctx.obj['data_provider'], mnemonic=mnemonic, passphrase=passphrase) wallet.to_file(ctx.obj['wallet_path']) if Two1Wallet.check_wallet_file(ctx.obj['wallet_path']): click.echo("Wallet successfully restored.") else: click.echo("Wallet not restored.") ctx.exit(code=6)
def test_to_entropy(self): data = [bytearray((random.getrandbits(8) for _ in range(32))) for _ in range(1024)] data.append( b" I'm a little teapot, short and stout. Here is my handle. " b"Here is my spout. When I get all steamed up, hear me shout. " b"Tip me over and pour me out!! ") m = Mnemonic('english') for d in data: self.assertEqual(m.to_entropy(m.to_mnemonic(d).split()), d)
def showDetails(mnemonic, passphrase="", i=1): myMnemonic = mnemonic passphrase = passphrase mnemo = Mnemonic('english') seed = hexlify(mnemo.to_seed(myMnemonic, passphrase=passphrase)) print 'Seed:\t\t\t\t', seed priv = bitcoin.bip32_master_key(unhexlify(seed)) print 'Xpriv:\t\t\t\t', priv key = bitcoin.encode_privkey(bitcoin.bip32_extract_key(priv), 'wif_compressed') print 'Key:\t\t\t\t', key pub = bitcoin.bip32_privtopub(priv) print 'Derived public key:\t', pub pubHex = bitcoin.bip32_extract_key(pub) print 'public key (hex):\t', pubHex print 'Master Key address:\t', bitcoin.pubtoaddr(pubHex) print "" print "TREZOR Keys:" account = 0 derivedPrivateKey = bitcoin.bip32_ckd(bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44+HARDENED), HARDENED), HARDENED+account) print 'Derived private key:', derivedPrivateKey privateKey = bitcoin.encode_privkey(bitcoin.bip32_extract_key(derivedPrivateKey), 'wif_compressed') print 'private key (wif):\t', privateKey derivedPublicKey = bitcoin.bip32_privtopub(derivedPrivateKey) print 'Derived public key:', derivedPublicKey publicKeyHex = bitcoin.privtopub(privateKey) print 'public key (hex):\t', publicKeyHex address = bitcoin.pubtoaddr(publicKeyHex) print 'address:\t\t\t', address print "" print "Account public keys (XPUB)" xpubs = [] for i in range(0, i): derivedPrivateKey = bitcoin.bip32_ckd(bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44+HARDENED), HARDENED), HARDENED+i) xpub = bitcoin.bip32_privtopub(derivedPrivateKey) print 'Account', i, 'xpub:', xpub xpubs.append(xpub) return xpubs
def _check_list(self, language, vectors): mnemo = Mnemonic(language) for v in vectors: code = mnemo.to_mnemonic(unhexlify(v[0])) seed = hexlify(Mnemonic.to_seed(code, passphrase="TREZOR")) xprv = Mnemonic.to_hd_master_key(unhexlify(seed)) if sys.version >= "3": seed = seed.decode("utf8") self.assertIs(mnemo.check(v[1]), True) self.assertEqual(v[1], code) self.assertEqual(v[2], seed) self.assertEqual(v[3], xprv)
def _check_list(self, language, vectors): mnemo = Mnemonic(language) for v in vectors: code = mnemo.encode(unhexlify(v[0])) data = hexlify(mnemo.decode(code)) self.assertEqual(v[1], code) self.assertEqual(v[0], data) print "input: ", v[0], "(%d bits)" % len(v[0] * 4) print "mnemonic:", code, "(%d words)" % len(code.split(' ')) print
def restore_wallet(PIN): if len(PIN) == 0: PIN = choose_PIN_code() retry = True while retry: userWords = [] print_screen_title("RESTORE AN EXISTING WALLET (step 2/3)") print "Please type in your 24 words backup phrase." print "Warning: BIP39 is " + term.bold("case-sensitive!") + "\n" for i in range(1, 25): validWord = False while not validWord: typedWord = raw_input("Word #" + str(i) + "? ") typedWord = typedWord.lower() if len(typedWord) > 0: if typedWord in english_wordlist: userWords.append(typedWord) validWord = True else: print "This word is not in the official BIP39 english wordlist." else: print "Type a word a please." bip39Seed = " ".join(userWords) mnemo = Mnemonic("english") if mnemo.check(bip39Seed) == False: print "" print "An " + term.bold("error occurred") + "." print "Your BIP39 seed is invalid !\n" question = "Try again to type the seed?" retry = yes_or_no_question(question) else: retry = False print "\nWe're almost done!" print "Here is your BIP39 seed:\n" print_wordlist(bip39Seed) print "\nPlease check that it is correct." question = "Continue and restore your wallet from this seed?" choice = yes_or_no_question(question) if choice == True: start_flashing(PIN, bip39Seed) else: restore_wallet(PIN)
def __init__(self): conf = read_config_file("ew.conf") if conf['entropy']: entropy = binascii.unhexlify(conf['entropy']) else: mnemo = Mnemonic('english') entropy = mnemo.to_entropy(conf['passphrase']) print("entropy=" + entropy.hex()) master = BIP32Node.from_master_secret(entropy, 'BTC') print("master address=" + master.address()) # /m/4544288'/0'/0'/0/0 alias alias = master.subkey(i=EW_DERIVATION, is_hardened=True).subkey(i=0, is_hardened=True).subkey(i=0, is_hardened=True).subkey(i=0, is_hardened=False).subkey(i=0, is_hardened=False) self.address = alias.address() print("alias address=" + self.address) self.key = CBitcoinSecret(alias.wif())
def test_similarity(self): similar = ( ('a', 'c'), ('a', 'e'), ('a', 'o'), ('b', 'd'), ('b', 'h'), ('b', 'p'), ('b', 'q'), ('b', 'r'), ('c', 'e'), ('c', 'g'), ('c', 'n'), ('c', 'o'), ('c', 'q'), ('c', 'u'), ('d', 'g'), ('d', 'h'), ('d', 'o'), ('d', 'p'), ('d', 'q'), ('e', 'f'), ('e', 'o'), ('f', 'i'), ('f', 'j'), ('f', 'l'), ('f', 'p'), ('f', 't'), ('g', 'j'), ('g', 'o'), ('g', 'p'), ('g', 'q'), ('g', 'y'), ('h', 'k'), ('h', 'l'), ('h', 'm'), ('h', 'n'), ('h', 'r'), ('i', 'j'), ('i', 'l'), ('i', 't'), ('i', 'y'), ('j', 'l'), ('j', 'p'), ('j', 'q'), ('j', 'y'), ('k', 'x'), ('l', 't'), ('m', 'n'), ('m', 'w'), ('n', 'u'), ('n', 'z'), ('o', 'p'), ('o', 'q'), ('o', 'u'), ('o', 'v'), ('p', 'q'), ('p', 'r'), ('q', 'y'), ('s', 'z'), ('u', 'v'), ('u', 'w'), ('u', 'y'), ('v', 'w'), ('v', 'y') ) languages = Mnemonic.list_languages() fail = False for lang in languages: mnemo = Mnemonic(lang) for w1 in mnemo.wordlist: for w2 in mnemo.wordlist: if len(w1) != len(w2): continue if w1 == w2: continue if w1 > w2: # No need to print warning twice continue diff = [] for i in range(len(w1)): if w1[i] != w2[i]: if w1[i] < w2[i]: pair = (w1[i], w2[i]) else: pair = (w2[i], w1[i]) diff.append(pair) # pairs.update((pair,)) if len(diff) == 1: if list(diff)[0] in similar: fail = True print("Similar words (%s): %s, %s" % (lang, w1, w2)) if fail: self.assert_(False, "Similar words found")
def processNext(self): self.persoData['seed'] = None if self.ui.RestoreWalletButton.isChecked(): # Check if it's an hexa string seedText = str(self.ui.seed.text()) if len(seedText) == 0: QMessageBox.warning(self, "Error", "Please enter a seed", "OK") return if seedText[-1] == 'X': seedText = seedText[0:-1] try: self.persoData['seed'] = seedText.decode('hex') except: pass if self.persoData['seed'] == None: if not MNEMONIC: QMessageBox.warning(self, "Error", "Mnemonic API not available. Please install https://github.com/trezor/python-mnemonic", "OK") return if not self.mnemonic.check(seedText): QMessageBox.warning(self, "Error", "Invalid mnemonic", "OK") return self.persoData['seed'] = Mnemonic.to_seed(seedText) else: if (len(self.persoData['seed']) < 32) or (len(self.persoData['seed']) > 64): QMessageBox.warning(self, "Error", "Invalid seed length", "OK") return dialog = SecurityDialog(self.persoData, self) self.hide() dialog.exec_()
def testvectors(): """ This function exercises the libraries and double checks that they are returning expected data. """ print "Self Checking", print_dot() if "51477815b762e495e0f7deb01fb2969f2e15ba4615fa4a5aafc23ccf5c3c8bd2".decode('hex') != \ privkey_to_pubkey("12fab77add10bcabe1b62b3fe8b167e966e4beee38ccf0062fdd207b5906c841".decode('hex'), False): return False print_dot() doublecheck_key_works("12fab77add10bcabe1b62b3fe8b167e966e4beee38ccf0062fdd207b5906c841".decode('hex'), \ "51477815b762e495e0f7deb01fb2969f2e15ba4615fa4a5aafc23ccf5c3c8bd2".decode('hex'), False) print_dot() if "51477815-b762e495-e0f7deb0-1fb2969f-2e15ba46-15fa4a5a-afc23ccf-5c3c8bd2-6c4cf980" != \ pubkey_to_send("51477815b762e495e0f7deb01fb2969f2e15ba4615fa4a5aafc23ccf5c3c8bd2".decode('hex'), False): return False print_dot() if "Fs1Ts7PsKMwo4ftCYxQJ3rW4pLiRBXyGEjMrxtHycLu52aDgKGEy" != \ private_key_to_human("12fab77add10bcabe1b62b3fe8b167e966e4beee38ccf0062fdd207b5906c841".decode('hex'), False): return False print_dot() if not onlyB58chars("Xw1"): return False if onlyB58chars("$"): return False print_dot() if "4f4488c609552caf2c7a508108809518e9a1ab3ae6dc259a1e2e9989d053018d".decode('hex') != \ hashlib.sha256(hashlib.sha256("647812fab77add10bcabe1b62b3fe8b167e966e4beee38ccf0062fdd207b5906c841" \ .decode('hex')).digest()).digest(): return False print_dot() if True != verify_koinify_words("legal winner thank year wave sausage worth useful legal winner thank yellow"): return False print_dot() if True == verify_koinify_words("legal winner thank year wave sausage worth useful legal winner thank thank"): return False print_dot() if "878386efb78845b3355bd15ea4d39ef97d179cb712b77d5c12b6be415fffeffe5f377ba02bf3f8544ab800b955e51fbff09828f682052a20faa6addbbddfb096" \ .decode('hex') != Mnemonic.to_seed("legal winner thank year wave sausage worth useful legal winner thank yellow", ''): return False print_dot() if "0488ade4000000000000000000598b4595ea72802756519e65a797234231d7d4f13d650cb06db15957c2368b1b007e56ecf5943d79e1f5f87e11c768253d7f3fcf30ae71335611e366c578b4564e"\ .decode('hex') != BIP32Key.fromEntropy("878386efb78845b3355bd15ea4d39ef97d179cb712b77d5c12b6be415fffeffe5f377ba02bf3f8544ab800b955e51fbff09828f682052a20faa6addbbddfb096"\ .decode('hex'), public=False).ExtendedKey(private=True, encoded=False): return False print_dot() if "7999d61b8f5efc24b437244ff82b69ba474deeadbf144421f05d5b4b5ab20a8e".decode('hex') != \ koinify_words_to_private_key("legal winner thank year wave sausage worth useful legal winner thank yellow", False): return False print("\n") # everything checks out ok return True
def process(data, lst): code = mnemo.to_mnemonic(unhexlify(data)) seed = b2h(Mnemonic.to_seed(code, passphrase = 'TREZOR')) print('input : %s (%d bits)' % (data, len(data) * 4)) print('mnemonic : %s (%d words)' % (code, len(code.split(' ')))) print('seed : %s (%d bits)' % (seed, len(seed) * 4)) print() lst.append((data, code, seed))
def test_lengths(self): # check if wordlists contain words between 3 and 8 characters languages = Mnemonic.list_languages() for lang in languages: mnemo = Mnemonic(lang) words = [w for w in mnemo.wordlist if len(w) < 3 or len(w) > 8] print("Language '{}'".format(lang)) self.assertListEqual(words, [])
def verify_koinify_words(words): """ This function checks to make sure there are multiple words and that the first word is in the english wordlist. Both of these errors would crash the Mnemonic library, so they should be checked before using it. The Mnemonic library checks for other errors. """ if ' ' in words: wordchecker = Mnemonic('english') firstword = words.split(' ')[0] if firstword in wordchecker.wordlist: check = wordchecker.check(words) return check else: return False else: return False
def test_validchars(self): # check if wordlists contain valid characters languages = Mnemonic.list_languages() for lang in languages: mnemo = Mnemonic(lang) letters = set(sum([list(w) for w in mnemo.wordlist] ,[])) print("Language '{}'".format(lang)) for l in letters: self.assertIn(l, 'abcdefghijklmnopqrstuvwxyz')
def process(ctr, p_hex): print '(%i)' % ctr print 'input : %s (%d bits)' % (p_hex, len(p_hex) * 4) p_mnemonic = mnemo.to_mnemonic(unhexlify(p_hex)) print 'mnemonic : %s (%d words)' % (p_mnemonic, len(p_mnemonic.split(' '))) p_seed = hexlify(Mnemonic.to_seed(p_mnemonic, passphrase = '')) print 'seed : %s (%d bits)' % (p_seed, len(p_seed) * 4)
def process(data, lst, mnemo): code = mnemo.to_mnemonic(unhexlify(data)) _seed = Mnemonic.to_seed(code, passphrase='TREZOR') xprv = BIP32Key.fromEntropy(_seed).ExtendedKey() _seed = b2h(_seed) print('input : %s (%d bits)' % (data, len(data) * 4)) print('mnemonic : %s (%d words)' % (code, len(code.split(' ')))) print('seed : %s (%d bits)' % (_seed, len(_seed) * 4)) print('xprv : %s\n' % xprv) lst.append((data, code, _seed, xprv))
def __init__(self, language): self.mnemo = Mnemonic(language) # see https://primes.utm.edu/lists/2small/ for biggest primes that fit into X bits self.primes = { 15: (2**120 - 119), 19: (2**152 - 17), 23: (2**184 - 33), 27: (2**216 - 377), 31: (2**248 - 237) }
def getXPRIVKeys(mnemonic, passphrase="", i=1): myMnemonic = mnemonic passphrase = passphrase mnemo = Mnemonic('english') seed = hexlify(mnemo.to_seed(myMnemonic, passphrase=passphrase)) priv = bitcoin.bip32_master_key(unhexlify(seed)) account = 0 #derivedPrivateKey = bitcoin.bip32_ckd(bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44+HARDENED), HARDENED), HARDENED+account) xprivs = [] for i in range(0, i): derivedPrivateKey = bitcoin.bip32_ckd(bitcoin.bip32_ckd(bitcoin.bip32_ckd(priv, 44+HARDENED), HARDENED), HARDENED+i) xprivs.append(derivedPrivateKey) return xprivs
def from_seed(seed, passphrase): if is_old_seed(seed): keystore = Old_KeyStore({}) keystore.add_seed(seed) elif is_new_seed(seed): keystore = BIP32_KeyStore({}) keystore.add_seed(seed) keystore.passphrase = passphrase bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase) keystore.add_xprv_from_seed(bip32_seed, "m/") return keystore
def process(data, lst): code = mnemo.to_mnemonic(unhexlify(data)) seed = Mnemonic.to_seed(code, passphrase="TREZOR") xprv = BIP32Key.fromEntropy(seed).ExtendedKey() seed = b2h(seed) print("input : %s (%d bits)" % (data, len(data) * 4)) print("mnemonic : %s (%d words)" % (code, len(code.split(" ")))) print("seed : %s (%d bits)" % (seed, len(seed) * 4)) print("xprv : %s" % xprv) print() lst.append((data, code, seed, xprv))
def load_device_by_mnemonic( client, mnemonic, pin, passphrase_protection, label, language="english", skip_checksum=False, expand=False, ): # Convert mnemonic to UTF8 NKFD mnemonic = Mnemonic.normalize_string(mnemonic) # Convert mnemonic to ASCII stream mnemonic = mnemonic.encode() m = Mnemonic("english") if expand: mnemonic = m.expand(mnemonic) if not skip_checksum and not m.check(mnemonic): raise ValueError("Invalid mnemonic checksum") if client.features.initialized: raise RuntimeError( "Device is initialized already. Call device.wipe() and try again." ) resp = client.call( proto.LoadDevice( mnemonic=mnemonic, pin=pin, passphrase_protection=passphrase_protection, language=language, label=label, skip_checksum=skip_checksum, ) ) client.init_device() return resp
def test_collision(self): # Check for the same words across wordlists. # This is prohibited because of auto-detection feature of language. words = [] languages = Mnemonic.list_languages() for lang in languages: mnemo = Mnemonic(lang) words += mnemo.wordlist words_unique = list(set(words[:])) self.assertEqual(len(words), len(words_unique))
def __init__(self, persoData, parent = None): QDialog.__init__(self, parent) self.persoData = persoData self.ui = ui.personalization01seed.Ui_Dialog() self.ui.setupUi(self) self.ui.seed.setEnabled(False) self.ui.RestoreWalletButton.toggled.connect(self.restoreWalletToggled) self.ui.NextButton.clicked.connect(self.processNext) self.ui.CancelButton.clicked.connect(self.processCancel) if MNEMONIC: self.mnemonic = Mnemonic('english') self.ui.mnemonicNotAvailableLabel.hide()
def test_expand_word(self): m = Mnemonic("english") self.assertEqual("", m.expand_word("")) self.assertEqual(" ", m.expand_word(" ")) self.assertEqual("access", m.expand_word("access")) # word in list self.assertEqual( "access", m.expand_word("acce") ) # unique prefix expanded to word in list self.assertEqual("acb", m.expand_word("acb")) # not found at all self.assertEqual("acc", m.expand_word("acc")) # multi-prefix match self.assertEqual("act", m.expand_word("act")) # exact three letter match self.assertEqual( "action", m.expand_word("acti") ) # unique prefix expanded to word in list
def __init__(self, wordfile = 'wordlist.txt'): # Read create the mnemonic wordlist object self.mnemonic = Mnemonic("english") # Set up a default reference wallet self.wallet = Wallet.from_master_secret(bytes(0)) # Set up a Polly communication pipe self.polly = PollyCom() # Default print padding self.PAD = "{:35}"
def xkeys_from_seed(seed, passphrase, derivation): from mnemonic import Mnemonic xprv, xpub = bip32_root(Mnemonic.mnemonic_to_seed(seed, passphrase), 0) xprv, xpub = bip32_private_derivation(xprv, "m/", derivation) return xprv, xpub
def make_seed(self, nbits=128, entropy=1, language=None): """Create a seed""" from mnemonic import Mnemonic s = Mnemonic(language).make_seed(nbits, custom_entropy=entropy) return s.encode('utf8')
def use_passphrase(self, passphrase: str) -> None: """Respond to passphrase prompts from device with the provided passphrase.""" self.ui.passphrase = Mnemonic.normalize_string(passphrase)
def check_seed(self, seed, entropy=1, language=None): """Check that a seed was generated with given entropy""" from mnemonic import Mnemonic return Mnemonic(language).check_seed(seed, entropy)
def test_failed_checksum(self): code = ( "bless cloud wheel regular tiny venue bird web grief security dignity zoo" ) mnemo = Mnemonic("english") self.assertFalse(mnemo.check(code))
def generate_words(language: str = 'english', count: int = 24) -> str: from mnemonic import Mnemonic mnemonic = Mnemonic(language) return mnemonic.generate(strength=int(count * 10.67))
def test_reset_device(self): words = [] strength = 128 def input_flow(): # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # safety warning btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice # 12 words, 3 pages for i in range(3): time.sleep(1) words.extend(self.client.debug.state().reset_word.split()) if i < 2: self.client.debug.swipe_down() else: # last page is confirmation self.client.debug.press_yes() # check backup words for _ in range(2): time.sleep(1) index = self.client.debug.state().reset_word_pos self.client.debug.input(words[index]) # confirm recovery seed check btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # confirm success btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), self.client: self.client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.Success(), proto.Features(), ]) self.client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( self.client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", ) # generate mnemonic locally internal_entropy = self.client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert " ".join(words) == expected_mnemonic # Check if device is properly initialized resp = self.client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False
def test_detection(self): self.assertEqual('english', Mnemonic.detect_language('security')) with self.assertRaises(Exception): Mnemonic.detect_language('xxxxxxx')
def test_expand(self): m = Mnemonic('english') self.assertEqual('access', m.expand('access')) self.assertEqual('access access acb acc act action', m.expand('access acce acb acc act acti'))
def get_bip39_seed_from_mnemonic(mnemonic: str, passphrase='') -> bytes: seed = Mnemonic.to_seed(mnemonic=mnemonic, passphrase=passphrase) return seed
def check_seed(self, seed, custom_entropy, language): from mnemonic import Mnemonic return Mnemonic(language).check_seed(seed, custom_entropy)
def make_seed(self, nbits, custom_entropy, language): from mnemonic import Mnemonic s = Mnemonic(language).make_seed(nbits, custom_entropy=custom_entropy) return s.encode('utf8')
def check_seedphrase(seedphrase, language='english'): return Mnemonic(language).check(seedphrase)
def test_reset_device_pin(self, client): external_entropy = b"zlutoucky kun upel divoke ody" * 2 strength = 128 ret = client.call_raw( proto.ResetDevice( display_random=True, strength=strength, passphrase_protection=True, pin_protection=True, language="english", label="test", )) # Do you want ... ? assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) # Entropy screen #1 assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) # Entropy screen #2 assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) assert isinstance(ret, proto.PinMatrixRequest) # Enter PIN for first time pin_encoded = client.debug.encode_pin("654") ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) assert isinstance(ret, proto.PinMatrixRequest) # Enter PIN for second time pin_encoded = client.debug.encode_pin("654") ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) # Provide entropy assert isinstance(ret, proto.EntropyRequest) internal_entropy = client.debug.read_reset_entropy() ret = client.call_raw(proto.EntropyAck(entropy=external_entropy)) # Generate mnemonic locally entropy = generate_entropy(strength, internal_entropy, external_entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) mnemonic = [] for _ in range(strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) mnemonic.append(client.debug.read_reset_word()) client.debug.press_yes() client.call_raw(proto.ButtonAck()) mnemonic = " ".join(mnemonic) # Compare that device generated proper mnemonic for given entropies assert mnemonic == expected_mnemonic mnemonic = [] for _ in range(strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) mnemonic.append(client.debug.read_reset_word()) client.debug.press_yes() resp = client.call_raw(proto.ButtonAck()) assert isinstance(resp, proto.Success) mnemonic = " ".join(mnemonic) # Compare that second pass printed out the same mnemonic once again assert mnemonic == expected_mnemonic # Check if device is properly initialized resp = client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is True assert resp.passphrase_protection is True # Do passphrase-protected action, PassphraseRequest should be raised resp = client.call_raw(proto.Ping(passphrase_protection=True)) assert isinstance(resp, proto.PassphraseRequest) client.call_raw(proto.Cancel())
def process(data, lst): code = mnemo.to_mnemonic(unhexlify(data)) seed = hexlify(Mnemonic.to_seed(code, passphrase='TREZOR')) print 'input : %s (%d bits)' % (data, len(data) * 4) print 'mnemonic : %s (%d words)' % (code, len(code.split(' '))) print 'seed : %s (%d bits)' % (seed, len(seed) * 4) print lst.append((data, code, seed)) if __name__ == '__main__': out = {} for lang in Mnemonic.list_languages(): mnemo = Mnemonic(lang) out[lang] = [] # Generate corner cases data = [] for l in range(16, 32 + 1, 8): for b in ['00', '7f', '80', 'ff']: process(b * l, out[lang]) # Generate random seeds for i in range(12): data = hexlify(''.join( chr(choice(range(0, 256))) for _ in range(8 * (i % 3 + 2)))) process(data, out[lang])
def test_reset_device(self): # No PIN, no passphrase external_entropy = b"zlutoucky kun upel divoke ody" * 2 strength = 128 ret = self.client.call_raw( proto.ResetDevice( display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, language="english", label="test", ) ) assert isinstance(ret, proto.ButtonRequest) self.client.debug.press_yes() ret = self.client.call_raw(proto.ButtonAck()) # Provide entropy assert isinstance(ret, proto.EntropyRequest) internal_entropy = self.client.debug.read_reset_entropy() ret = self.client.call_raw(proto.EntropyAck(entropy=external_entropy)) # Generate mnemonic locally entropy = generate_entropy(strength, internal_entropy, external_entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) mnemonic = [] for _ in range(strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) mnemonic.append(self.client.debug.read_reset_word()) self.client.debug.press_yes() self.client.call_raw(proto.ButtonAck()) mnemonic = " ".join(mnemonic) # Compare that device generated proper mnemonic for given entropies assert mnemonic == expected_mnemonic mnemonic = [] for _ in range(strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) mnemonic.append(self.client.debug.read_reset_word()) self.client.debug.press_yes() resp = self.client.call_raw(proto.ButtonAck()) assert isinstance(resp, proto.Success) mnemonic = " ".join(mnemonic) # Compare that second pass printed out the same mnemonic once again assert mnemonic == expected_mnemonic # Check if device is properly initialized resp = self.client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False # Do passphrase-protected action, PassphraseRequest should NOT be raised resp = self.client.call_raw(proto.Ping(passphrase_protection=True)) assert isinstance(resp, proto.Success) # Do PIN-protected action, PinRequest should NOT be raised resp = self.client.call_raw(proto.Ping(pin_protection=True)) assert isinstance(resp, proto.Success)
def new_device_manual(): err = None device_type = "" device_name = "" xpubs = "" strength = 128 mnemonic = generate_mnemonic(strength=strength) if request.method == "POST": action = request.form["action"] device_type = request.form["device_type"] device_name = request.form["device_name"] if action == "newcolddevice": if not device_name: err = "Device name must not be empty" elif device_name in app.specter.device_manager.devices_names: err = "Device with this name already exists" xpubs = request.form["xpubs"] if not xpubs: err = "xpubs name must not be empty" keys, failed = Key.parse_xpubs(xpubs) if len(failed) > 0: err = "Failed to parse these xpubs:\n" + "\n".join(failed) if err is None: device = app.specter.device_manager.add_device( name=device_name, device_type=device_type, keys=keys ) return redirect( url_for("devices_endpoint.device", device_alias=device.alias) ) elif action == "newhotdevice": if not device_name: err = "Device name must not be empty" elif device_name in app.specter.device_manager.devices_names: err = "Device with this name already exists" if len(request.form["mnemonic"].split(" ")) not in [12, 15, 18, 21, 24]: err = "Invalid mnemonic entered: Must contain either: 12, 15, 18, 21, or 24 words." mnemo = Mnemonic("english") if not mnemo.check(request.form["mnemonic"]): err = "Invalid mnemonic entered." range_start = int(request.form["range_start"]) range_end = int(request.form["range_end"]) if range_start > range_end: err = "Invalid address range selected." if err is None: mnemonic = request.form["mnemonic"] paths = [ l.strip() for l in request.form["derivation_paths"].split("\n") if len(l) > 0 ] passphrase = request.form["passphrase"] file_password = request.form["file_password"] device = app.specter.device_manager.add_device( name=device_name, device_type=device_type, keys=[] ) try: device.setup_device(file_password, app.specter.wallet_manager) device.add_hot_wallet_keys( mnemonic, passphrase, paths, file_password, app.specter.wallet_manager, is_testnet(app.specter.chain), keys_range=[range_start, range_end], ) return redirect( url_for("devices_endpoint.device", device_alias=device.alias) ) except Exception as e: handle_exception(e) flash(f"Failed to setup hot wallet. Error: {e}", "error") app.specter.device_manager.remove_device( device, app.specter.wallet_manager, bitcoin_datadir=app.specter.bitcoin_datadir, chain=app.specter.chain, ) elif action == "generatemnemonic": strength = int(request.form["strength"]) mnemonic = generate_mnemonic(strength=strength) return render_template( "device/new_device_manual.jinja", device_type=device_type, device_name=device_name, xpubs=xpubs, mnemonic=mnemonic, strength=strength, error=err, specter=app.specter, rand=rand, )
def __init__(self, transport, ask_for_pin_fun, ask_for_pass_fun, passphrase_encoding): keepkey_TextUIMixin.__init__(self, transport) self.ask_for_pin_fun = ask_for_pin_fun self.ask_for_pass_fun = ask_for_pass_fun self.passphrase_encoding = passphrase_encoding self.__mnemonic = Mnemonic('english')
class HDWallet(BaseWallet): """ Hierarchical Deterministic Wallet based in BIP32 (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) """ def __init__(self, *, words: Optional[Any] = None, language: str = 'english', passphrase: bytes = b'', gap_limit: int = 20, word_count: int = 24, directory: str = './', pubsub: Optional[Any] = None, reactor: Optional[Any] = None, initial_key_generation: Optional[Any] = None) -> None: """ :param words: words to generate the seed. It's a string with the words separated by a single space. If None we generate new words when starting the wallet :type words: string :param language: language of the words :type language: string :param passphrase: one more security level to generate the seed :type passphrase: bytes :param gap_limit: maximum of unused addresses in sequence (default value based in https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#address-gap-limit) :type gap_limit: int :param word_count: quantity of words that are gonna generate the seed Possible choices are [12, 15, 18, 21, 24] :type word_count: int :param initial_key_generation: number of keys that will be generated in the initialization If not set we make it equal to gap_limit :type initial_key_generation: int :raises ValueError: Raised on invalid word_count """ super().__init__(directory=directory, pubsub=pubsub, reactor=reactor) # Dict[string(base58), BIP32Key] self.keys: Dict[str, Any] = {} # Last index that the address was shared # We use this index to know which address should be shared with the user # This index together with last_generated_index show us if the gap limit was achieved self.last_shared_index = 0 # Last index that the address was generated self.last_generated_index = 0 # Maximum gap between indexes of last generated address and last used address self.gap_limit = gap_limit # XXX Should we save this data in the object? self.language = language self.words = words self.passphrase = passphrase self.mnemonic = None # Used in admin frontend to know which wallet is being used self.type = self.WalletType.HD # Validating word count if word_count not in WORD_COUNT_CHOICES: raise ValueError( 'Word count ({}) is not one of the options {}.'.format( word_count, WORD_COUNT_CHOICES)) self.word_count = word_count # Number of keys that will be generated in the initialization self.initial_key_generation = initial_key_generation or gap_limit def _manually_initialize(self): """ Create words (if is None) and start seed and master node Then we generate the first addresses, so we can check if we already have transactions """ self.mnemonic = Mnemonic(self.language) if not self.words: # Initialized but still locked return # Validate words first self.validate_words() assert isinstance(self.passphrase, bytes), 'Passphrase must be in bytes' # Master seed seed = self.mnemonic.to_seed(self.words, self.passphrase.decode('utf-8')) # Master node from pycoin.networks.registry import network_for_netcode _register_pycoin_networks() network = network_for_netcode('htr') key = network.keys.bip32_seed(seed) # Until account key should be hardened # Chain path = 44'/0'/0'/0 # 44' (hardened) -> BIP44 # 280' (hardened) -> Coin type (280 = hathor) # 0' (hardened) -> Account # 0 -> Chain self.chain_key = key.subkey_for_path('44H/280H/0H/0') for key in self.chain_key.children(self.initial_key_generation, 0, False): self._key_generated(key, key.child_index()) def get_private_key(self, address58: str) -> 'EllipticCurvePrivateKey': """ We get the private key bytes and generate the cryptography object :param address58: address in base58 :type address58: string :return: Private key object. :rtype: :py:class:`cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey` """ return self.keys[address58] def generate_new_key(self, index): """ Generate a new key in the tree at defined index We add this new key to self.keys and set last_generated_index :param index: index to generate the key :type index: int """ new_key = self.chain_key.subkey(index) self._key_generated(new_key, index) def _key_generated(self, key, index): """ Add generated key to self.keys and set last_generated_index :param key: generated key of hd wallet :type key: pycoin.key.Key.Key :param index: index to generate the key :type index: int """ self.keys[self.get_address(key)] = key self.last_generated_index = index def get_address(self, new_key): return new_key.address() def get_key_at_index(self, index): """ Return the key generated by the index in the parameter :param index: index to return the key :type index: int """ return self.chain_key.subkey(index) def tokens_received(self, address58: str) -> None: """ Method called when the wallet receive new tokens If the gap limit is not yet achieved we generate more keys :param address58: address that received the token in base58 :type address58: string """ received_key = self.keys[address58] # If the gap now is less than the limit, we generate the new keys until the limit # Because we might be in sync phase, so we need those keys pre generated diff = self.last_generated_index - received_key.child_index() if (self.gap_limit - diff) > 0: for _ in range(self.gap_limit - diff): self.generate_new_key(self.last_generated_index + 1) # Last shared index should be at least the index after the received one self.last_shared_index = max(self.last_shared_index, received_key.child_index() + 1) def get_unused_address(self, mark_as_used: bool = True) -> str: """ Return an address that is not used yet :param mark_as_used: if True we consider that this address is already used :type mark_as_used: bool :return: unused address in base58 :rtype: string """ if self.last_shared_index != self.last_generated_index: # Only in case we are not yet in the gap limit if mark_as_used: self.last_shared_index += 1 else: if mark_as_used: self.publish_update(HathorEvents.WALLET_GAP_LIMIT, limit=self.gap_limit) key = self.get_key_at_index(self.last_shared_index) return self.get_address(key) def is_locked(self) -> bool: """ Return if wallet is currently locked The wallet is locked if self.words is None :return: if wallet is locked :rtype: bool """ return self.words is None def lock(self): """ Lock the wallet Set all parameters to default values """ self.words = None self.keys = {} self.passphrase = b'' self.language = '' self.unspent_txs = {} self.spent_txs = [] self.balance = 0 self.last_shared_index = 0 self.last_generated_index = 0 def unlock(self, tx_storage, words=None, passphrase=b'', language='english'): """ Unlock the wallet Set all parameters to initialize the wallet and load the txs :param tx_storage: storage from where I should load the txs :type tx_storage: :py:class:`hathor.transaction.storage.transaction_storage.TransactionStorage` :param words: words to generate the seed. It's a string with the words separated by a single space. If None we generate new words when starting the wallet :type words: string :param language: language of the words :type language: string :param passphrase: one more security level to generate the seed :type passphrase: bytes :return: hd wallet words. Generated in this method or passed as parameter :rtype: string """ self.language = language if not words: # Decide to choose words automatically # Can be a different language than self.mnemonic m = Mnemonic(self.language) # We can't pass the word_count to generate method, only the strength # Multiplying by 10.67 gives the result we expect words = m.generate(strength=int(self.word_count * 10.67)) self.words = words self.passphrase = passphrase self._manually_initialize() self.load_txs(tx_storage) return words def load_txs(self, tx_storage): """ Load all saved txs to fill the wallet txs :param tx_storage: storage from where I should load the txs :type tx_storage: :py:class:`hathor.transaction.storage.transaction_storage.TransactionStorage` """ for tx in tx_storage._topological_sort(): self.on_new_tx(tx) def validate_words(self): """ Validate if set of words is valid If words is None or is not valid we raise error :raises InvalidWords: when the words are invalid """ if not self.words or not self.mnemonic.check(self.words): raise InvalidWords def get_input_aux_data(self, data_to_sign: bytes, private_key: 'Key') -> Tuple[bytes, bytes]: """ Sign the data to be used in input and get public key compressed in bytes :param data_to_sign: Data to be signed :type data_to_sign: bytes :param private_key: private key to sign data :type private_key: pycoin.key.Key.Key :return: public key compressed in bytes and signature :rtype: tuple[bytes, bytes] """ prehashed_msg = hashlib.sha256( hashlib.sha256(data_to_sign).digest()).digest() signature = private_key.sign(prehashed_msg) return private_key.sec(), signature
def test_expand(self): m = Mnemonic("english") self.assertEqual("access", m.expand("access")) self.assertEqual( "access access acb acc act action", m.expand("access acce acb acc act acti") )
def set_passphrase(self, passphrase): self.passphrase = Mnemonic.normalize_string(passphrase)
def test_detection(self): self.assertEqual("english", Mnemonic.detect_language("security")) with self.assertRaises(Exception): Mnemonic.detect_language("xxxxxxx")
def set_mnemonic(self, mnemonic): self.mnemonic = Mnemonic.normalize_string(mnemonic).split(' ')
def test_reset_device_skip_backup(self, client): ret = client.call_raw( proto.ResetDevice( display_random=False, strength=self.strength, passphrase_protection=False, pin_protection=False, language="english", label="test", skip_backup=True, )) assert isinstance(ret, proto.ButtonRequest) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) # Provide entropy assert isinstance(ret, proto.EntropyRequest) internal_entropy = client.debug.read_reset_entropy() ret = client.call_raw(proto.EntropyAck(entropy=self.external_entropy)) assert isinstance(ret, proto.Success) # Check if device is properly initialized ret = client.call_raw(proto.Initialize()) assert ret.initialized is True assert ret.needs_backup is True assert ret.unfinished_backup is False assert ret.no_backup is False # Generate mnemonic locally entropy = generate_entropy(self.strength, internal_entropy, self.external_entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # start Backup workflow ret = client.call_raw(proto.BackupDevice()) mnemonic = [] for _ in range(self.strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) mnemonic.append(client.debug.read_reset_word()) client.debug.press_yes() client.call_raw(proto.ButtonAck()) mnemonic = " ".join(mnemonic) # Compare that device generated proper mnemonic for given entropies assert mnemonic == expected_mnemonic mnemonic = [] for _ in range(self.strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) mnemonic.append(client.debug.read_reset_word()) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) assert isinstance(ret, proto.Success) mnemonic = " ".join(mnemonic) # Compare that second pass printed out the same mnemonic once again assert mnemonic == expected_mnemonic # start backup again - should fail ret = client.call_raw(proto.BackupDevice()) assert isinstance(ret, proto.Failure)
def get_cwid_from_mnemonic(words): # print("\nMnemonic:", words) entropy = Mnemonic('english').to_entropy(words) # print("Entropy:", entropy.hex()) cborEnt = cbor.dumps(bytes(entropy)) # print("Serialised:", cborEnt.hex(), "\n") seed = hashlib.blake2b(cborEnt, digest_size=32) # print("Seed:", seed.hexdigest()) cborSeed = cbor.dumps(seed.digest()) # print("Serialised:", cborSeed.hex(), "\n") passPhrase = '' # print("Spending pass:"******"Serialised:", passPhrase.hex()) seedBuf = cbor.dumps(cborSeed) hashedSeed = hashlib.blake2b(seedBuf, digest_size=32) salt = cbor.dumps(hashedSeed.digest()) # print("Salt:", salt.hex()) hashedPass = scrypt.hash(passPhrase, salt, buflen=32) # print("Pass:"******"14|8|1|" + base64.standard_b64encode(hashedPass).decode() + "|" + base64.standard_b64encode( salt).decode() encryptedPass = cbor.dumps(encryptedPass.encode('utf-8')) # print("Encrypted Pass:"******"Base64-ed:", base64.standard_b64encode(encryptedPass).decode(), "\n") for i in range(5, 1000): buf = hmac.new(cborSeed, b'Root Seed Chain %d' % i, hashlib.sha512).digest() buf_l, buf_r = buf[:32], buf[32:] if hashlib.sha512(buf_l).digest()[31] & 32 == 0: # print(b'Root Seed Chain %d' % i) bip32 = ed25519.SigningKey(buf_l) break # print("SecretKey:", buf_l.hex()) # print("ChainCode:", buf_r.hex()) xpub = bip32.vk_s + buf_r # print("XPub:", xpub.hex()) addrType = 0 addrAttributes = {} addrRoot = [ addrType, [addrType, xpub], addrAttributes ] addrRoot = cbor.dumps(addrRoot) # print("addrRoot:", addrRoot.hex()) sha3 = hashlib.sha3_256(addrRoot) # print("SHA3:", sha3.hexdigest()) addrRoot = hashlib.blake2b(sha3.digest(), digest_size=28) # print("Blake2b:", addrRoot.hexdigest()) abstractHash = addrRoot.digest() address = [ abstractHash, addrAttributes, addrType ] address = cbor.dumps(address) crc = binascii.crc32(address) taggedAddress = cbor.Tag(24, address) cwid = cbor.dumps([taggedAddress, crc]) cwid = base58.b58encode(cwid) # print("CwID:", cwid.decode(), "\n") return cwid.decode()
def use_mnemonic(self, mnemonic: str) -> None: """Use the provided mnemonic to respond to device. Only applies to T1, where device prompts the host for mnemonic words.""" self.mnemonic = Mnemonic.normalize_string(mnemonic).split(" ")
def generate(self): seed = Mnemonic('english').generate() wif = seed address = get_cwid_from_mnemonic(seed) return CryptoCoin(address, wif, seed)
import sys try: # make the test data from mnemonic import Mnemonic eng = Mnemonic('english') with open('b39_data.py', 'wt') as fd: print('vectors = [', file=fd) for ln in [16, 20, 24, 28, 32]: for val in [b'\0', b'\xff', b'\xab\xcd', b'\xa5\xa5', b'\xAA', b'\x55']: vector = val * (ln // len(val)) exp = eng.to_mnemonic(vector) print('(%r, %r),' % (vector, exp), file=fd) print(']', file=fd) sys.path.insert(0, '..') # continue to test below on desktop from binascii import a2b_hex except ImportError: sys.path.insert(0, '') # bugfix from ubinascii import unhexlify as a2b_hex pass import bip39 from ngu_tests import b39_data from ngu_tests import b39_vectors def test_vectors():
def make_seed(self, nbits=132, entropy=1, language=None, segwit=False): """Create a seed""" from .mnemonic import Mnemonic t = 'segwit' if segwit else 'standard' s = Mnemonic(language).make_seed(t, nbits, custom_entropy=entropy) return s
def test_reset_device_pin(self): external_entropy = b'zlutoucky kun upel divoke ody' * 2 strength = 128 ret = self.client.call_raw(proto.ResetDevice(display_random=True, strength=strength, passphrase_protection=True, pin_protection=True, language='english', label='test')) self.assertIsInstance(ret, proto.ButtonRequest) self.client.debug.press_yes() ret = self.client.call_raw(proto.ButtonAck()) self.assertIsInstance(ret, proto.PinMatrixRequest) # Enter PIN for first time pin_encoded = self.client.debug.encode_pin('654') ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) self.assertIsInstance(ret, proto.PinMatrixRequest) # Enter PIN for second time pin_encoded = self.client.debug.encode_pin('654') ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) # Provide entropy self.assertIsInstance(ret, proto.EntropyRequest) internal_entropy = self.client.debug.read_reset_entropy() ret = self.client.call_raw(proto.EntropyAck(entropy=external_entropy)) # Generate mnemonic locally entropy = generate_entropy(strength, internal_entropy, external_entropy) expected_mnemonic = Mnemonic('english').to_mnemonic(entropy) mnemonic = [] for _ in range(strength//32*3): self.assertIsInstance(ret, proto.ButtonRequest) mnemonic.append(self.client.debug.read_reset_word()) self.client.debug.press_yes() self.client.call_raw(proto.ButtonAck()) mnemonic = ' '.join(mnemonic) # Compare that device generated proper mnemonic for given entropies self.assertEqual(mnemonic, expected_mnemonic) mnemonic = [] for _ in range(strength//32*3): self.assertIsInstance(ret, proto.ButtonRequest) mnemonic.append(self.client.debug.read_reset_word()) self.client.debug.press_yes() resp = self.client.call_raw(proto.ButtonAck()) self.assertIsInstance(resp, proto.Success) mnemonic = ' '.join(mnemonic) # Compare that second pass printed out the same mnemonic once again self.assertEqual(mnemonic, expected_mnemonic) # Check if device is properly initialized resp = self.client.call_raw(proto.Initialize()) self.assertTrue(resp.pin_protection) self.assertTrue(resp.passphrase_protection) # Do passphrase-protected action, PassphraseRequest should be raised resp = self.client.call_raw(proto.Ping(passphrase_protection=True)) self.assertIsInstance(resp, proto.PassphraseRequest) self.client.call_raw(proto.Cancel()) # Do PIN-protected action, PinRequest should be raised resp = self.client.call_raw(proto.Ping(pin_protection=True)) self.assertIsInstance(resp, proto.PinMatrixRequest) self.client.call_raw(proto.Cancel())