def test_exceptions(self): storage.recovery.set_in_progress(True) words = MNEMONIC_SLIP39_BASIC_20_3of6[0] secret, share = process_slip39(words) self.assertIsNone(secret) # same mnemonic words = MNEMONIC_SLIP39_BASIC_20_3of6[0] with self.assertRaises(RuntimeError): secret, share = process_slip39(words) self.assertIsNone(secret) # identifier mismatch words = MNEMONIC_SLIP39_ADVANCED_20[0] with self.assertRaises(RuntimeError): secret, share = process_slip39(words) self.assertIsNone(secret) # same identifier but different group settings words = MNEMONIC_SLIP39_BASIC_20_3of6[0] w = words.split() w[2] = "check" # change the group settings w[3] = "mortgage" w[17] = "garden" # modify checksum accordingly w[18] = "merchant" w[19] = "merchant" words = " ".join(w) with self.assertRaises(RuntimeError): secret, share = process_slip39(words) self.assertIsNone(secret)
def test_check_word_validity(self): storage.recovery.set_in_progress(True) # We claim to know the backup type, but nothing is stored. That is an invalid state. with self.assertRaises(RuntimeError): check(BackupType.Slip39_Advanced, ["ocean"]) # if backup type is not set we can not do any checks check(None, ["ocean"]) # BIP-39 has no "on-the-fly" checks check(BackupType.Bip39, ["ocean"]) # let's store two shares in the storage secret, share = process_slip39( "trash smug adjust ambition criminal prisoner security math cover pecan response pharmacy center criminal salary elbow bracelet lunar briefing dragon" ) self.assertIsNone(secret) secret, share = process_slip39( "trash smug adjust aide benefit temple round clogs devote prevent type cards clogs plastic aspect paper behavior lunar custody intimate" ) self.assertIsNone(secret) # different identifier with self.assertRaises(IdentifierMismatch): check(BackupType.Slip39_Advanced, ["slush"]) # same first word but still a different identifier with self.assertRaises(IdentifierMismatch): check(BackupType.Slip39_Advanced, ["trash", "slush"]) # same identifier but different group settings for Slip 39 Basic with self.assertRaises(IdentifierMismatch): check(BackupType.Slip39_Basic, ["trash", "smug", "slush"]) # same mnemonic found out using the index with self.assertRaises(AlreadyAdded): check(BackupType.Slip39_Advanced, ["trash", "smug", "adjust", "ambition"]) # Let's store two more. The group is 4/6 so this group is now complete. secret, share = process_slip39( "trash smug adjust arena beard quick language program true hush amount round geology should training practice language diet order ruin" ) self.assertIsNone(secret) secret, share = process_slip39( "trash smug adjust beam brave sack magazine radar toxic emission domestic cradle vocal petition mule toxic acid hobo welcome downtown" ) self.assertIsNone(secret) # If trying to add another one from this group we get a warning. with self.assertRaises(ThresholdReached): check(BackupType.Slip39_Advanced, ["trash", "smug", "adjust"])
def test_process_slip39(self): storage.recovery.set_in_progress(True) words = MNEMONIC_SLIP39_BASIC_20_3of6[0] secret, share = process_slip39(words) self.assertIsNone(secret) self.assertEqual(share.group_count, storage.recovery.get_slip39_group_count())
def test_process_slip39_basic(self): storage.recovery.set_in_progress(True) # first share (member index 5) first = MNEMONIC_SLIP39_BASIC_20_3of6[0] secret, share = process_slip39(first) self.assertIsNone(secret) self.assertEqual(share.group_count, storage.recovery.get_slip39_group_count()) self.assertEqual(share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()) self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier()) self.assertEqual(storage.recovery.get_slip39_remaining_shares(0), 2) self.assertEqual( storage.recovery_shares.get(share.index, share.group_index), first) # second share (member index 0) second = MNEMONIC_SLIP39_BASIC_20_3of6[1] secret, share = process_slip39(second) self.assertIsNone(secret) self.assertEqual(storage.recovery.get_slip39_remaining_shares(0), 1) self.assertEqual( storage.recovery_shares.get(share.index, share.group_index), second) self.assertEqual(storage.recovery_shares.fetch_group( share.group_index), [second, first]) # ordered by index # third share (member index 3) third = MNEMONIC_SLIP39_BASIC_20_3of6[2] secret, share = process_slip39(third) self.assertEqual(secret, b'I\x1by[\x80\xfc!\xcc\xdfFl\x0f\xbc\x98\xc8\xfc') self.assertEqual(storage.recovery.get_slip39_remaining_shares(0), 0) self.assertEqual( storage.recovery_shares.get(share.index, share.group_index), third) self.assertEqual(storage.recovery_shares.fetch_group( share.group_index), [second, third, first]) # ordered by index
def test_process_slip39_advanced(self): storage.recovery.set_in_progress(True) # complete group 1 (1of1) words = MNEMONIC_SLIP39_ADVANCED_20[0] secret, share = process_slip39(words) self.assertIsNone(secret) self.assertEqual(share.group_count, storage.recovery.get_slip39_group_count()) self.assertEqual(share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()) self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier()) self.assertEqual(storage.recovery.fetch_slip39_remaining_shares(), [16, 0, 16, 16]) self.assertEqual( storage.recovery_shares.get(share.index, share.group_index), words) # member index 4 from group 2 (3of5) words = MNEMONIC_SLIP39_ADVANCED_20[1] secret, share = process_slip39(words) self.assertIsNone(secret) self.assertEqual(share.group_count, storage.recovery.get_slip39_group_count()) self.assertEqual(share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()) self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier()) self.assertEqual( storage.recovery_shares.get(share.index, share.group_index), words) self.assertEqual(storage.recovery_shares.fetch_group(1), [MNEMONIC_SLIP39_ADVANCED_20[0]]) self.assertEqual(storage.recovery_shares.fetch_group(2), [MNEMONIC_SLIP39_ADVANCED_20[1]]) self.assertEqual(storage.recovery.fetch_slip39_remaining_shares(), [16, 0, 2, 16]) # member index 2 from group 2 words = MNEMONIC_SLIP39_ADVANCED_20[2] secret, share = process_slip39(words) self.assertIsNone(secret) self.assertEqual(share.group_count, storage.recovery.get_slip39_group_count()) self.assertEqual(share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()) self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier()) self.assertEqual( storage.recovery_shares.get(share.index, share.group_index), words) self.assertEqual(storage.recovery_shares.fetch_group(1), [MNEMONIC_SLIP39_ADVANCED_20[0]]) self.assertEqual( storage.recovery_shares.fetch_group(2), [MNEMONIC_SLIP39_ADVANCED_20[2], MNEMONIC_SLIP39_ADVANCED_20[1]]) self.assertEqual(storage.recovery.fetch_slip39_remaining_shares(), [16, 0, 1, 16]) # last member index 0 from group 2 # now group 2 is complete => the whole Shamir recovery is completed words = MNEMONIC_SLIP39_ADVANCED_20[3] secret, share = process_slip39(words) self.assertEqual(secret, b'\xc2\xd2\xe2j\xd0`#\xc6\x01E\xf1P\xab\xe2\xdd+') self.assertEqual(share.group_count, storage.recovery.get_slip39_group_count()) self.assertEqual(share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()) self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier()) self.assertEqual( storage.recovery_shares.get(share.index, share.group_index), words) self.assertEqual(storage.recovery_shares.fetch_group(1), [MNEMONIC_SLIP39_ADVANCED_20[0]]) self.assertEqual(storage.recovery_shares.fetch_group(2), [ MNEMONIC_SLIP39_ADVANCED_20[3], MNEMONIC_SLIP39_ADVANCED_20[2], MNEMONIC_SLIP39_ADVANCED_20[1] ]) self.assertEqual(storage.recovery.fetch_slip39_remaining_shares(), [16, 0, 0, 16])