示例#1
0
 def update_header_data(self, new_header_data):
     self._storage.update_header_data(
         AES.GCMEnc(
             self.key,
             AES.GCMDec(self._key,
                        self._storage.header_data)\
                        [:self._index_offset] + \
                        new_header_data))
示例#2
0
 def test_KeyGen(self):
     self.assertTrue(len(AES.key_sizes) in (3, 4))
     self.assertTrue(len(set(AES.key_sizes)) in (3, 4))
     for keysize in AES.key_sizes:
         key_list = []
         key_set = set()
         for i in range(10):
             k = AES.KeyGen(keysize)
             self.assertEqual(len(k), keysize)
             key_list.append(k)
             key_set.add(k)
         self.assertEqual(len(key_list), 10)
         # make sure every key is unique
         self.assertEqual(len(key_list), len(key_set))
示例#3
0
    def __init__(self, storage, **kwds):
        self._key = kwds.pop('key', None)
        if self._key is None:
            raise ValueError("An encryption key is required using "
                             "the 'key' keyword.")
        if isinstance(storage, BlockStorageInterface):
            storage_owned = False
            self._storage = storage
            if len(kwds):
                raise ValueError("Keywords not used when initializing "
                                 "with a storage device: %s" % (str(kwds)))
        else:
            storage_owned = True
            storage_type = kwds.pop('storage_type', 'file')
            self._storage = \
                BlockStorageTypeFactory(storage_type)(storage, **kwds)

        try:
            header_data = AES.GCMDec(self._key, self._storage.header_data)
            (self._ismodegcm, ) = struct.unpack(
                self._index_struct_string, header_data[:self._index_offset])
            self._verify_digest = header_data[:hashlib.sha384().digest_size]

            verify = hmac.HMAC(key=self.key,
                               msg=struct.pack(self._verify_struct_string,
                                               self._storage.block_size,
                                               self._storage.block_count,
                                               len(self._storage.header_data)),
                               digestmod=hashlib.sha384)
            if verify.digest() != self._verify_digest:
                raise ValueError("HMAC of plaintext index data does not match")
            if self._ismodegcm:
                self._encrypt_block_func = AES.GCMEnc
                self._decrypt_block_func = AES.GCMDec
            else:
                self._encrypt_block_func = AES.CTREnc
                self._decrypt_block_func = AES.CTRDec
        except:
            if storage_owned:
                self._storage.close()
            raise
示例#4
0
def runtest(label, enc_func, dec_func):
    print("")
    print("$" * 20)
    print("{0:^20}".format(label))
    print("$" * 20)
    for keysize in AES.key_sizes[:3]:
        print("")
        print("@@@@@@@@@@@@@@@@@@@@")
        print(" Key Size: %s bytes" % (keysize))
        print("@@@@@@@@@@@@@@@@@@@@")
        print("\nTest Bulk")
        #
        # generate a key
        #
        key = AES.KeyGen(keysize)
        print("Key: %s" % (base64.b64encode(key)))

        #
        # generate some plaintext
        #
        nblocks = 1000000
        plaintext_numbytes = AES.block_size * nblocks
        print("Plaintext Size: %s MB" % (plaintext_numbytes * 1.0e-6))
        # all zeros
        plaintext = bytes(bytearray(plaintext_numbytes))

        #
        # time encryption
        #
        start_time = time.time()
        ciphertext = enc_func(key, plaintext)
        stop_time = time.time()
        print("Encryption Time: %.3fs (%.3f MB/s)" %
              (stop_time - start_time,
               (plaintext_numbytes * 1.0e-6) / (stop_time - start_time)))

        #
        # time decryption
        #
        start_time = time.time()
        plaintext_decrypted = dec_func(key, ciphertext)
        stop_time = time.time()
        print("Decryption Time: %.3fs (%.3f MB/s)" %
              (stop_time - start_time,
               (plaintext_numbytes * 1.0e-6) / (stop_time - start_time)))

        assert plaintext_decrypted == plaintext
        assert ciphertext != plaintext
        # IND-CPA
        assert enc_func(key, plaintext) != ciphertext
        # make sure the only difference is not in the IV
        assert enc_func(key, plaintext)[AES.block_size:] \
            != ciphertext[AES.block_size:]
        if enc_func is AES.CTREnc:
            assert len(plaintext) == \
                len(ciphertext) - AES.block_size
        else:
            assert enc_func is AES.GCMEnc
            assert len(plaintext) == \
                len(ciphertext) - 2*AES.block_size

        del plaintext
        del plaintext_decrypted
        del ciphertext

        print("\nTest Chunks")
        #
        # generate a key
        #
        key = AES.KeyGen(keysize)
        print("Key: %s" % (base64.b64encode(key)))

        #
        # generate some plaintext
        #
        nblocks = 1000
        blocksize = 16000
        total_bytes = blocksize * nblocks
        print("Block Size: %s KB" % (blocksize * 1.0e-3))
        print("Block Count: %s" % (nblocks))
        print("Total: %s MB" % (total_bytes * 1.0e-6))
        plaintext_blocks = [
            bytes(bytearray(blocksize)) for i in range(nblocks)
        ]

        #
        # time encryption
        #
        start_time = time.time()
        ciphertext_blocks = [enc_func(key, b) for b in plaintext_blocks]
        stop_time = time.time()
        print("Encryption Time: %.3fs (%.3f MB/s)" %
              (stop_time - start_time,
               (total_bytes * 1.0e-6) / (stop_time - start_time)))

        #
        # time decryption
        #
        start_time = time.time()
        plaintext_decrypted_blocks = [
            dec_func(key, c) for c in ciphertext_blocks
        ]
        stop_time = time.time()
        print("Decryption Time: %.3fs (%.3f MB/s)" %
              (stop_time - start_time,
               (total_bytes * 1.0e-6) / (stop_time - start_time)))
