def test_invalid_sharing(self): identifier = slip39.generate_random_identifier() # Group threshold exceeds number of groups. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.EMS, identifier, 3, [(3, 5), (2, 5)], 1) # Invalid group threshold. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.EMS, identifier, 0, [(3, 5), (2, 5)], 1) # Member threshold exceeds number of members. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.EMS, identifier, 2, [(3, 2), (2, 5)], 1) # Invalid member threshold. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.EMS, identifier, 2, [(0, 2), (2, 5)], 1) # Group with multiple members and threshold 1. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.EMS, identifier, 2, [(3, 5), (1, 3), (2, 5)], 1)
def test_iteration_exponent(self): identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data(self.MS, identifier, 1, [(3, 5)], b"TREZOR", 1) mnemonics = mnemonics[0] identifier, exponent, ems = slip39.combine_mnemonics(mnemonics[1:4]) self.assertEqual(slip39.decrypt(identifier, exponent, ems, b"TREZOR"), self.MS) self.assertNotEqual(slip39.decrypt(identifier, exponent, ems, b""), self.MS) identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data(self.MS, identifier, 1, [(3, 5)], b"TREZOR", 2) mnemonics = mnemonics[0] identifier, exponent, ems = slip39.combine_mnemonics(mnemonics[1:4]) self.assertEqual(slip39.decrypt(identifier, exponent, ems, b"TREZOR"), self.MS) self.assertNotEqual(slip39.decrypt(identifier, exponent, ems, b""), self.MS)
async def backup_group_slip39_wallet( ctx: wire.Context, encrypted_master_secret: bytes ) -> None: # get number of groups await layout.slip39_group_show_checklist_set_groups(ctx) groups_count = await layout.slip39_prompt_number_of_groups(ctx) # get group threshold await layout.slip39_group_show_checklist_set_group_threshold(ctx, groups_count) group_threshold = await layout.slip39_prompt_group_threshold(ctx, groups_count) # get shares and thresholds await layout.slip39_group_show_checklist_set_shares( ctx, groups_count, group_threshold ) groups = [] for i in range(groups_count): share_count = await layout.slip39_prompt_number_of_shares(ctx, i) share_threshold = await layout.slip39_prompt_threshold(ctx, share_count, i) groups.append((share_threshold, share_count)) # generate the mnemonics mnemonics = slip39.generate_mnemonics_from_data( encrypted_master_secret=encrypted_master_secret, identifier=storage.device.get_slip39_identifier(), group_threshold=group_threshold, groups=groups, iteration_exponent=storage.device.get_slip39_iteration_exponent(), ) # show and confirm individual shares await layout.slip39_group_show_and_confirm_shares(ctx, mnemonics)
def test_group_sharing(self): group_threshold = 2 group_sizes = (5, 3, 5, 1) member_thresholds = (3, 2, 2, 1) identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data( self.MS, identifier, group_threshold, list(zip(member_thresholds, group_sizes)) ) # Test all valid combinations of mnemonics. for groups in combinations(zip(mnemonics, member_thresholds), group_threshold): for group1_subset in combinations(groups[0][0], groups[0][1]): for group2_subset in combinations(groups[1][0], groups[1][1]): mnemonic_subset = list(group1_subset + group2_subset) random.shuffle(mnemonic_subset) identifier, exponent, ems = slip39.combine_mnemonics(mnemonic_subset) self.assertEqual(slip39.decrypt(identifier, exponent, ems, b""), self.MS) # Minimal sets of mnemonics. identifier, exponent, ems = slip39.combine_mnemonics([mnemonics[2][0], mnemonics[2][2], mnemonics[3][0]]) self.assertEqual(slip39.decrypt(identifier, exponent, ems, b""), self.MS) self.assertEqual(slip39.combine_mnemonics([mnemonics[2][3], mnemonics[3][0], mnemonics[2][4]])[2], ems) # One complete group and one incomplete group out of two groups required. with self.assertRaises(slip39.MnemonicError): slip39.combine_mnemonics(mnemonics[0][2:] + [mnemonics[1][0]]) # One group of two required. with self.assertRaises(slip39.MnemonicError): slip39.combine_mnemonics(mnemonics[0][1:4])
def test_all_groups_exist(self): for group_threshold in (1, 2, 5): _, mnemonics = slip39.generate_mnemonics_from_data( self.MS, group_threshold, [(3, 5), (1, 1), (2, 3), (2, 5), (3, 5)]) self.assertEqual(len(mnemonics), 5) self.assertEqual(len(sum(mnemonics, [])), 19)
def test_basic_sharing_random(self): ems = random.bytes(32) identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data( ems, identifier, 1, [(3, 5)], 1) mnemonics = mnemonics[0] self.assertEqual(slip39.combine_mnemonics(mnemonics[:3]), slip39.combine_mnemonics(mnemonics[2:]))
def test_all_groups_exist(self): for group_threshold in (1, 2, 5): identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data( self.EMS, identifier, group_threshold, [(3, 5), (1, 1), (2, 3), (2, 5), (3, 5)], 1) self.assertEqual(len(mnemonics), 5) self.assertEqual(len(sum(mnemonics, [])), 19)
def test_passphrase(self): _, mnemonics = slip39.generate_mnemonics_from_data( self.MS, 1, [(3, 5)], b"TREZOR") mnemonics = mnemonics[0] identifier, exponent, ems = slip39.combine_mnemonics(mnemonics[1:4]) self.assertEqual(slip39.decrypt(identifier, exponent, ems, b"TREZOR"), self.MS) self.assertNotEqual(slip39.decrypt(identifier, exponent, ems, b""), self.MS)
def test_iteration_exponent(self): identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data( self.EMS, identifier, 1, [(3, 5)], 1) mnemonics = mnemonics[0] identifier, exponent, ems, group_count = slip39.combine_mnemonics( mnemonics[1:4]) self.assertEqual(ems, self.EMS) self.assertEqual(group_count, 1) identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data( self.EMS, identifier, 1, [(3, 5)], 2) mnemonics = mnemonics[0] identifier, exponent, ems, group_count = slip39.combine_mnemonics( mnemonics[1:4]) self.assertEqual(group_count, 1) self.assertEqual(ems, self.EMS)
def test_basic_sharing_fixed(self): generated_identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data(self.MS, generated_identifier, 1, [(3, 5)]) mnemonics = mnemonics[0] identifier, exponent, ems = slip39.combine_mnemonics(mnemonics[:3]) self.assertEqual(slip39.decrypt(identifier, exponent, ems, b""), self.MS) self.assertEqual(generated_identifier, identifier) self.assertEqual(slip39.combine_mnemonics(mnemonics[1:4])[2], ems) with self.assertRaises(slip39.MnemonicError): slip39.combine_mnemonics(mnemonics[1:3])
def test_group_sharing_threshold_1(self): group_threshold = 1 group_sizes = (5, 3, 5, 1) member_thresholds = (3, 2, 2, 1) identifier = slip39.generate_random_identifier() mnemonics = slip39.generate_mnemonics_from_data( self.MS, identifier, group_threshold, list(zip(member_thresholds, group_sizes)) ) # Test all valid combinations of mnemonics. for group, threshold in zip(mnemonics, member_thresholds): for group_subset in combinations(group, threshold): mnemonic_subset = list(group_subset) random.shuffle(mnemonic_subset) identifier, exponent, ems = slip39.combine_mnemonics(mnemonic_subset) self.assertEqual(slip39.decrypt(identifier, exponent, ems, b""), self.MS)
async def backup_slip39_basic(ctx: wire.Context, encrypted_master_secret: bytes) -> None: # get number of shares await layout.slip39_show_checklist(ctx, 0, BackupType.Slip39_Basic) shares_count = await layout.slip39_prompt_number_of_shares(ctx) # get threshold await layout.slip39_show_checklist(ctx, 1, BackupType.Slip39_Basic) threshold = await layout.slip39_prompt_threshold(ctx, shares_count) # generate the mnemonics mnemonics = slip39.generate_mnemonics_from_data( encrypted_master_secret, storage.device.get_slip39_identifier(), 1, # Single Group threshold [(threshold, shares_count)], # Single Group threshold/count storage.device.get_slip39_iteration_exponent(), )[0] # show and confirm individual shares await layout.slip39_show_checklist(ctx, 2, BackupType.Slip39_Basic) await layout.slip39_basic_show_and_confirm_shares(ctx, mnemonics)
def test_invalid_sharing(self): identifier = slip39.generate_random_identifier() # Short master secret. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.MS[:14], identifier, 1, [(2, 3)]) # Odd length master secret. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.MS + b"X", identifier,1, [(2, 3)]) # Group threshold exceeds number of groups. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.MS, identifier, 3, [(3, 5), (2, 5)]) # Invalid group threshold. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.MS, identifier, 0, [(3, 5), (2, 5)]) # Member threshold exceeds number of members. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.MS, identifier, 2, [(3, 2), (2, 5)]) # Invalid member threshold. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.MS, identifier, 2, [(0, 2), (2, 5)]) # Group with multiple members and threshold 1. with self.assertRaises(ValueError): slip39.generate_mnemonics_from_data(self.MS, identifier, 2, [(3, 5), (1, 3), (2, 5)])
def test_basic_sharing_random(self): ms = random.bytes(32) _, mnemonics = slip39.generate_mnemonics_from_data(ms, 1, [(3, 5)]) mnemonics = mnemonics[0] self.assertEqual(slip39.combine_mnemonics(mnemonics[:3]), slip39.combine_mnemonics(mnemonics[2:]))