def test_initialize_many(self): """ Check that multiple keys generated, wrapped with users' public keys, and stored in a keystore can be retrieved and unwrapped with the users' secret keys. """ keygen = KeyGen('Sixteen byte key') keystore = DummyKeyStore() key_infos = [('attr' + str(i), i, 'meta' + str(i), 16) for i in xrange(self.num_keys)] users = {} RSA_sks = {} for i in xrange(self.num_users): userid = 'user' + str(i) RSA_key = RSA.generate(3072) RSA_sks[userid] = RSA_key RSA_pk = RSA_key.publickey() info = random.sample(key_infos, random.randint(1, len(key_infos))) users[userid] = (RSA_pk, info) keygen.initialize_users(users, keystore) for userid in users: RSA_pk, info = users[userid] for attr, vers, meta, keylen in info: keywrap = keystore.retrieve(userid, attr, vers, meta) self.assertEqual( utils.unwrap_key(keywrap, RSA_sks[userid]), keygen._generate_key(attr, vers, meta, keylen))
def test_init_many_from_file(self): """ Check that multiple keys generated, wrapped with users' public keys, and stored in a keystore can be retrieved and unwrapped with the users' secret keys when input comes from a configuration file. """ keygen = KeyGen('Sixteen byte key') keystore = DummyKeyStore() user_info = { 'user1': [('attr1', 1, 'AES_GCM', 16), ('attr2', 1, 'AES_GCM', 16), ('attr3', 2, 'AES_GCM', 16)], 'user2': [('attr2', 1, 'AES_GCM', 16), ('attr4', 2, 'AES_GCM', 16)], 'user3': [('attr1', 1, 'AES_GCM', 16), ('attr4', 2, 'AES_GCM', 16)] } self.create_configs_from_dict(user_info, TMP_PATH + '/user_info_test.cfg') keygen.init_from_file(TMP_PATH + '/user_info_test.cfg', keystore) for userid in user_info: key_infos = user_info[userid] f = open(TMP_PATH + '/' + userid + '_privkey.pem', 'r') RSA_sk = RSA.importKey(f.read()) f.close() for attr, vers, meta, keylen in key_infos: keywrap = keystore.retrieve(userid, attr, vers, meta) self.assertEqual( utils.unwrap_key(keywrap, RSA_sk), keygen._generate_key(attr, vers, meta, keylen))
def get_attribute_key(self, algorithm, attribute, version=1): """ Arguments: algorithm - (string) Name of algorithm for which the user wishes to retrieve the current key for, triggers PKILookupError if the algorithm is not part of VIS_ALGORITHMS attribute - (string) Attribute for which to retrieve the key for version - (int)version of key to grab, defaults to 1 Returns: Key for (userid, algorithm, attribute, version) tuple Raises: PKILookupError if the key cannot be found for the (userid, algorithm, attribute, version) tuple. """ #get the keys try: key_wrap = self._acc_keystore.retrieve(self._user_id, attribute, version, algorithm) except PKILookupError as ple: raise PKILookupError( "User %s with algorithm %s and attribute %s is not present in keystore." % (self._user_id, algorithm, attribute)) #unwrap the key return key_utils.unwrap_key(key_wrap, self._rsa_key)
def get_key(self, algorithm, version=1): """ Arguments: algorithm - (string) Name of algorithm for which the user wishes to retrieve the key for, triggers PKILookupError if the algorithm is not part of AES_ALGORITHMS version - (int) version of key to grab, defaults to 1 Returns: Key for (userid, algorithm, version) tuple Raises: PKILookupError if the key cannot be found for the (userid, algorithm, version) tuple. """ #get the keys try: key_wrap = self._acc_keystore.retrieve(self._user_id, '', version, algorithm) except PKILookupError: raise PKILookupError("User " + self._user_id + " with algorithm " +\ algorithm + " is not present in keystore.") #unwrap the key return key_utils.unwrap_key(key_wrap, self._rsa_key)
def get_current_attribute_key(self, algorithm, attribute): """ Arguments: algorithm - (string) Name of algorithm for which the user wishes to retrieve the key for, triggers PKILookupError if the algorithm is not part of AES_ALGORITHMS attribute - (string) Attribute for which to retrieve the key for Returns: (Most current key for (userid, algorithm, attribute) tuple, version) Raises: PKILookupError if the key cannot be found for the (userid, algorithm, attribute) tuple. """ #get the keys try: key_wrap = self._acc_keystore.retrieve_latest_version( self._user_id, algorithm, attribute) except PKILookupError as ple: raise PKILookupError( "User %s with algorithm %s and attribute %s is not present in keystore." % (self._user_id, algorithm, attribute)) #unwrap the key return (key_utils.unwrap_key(key_wrap.keywrap, self._rsa_key), key_wrap.vers)
def get_current_key(self, algorithm): """ Arguments: algorithm - (string) Name of algorithm for which the user wishes to retrieve the key for, triggers PKILookupError if the algorithm is not part of AES_ALGORITHMS Returns: (Most current key for (userid, algorithm) tuple, version) Raises: PKILookupError if the key cannot be found for the (userid, algorithm) tuple. """ #get the keys try: key_wrap = self._acc_keystore.retrieve_latest_version( self._user_id, algorithm, '') except PKILookupError: raise PKILookupError("User " + self._user_id + " with algorithm " +\ algorithm + " is not present in keystore.") #unwrap the key return (key_utils.unwrap_key(key_wrap.keywrap, self._rsa_key), key_wrap.vers)
def test_initialize_diff_users_same_info(self): """ Check that two different users can recover the same key for the same attribute, version, metadata, key length combination. """ RSA_key1 = RSA.generate(3072) RSA_pk1 = RSA_key1.publickey() RSA_key2 = RSA.generate(3072) RSA_pk2 = RSA_key2.publickey() keygen = KeyGen('Sixteen byte key') keystore = DummyKeyStore() keygen.initialize_users( { 'user1': (RSA_pk1, [('attr', 1, 'meta', 16)]), 'user2': (RSA_pk2, [('attr', 1, 'meta', 16)]) }, keystore) keywrap1 = keystore.retrieve('user1', 'attr', 1, 'meta') keywrap2 = keystore.retrieve('user2', 'attr', 1, 'meta') self.assertEqual(utils.unwrap_key(keywrap1, RSA_key1), utils.unwrap_key(keywrap2, RSA_key2))
def test_initialize_single(self): """ Check that a key generated, wrapped with a user's public key, and stored in a keystore can be retrieved and unwrapped with the user's secret key. """ RSA_key = RSA.generate(3072) RSA_pk = RSA_key.publickey() keygen = KeyGen('Sixteen byte key') keystore = DummyKeyStore() orig_key = keygen._generate_key('attr', 1, 'meta', 16) keygen.initialize_users( {'userid': (RSA_pk, [('attr', 1, 'meta', 16)])}, keystore) keywrap = keystore.retrieve('userid', 'attr', 1, 'meta') self.assertEqual(utils.unwrap_key(keywrap, RSA_key), orig_key)
def test_valid_enc_dec(self): """ Check that we can unwrap a key using the private key corresponding to the public key used to wrap the key. """ RSA_key = RSA.generate(3072) RSA_pk = RSA_key.publickey() for i in range(self.num_iters): sk = format(random.getrandbits(128), 'b') keywrap = wrap_key(sk, RSA_pk) try: decrypted_key = unwrap_key(keywrap, RSA_key) except ValueError as e: self.assertTrue(False, 'Error: %s' % e.msg) else: self.assertEqual(decrypted_key, sk, 'Failed to unwrap original key')
def test_invalid_enc_dec(self): """ Check that we cannot unwrap a key using a private key that does not correspond to the public key used to wrap the key. """ RSA_key = RSA.generate(3072) RSA_pk = RSA_key.publickey() for i in range(self.num_iters): sk = format(random.getrandbits(128), 'b') keywrap = wrap_key(sk, RSA_pk) other_key = RSA.generate(3072) try: decrypted_key = unwrap_key(keywrap, other_key) except ValueError: self.assertTrue(True, 'error') else: self.assertNotEqual(decrypted_key, sk, 'Decryption succeeded with invalid key')
def test_initialize_empty(self): """ Check that a key generated from empty string inputs, wrapped with a user's public key, and stored in a keystore can be retrieved and unwrapped with the user's secret key. """ RSA_key = RSA.generate(3072) RSA_pk = RSA_key.publickey() keygen = KeyGen('Sixteen byte key') keystore = DummyKeyStore() params = [('', 'attr', 1, 'meta'), ('userid', '', 1, 'meta'), ('userid', 'attr', 0, 'meta'), ('userid', 'attr', 1, ''), ('', '', 0, '')] for userid, attr, vers, meta in params: orig_key = keygen._generate_key(attr, vers, meta, 16) keygen.initialize_users( {userid: (RSA_pk, [(attr, vers, meta, 16)])}, keystore) keywrap = keystore.retrieve(userid, attr, vers, meta) self.assertEqual(utils.unwrap_key(keywrap, RSA_key), orig_key)
def test_revocation_all_attrs(self): """ Tests that revoking all of a user's attributes removes the appropriate entries from the keystore and the user/attr maps and generates wraps of new keys for the correct set of users. """ keygen = KeyGen('Sixteen byte key') ks = DummyKeyStore() attr_user_dict = { 'A': ['user1', 'user2', 'user3'], 'B': ['user1', 'user2'], 'C': ['user1', 'user3'] } attr_user_map = LocalAttrUserMap(attr_user_dict) user_attr_dict = { 'user1': ['A', 'B', 'C'], 'user2': ['A', 'B'], 'user3': ['A', 'C'] } user_attr_map = LocalUserAttrMap(user_attr_dict) user_sks = {} user_pks = {} for i in range(1, 4): userid = 'user' + str(i) RSA_key = RSA.generate(3072) user_sks[userid] = RSA_key RSA_pk = RSA_key.publickey() user_pks[userid] = RSA_pk key_infos = { 'user1': [ KeyInfo('A', 1, 'meta1', 'keywrap1', 16), KeyInfo('A', 1, 'meta2', 'keywrap2', 16), KeyInfo('B', 1, 'meta1', 'keywrap4', 16), KeyInfo('B', 1, 'meta2', 'keywrap5', 16), KeyInfo('C', 1, 'meta1', 'keywrap6', 16), KeyInfo('C', 1, 'meta2', 'keywrap7', 16) ], 'user2': [ KeyInfo('A', 1, 'meta2', 'keywrap8', 16), KeyInfo('A', 1, 'meta3', 'keywrap9', 16), KeyInfo('B', 1, 'meta1', 'keywrap10', 16), KeyInfo('B', 1, 'meta2', 'keywrap11', 16) ], 'user3': [ KeyInfo('A', 1, 'meta1', 'keywrap12', 16), KeyInfo('A', 1, 'meta2', 'keywrap13', 16), KeyInfo('A', 1, 'meta3', 'keywrap14', 16), KeyInfo('C', 1, 'meta1', 'keywrap15', 16), KeyInfo('C', 1, 'meta2', 'keywrap16', 16) ] } for user in key_infos: ks.batch_insert(user, key_infos[user]) #revoke all attributes from a user keygen.revoke_all_attrs('user1', ks, attr_user_map, user_attr_map, user_pks) #check that keywraps for revoked user were removed from keystore for i in range(1, 3): self.assertRaises(PKILookupError, ks.retrieve, 'user1', 'A', 1, 'meta' + str(i)) self.assertRaises(PKILookupError, ks.retrieve, 'user1', 'B', 1, 'meta' + str(i)) self.assertRaises(PKILookupError, ks.retrieve, 'user1', 'C', 1, 'meta' + str(i)) #check that updated user/attr maps are correct self.assertEqual(set(attr_user_map.users_by_attribute('A')), set(['user2', 'user3'])) self.assertEqual(attr_user_map.users_by_attribute('B'), ['user2']) self.assertEqual(attr_user_map.users_by_attribute('C'), ['user3']) self.assertEqual(user_attr_map.attributes_by_user('user1'), []) self.assertEqual(set(user_attr_map.attributes_by_user('user2')), set(['A', 'B'])) self.assertEqual(set(user_attr_map.attributes_by_user('user3')), set(['A', 'C'])) #check that metadatas for revoked attrs have correct version numbers self.assertEqual(ks.retrieve_latest_version_number('meta1', 'A'), 2) self.assertEqual(ks.retrieve_latest_version_number('meta2', 'A'), 2) self.assertEqual(ks.retrieve_latest_version_number('meta3', 'A'), 1) self.assertEqual(ks.retrieve_latest_version_number('meta1', 'B'), 2) self.assertEqual(ks.retrieve_latest_version_number('meta2', 'B'), 2) #check that other users with revoked attrs got new keywraps that decrypt #to keys of the correct length kw_2_2_A = ks.retrieve_latest_version('user2', 'meta2', 'A').keywrap kw_3_1_A = ks.retrieve_latest_version('user3', 'meta1', 'A').keywrap kw_3_2_A = ks.retrieve_latest_version('user3', 'meta2', 'A').keywrap kw_2_1_B = ks.retrieve_latest_version('user2', 'meta1', 'B').keywrap kw_2_2_B = ks.retrieve_latest_version('user2', 'meta2', 'B').keywrap kw_3_1_C = ks.retrieve_latest_version('user3', 'meta1', 'C').keywrap kw_3_2_C = ks.retrieve_latest_version('user3', 'meta2', 'C').keywrap self.assertEqual(len(utils.unwrap_key(kw_2_2_A, user_sks['user2'])), 16) self.assertEqual(len(utils.unwrap_key(kw_3_1_A, user_sks['user3'])), 16) self.assertEqual(len(utils.unwrap_key(kw_3_2_A, user_sks['user3'])), 16) self.assertEqual(len(utils.unwrap_key(kw_2_1_B, user_sks['user2'])), 16) self.assertEqual(len(utils.unwrap_key(kw_2_2_B, user_sks['user2'])), 16) self.assertEqual(len(utils.unwrap_key(kw_3_1_C, user_sks['user3'])), 16) self.assertEqual(len(utils.unwrap_key(kw_3_2_C, user_sks['user3'])), 16) #revoke all attributes from a user and update some key lengths keylens = {'meta2': 24} keygen.revoke_all_attrs('user2', ks, attr_user_map, user_attr_map, user_pks, keylens) #check that new keys for other users have correct key lengths kw_3_2_A = ks.retrieve_latest_version('user3', 'meta2', 'A').keywrap kw_3_3_A = ks.retrieve_latest_version('user3', 'meta3', 'A').keywrap self.assertEqual(len(utils.unwrap_key(kw_3_2_A, user_sks['user3'])), 24) self.assertEqual(len(utils.unwrap_key(kw_3_3_A, user_sks['user3'])), 16)