示例#5
0
    def _test_Enc_Dec(self, enc_func, dec_func, get_plaintext, keysizes):
        keysizes = list(keysizes)
        self.assertTrue(len(keysizes) > 0)
        blocksize_factor = [0.5, 1, 1.5, 2, 2.5]
        plaintext_blocks = []
        for i, f in enumerate(blocksize_factor):
            size = AES.block_size * f
            size = int(round(size))
            if int(f) != f:
                assert (size % AES.block_size) != 0
            plaintext_blocks.append(get_plaintext(i, size))

        assert len(AES.key_sizes) > 0
        ciphertext_blocks = {}
        keys = {}
        for keysize in keysizes:
            key = AES.KeyGen(keysize)
            keys[keysize] = key
            ciphertext_blocks[keysize] = []
            for block in plaintext_blocks:
                ciphertext_blocks[keysize].append(enc_func(key, block))

        self.assertEqual(len(ciphertext_blocks), len(keysizes))
        self.assertEqual(len(keys), len(keysizes))

        plaintext_decrypted_blocks = {}
        for keysize in keys:
            key = keys[keysize]
            plaintext_decrypted_blocks[keysize] = []
            for block in ciphertext_blocks[keysize]:
                plaintext_decrypted_blocks[keysize].append(dec_func(
                    key, block))

        self.assertEqual(len(plaintext_decrypted_blocks), len(keysizes))

        for i in range(len(blocksize_factor)):
            for keysize in keysizes:
                self.assertEqual(plaintext_blocks[i],
                                 plaintext_decrypted_blocks[keysize][i])
                self.assertNotEqual(plaintext_blocks[i],
                                    ciphertext_blocks[keysize][i])
                if enc_func is AES.CTREnc:
                    self.assertEqual(len(ciphertext_blocks[keysize][i]),
                                     len(plaintext_blocks[i]) + AES.block_size)
                else:
                    assert enc_func is AES.GCMEnc
                    self.assertEqual(
                        len(ciphertext_blocks[keysize][i]),
                        len(plaintext_blocks[i]) + 2 * AES.block_size)
                # check IND-CPA
                key = keys[keysize]
                alt_ciphertext = enc_func(key, plaintext_blocks[i])
                self.assertNotEqual(ciphertext_blocks[keysize][i],
                                    alt_ciphertext)
                self.assertEqual(len(ciphertext_blocks[keysize][i]),
                                 len(alt_ciphertext))
                self.assertNotEqual(
                    ciphertext_blocks[keysize][i][:AES.block_size],
                    alt_ciphertext[:AES.block_size])
                self.assertNotEqual(
                    ciphertext_blocks[keysize][i][AES.block_size:],
                    alt_ciphertext[AES.block_size:])
示例#6
0
 def header_data(self):
     return AES.GCMDec(self._key,
                       self._storage.header_data)\
                       [self._index_offset:]
