I designed an puzzle algorithm to take the value of each encrypted block which point to the next block to be encrypted. I have to use aes-ctr-128 for that with some particular reason.
I run a dummy test to see how fast or slow it could be.
Here is what I did. I tested both pycrypto and cryptography.
I first create a 16MB file with random bytes.
I tried in two ways:
Method 1. Load the file into a block list with block size 128bits.
Method 2. Simply load the file into a string.
Now I tested the total time to encrypt each 128-bit block. And I tested the total time to encrypt the whole file.
Here’s the result:
pycrypto:
to encrypt 128-bit block one by one: 61,824 aes-ctr-128 per sec
to encrypt the entire file: 8,843,713 aes-ctr-128 per sec
cryptography
to encrypt 128-bit block one by one: 384,959 aes-ctr-128 per sec
to encrypt the entire file: 113,417,922 aes-ctr-128 per sec
I'm wondering why method 1 and 2 gave me the result with so much difference? Are these two methods suppose to give the same speed?
Here's my test code:
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
backend = default_backend()
from Crypto.Cipher import AES
from Crypto.Util import Counter
import random
import time
BLOCK_SIZE = 16
def read_block(fname):
block_list = []
blobfo = open(fname)
atEOF = False
while not atEOF:
blobdata = blobfo.read(BLOCK_SIZE)
block_list.append(blobdata)
if len(blobdata) < BLOCK_SIZE:
# we should stop after this...
atEOF = True
return block_list
print 'loading data'
block_list = read_block('mediumdata')
print 'loading finish'
print len(block_list), 'blocks'
print 'start encryption'
NUM_COUNTER_BITS = 128
# Here I just use a random key
key = os.urandom(16)
t1 = time.time()
for block in block_list:
ctr = Counter.new(NUM_COUNTER_BITS)
cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
cipher.encrypt(block)
t2 = time.time()
print 'finish encryption'
print 'total time:', t2 - t1
print 'time for each aes:', (t2 - t1) / len(block_list)
print 'num of aes per sec:', len(block_list) / (t2 - t1)
print 'now try to encrypt whole file'
block = open('mediumdata').read()
print type(block)
print 'start encryption'
NUM_COUNTER_BITS = 128
key = os.urandom(16)
t1 = time.time()
ctr = Counter.new(NUM_COUNTER_BITS)
cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
cipher.encrypt(block)
t2 = time.time()
print 'finish encryption'
print 'total time:', t2 - t1
print 'time for each aes:', (t2 - t1) / len(block_list)
print 'num of aes per sec:', len(block_list) / (t2 - t1)
print 'now try cryptography'
print 'start encryption'
t1 = time.time()
num = random.randint(1, 65530)
nonce = "".join(chr((num >> (i * 8)) & 0xFF) for i in range(16))
backend = default_backend()
cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=backend)
encryptor = cipher.encryptor()
for block in block_list:
ciphertext = encryptor.update(block)
encryptor.finalize()
t2 = time.time()
print 'finish encryption'
print 'total time:', t2 - t1
print 'time for each aes:', (t2 - t1) / len(block_list)
print 'num of aes per sec:', len(block_list) / (t2 - t1)
print 'try a whole file'
block = open('mediumdata').read()
print 'start encryption'
t1 = time.time()
num = random.randint(1, 65530)
nonce = "".join(chr((num >> (i * 8)) & 0xFF) for i in range(16))
backend = default_backend()
cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=backend)
encryptor = cipher.encryptor()
ciphertext = encryptor.update(block)# + encryptor.finalize()
encryptor.finalize()
t2 = time.time()
print 'finish encryption'
print 'total time:', t2 - t1
print 'time for each aes:', (t2 - t1) / len(block_list)
print 'num of aes per sec:', len(block_list) / (t2 - t1)
Did I miss anything here?
Is there a way that I can make method 1 faster?