示例#7
0
    def setup(cls,
              storage_name,
              block_size,
              block_count,
              aes_mode='ctr',
              key_size=None,
              key=None,
              storage_type='file',
              initialize=None,
              **kwds):

        if (key is not None) and (key_size is not None):
            raise ValueError("Only one of 'key' or 'keysize' keywords can "
                             "be specified at a time")
        if key is None:
            if key_size is None:
                key_size = 32
            if key_size not in AES.key_sizes:
                raise ValueError("Invalid key size: %s" % (key_size))
            key = AES.KeyGen(key_size)
        else:
            if len(key) not in AES.key_sizes:
                raise ValueError("Invalid key size: %s" % (len(key)))

        if (block_size <= 0) or (block_size != int(block_size)):
            raise ValueError(
                "Block size (bytes) must be a positive integer: %s" %
                (block_size))

        ismodegcm = None
        encrypt_block_func = None
        encrypted_block_size = block_size
        if aes_mode == 'ctr':
            ismodegcm = False
            encrypt_block_func = AES.CTREnc
            encrypted_block_size += AES.block_size
        elif aes_mode == 'gcm':
            ismodegcm = True
            encrypt_block_func = AES.GCMEnc
            encrypted_block_size += (2 * AES.block_size)
        else:
            raise ValueError(
                "AES encryption mode must be one of 'ctr' or 'gcm'. "
                "Invalid value: %s" % (aes_mode))
        assert ismodegcm is not None
        assert encrypt_block_func is not None

        if not isinstance(storage_type, BlockStorageInterface):
            storage_type = BlockStorageTypeFactory(storage_type)

        if initialize is None:
            zeros = bytes(bytearray(block_size))
            initialize = lambda i: zeros

        def encrypted_initialize(i):
            return encrypt_block_func(key, initialize(i))

        kwds['initialize'] = encrypted_initialize

        user_header_data = kwds.get('header_data', bytes())
        if type(user_header_data) is not bytes:
            raise TypeError("'header_data' must be of type bytes. "
                            "Invalid type: %s" % (type(user_header_data)))
        # we generate the first time simply to
        # compute the length
        tmp = hmac.HMAC(key=key,
                        msg=struct.pack(cls._verify_struct_string,
                                        encrypted_block_size, block_count, 0),
                        digestmod=hashlib.sha384).digest()
        header_data = bytearray(
            struct.pack(cls._index_struct_string, ismodegcm))
        header_data[:hashlib.sha384().digest_size] = tmp
        header_data = header_data + user_header_data
        header_data = AES.GCMEnc(key, bytes(header_data))
        # now that we know the length of the header data
        # being sent to the underlying storage we can
        # compute the real hmac
        verify_digest = hmac.HMAC(key=key,
                                  msg=struct.pack(cls._verify_struct_string,
                                                  encrypted_block_size,
                                                  block_count,
                                                  len(header_data)),
                                  digestmod=hashlib.sha384).digest()
        header_data = bytearray(
            struct.pack(cls._index_struct_string, ismodegcm))
        header_data[:hashlib.sha384().digest_size] = verify_digest
        header_data = header_data + user_header_data
        kwds['header_data'] = AES.GCMEnc(key, bytes(header_data))

        return EncryptedBlockStorage(storage_type.setup(
            storage_name, encrypted_block_size, block_count, **kwds),
                                     key=key)
示例#8
0
 def test_setup_fails(self):
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(IOError):
         PathORAM.setup(
             os.path.join(thisdir,
                          "baselines",
                          "exists.empty"),
             block_size=10,
             block_count=10,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=self._test_key,
             key_size=self._test_key_size,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(IOError):
         PathORAM.setup(
             os.path.join(thisdir,
                          "baselines",
                          "exists.empty"),
             block_size=10,
             block_count=10,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=self._test_key,
             key_size=self._test_key_size,
             storage_type=self._type_name,
             aes_mode=self._aes_mode,
             ignore_existing=False,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=0,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=self._test_key,
             key_size=self._test_key_size,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=0,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=self._test_key,
             key_size=self._test_key_size,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(TypeError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=self._test_key,
             key_size=self._test_key_size,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             header_data=2,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=self._test_key,
             key_size=self._test_key_size,
             aes_mode=None,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=0,
             heap_base=self._heap_base,
             key=self._test_key,
             key_size=self._test_key_size,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=1,
             key=self._test_key,
             key_size=self._test_key_size,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key_size=-1,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(TypeError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=-1,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=AES.KeyGen(AES.key_sizes[-1]),
             key_size=AES.key_sizes[-1],
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     self.assertEqual(os.path.exists(self._dummy_name), False)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=os.urandom(AES.key_sizes[-1]+100),
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)
     with self.assertRaises(ValueError):
         PathORAM.setup(
             self._dummy_name,
             block_size=1,
             block_count=1,
             heap_height=1,
             bucket_capacity=self._bucket_capacity,
             heap_base=self._heap_base,
             key=self._key,
             aes_mode=self._aes_mode,
             storage_type=self._type_name,
             **self._kwds)