Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么我的带有逐块加密的python aes-ctr-128微基准测试速度慢?_Python_Aes_Microbenchmark - Fatal编程技术网

为什么我的带有逐块加密的python aes-ctr-128微基准测试速度慢?

为什么我的带有逐块加密的python aes-ctr-128微基准测试速度慢?,python,aes,microbenchmark,Python,Aes,Microbenchmark,我设计了一个拼图算法来获取每个加密块的值,这些值指向下一个要加密的块。出于某种特殊原因,我不得不使用aes-ctr-128 我运行一个虚拟测试,看看它有多快或多慢 这就是我所做的。我测试了pycrypto和密码学 我首先创建一个带有随机字节的16MB文件 我试过两种方法: 方法1。将文件加载到块大小为128位的块列表中 方法2。只需将文件加载到字符串中即可 现在我测试了加密每个128位块的总时间。我测试了加密整个文件的总时间 结果如下: pycrypto: 逐个加密128位块:每秒61824 a

我设计了一个拼图算法来获取每个加密块的值,这些值指向下一个要加密的块。出于某种特殊原因,我不得不使用aes-ctr-128

我运行一个虚拟测试,看看它有多快或多慢

这就是我所做的。我测试了pycrypto和密码学

我首先创建一个带有随机字节的16MB文件

我试过两种方法:

方法1。将文件加载到块大小为128位的块列表中

方法2。只需将文件加载到字符串中即可

现在我测试了加密每个128位块的总时间。我测试了加密整个文件的总时间

结果如下:

pycrypto:

  • 逐个加密128位块:每秒61824 aes-ctr-128

  • 加密整个文件:每秒8843713 aes-ctr-128

  • 密码学

  • 逐个加密128位块:每秒384959 aes-ctr-128

  • 加密整个文件:每秒113417922 aes-ctr-128

  • 我想知道为什么方法1和方法2给我的结果有这么大的差异?假设这两种方法的速度相同吗

    以下是我的测试代码:

    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)
    
    导入操作系统
    从cryptography.hazmat.primitives.ciphers导入密码、算法、模式
    从cryptography.hazmat.backends导入默认\u后端
    backend=默认值_backend()
    从Crypto.Cipher导入AES
    从Crypto.Util导入计数器
    随机输入
    导入时间
    块大小=16
    def read_块(fname):
    块列表=[]
    blobfo=打开(fname)
    atEOF=错误
    虽然不包括:
    blobdata=blobfo.read(块大小)
    block_list.append(blobdata)
    如果len(blobdata)<块大小:
    #我们应该在这之后停止。。。
    atEOF=真
    返回块列表
    打印“加载数据”
    块列表=读取块('mediumdata'))
    打印“加载完成”
    打印透镜(块列表),“块”
    打印“开始加密”
    NUM_计数器_位=128
    #这里我只使用一个随机键
    key=os.uradom(16)
    t1=时间。时间()
    对于块列表中的块:
    ctr=计数器。新(计数器位数)
    密码=AES.new(密钥,AES.MODE\u CTR,计数器=CTR)
    加密(块)
    t2=时间。时间()
    打印“完成加密”
    打印“总时间:”,t2-t1
    打印“每个aes的时间:”,(t2-t1)/len(块列表)
    打印“每秒不良事件数:”,len(块列表)/(t2-t1)
    打印“现在尝试加密整个文件”
    block=open('mediumdata')。read()
    打印类型(块)
    打印“开始加密”
    NUM_计数器_位=128
    key=os.uradom(16)
    t1=时间。时间()
    ctr=计数器。新(计数器位数)
    密码=AES.new(密钥,AES.MODE\u CTR,计数器=CTR)
    加密(块)
    t2=时间。时间()
    打印“完成加密”
    打印“总时间:”,t2-t1
    打印“每个aes的时间:”,(t2-t1)/len(块列表)
    打印“每秒不良事件数:”,len(块列表)/(t2-t1)
    打印“现在尝试加密”
    打印“开始加密”
    t1=时间。时间()
    num=random.randint(165530)
    nonce=“”.join(chr((num>>(i*8))&0xFF)表示范围(16)内的i)
    backend=默认值_backend()
    cipher=cipher(algorithms.AES(key)、modes.CTR(nonce)、backend=backend)
    encryptor=cipher.encryptor()
    对于块列表中的块:
    密文=加密程序。更新(块)
    encryptor.finalize()
    t2=时间。时间()
    打印“完成加密”
    打印“总时间:”,t2-t1
    打印“每个aes的时间:”,(t2-t1)/len(块列表)
    打印“每秒不良事件数:”,len(块列表)/(t2-t1)
    打印“尝试整个文件”
    block=open('mediumdata')。read()
    打印“开始加密”
    t1=时间。时间()
    num=random.randint(165530)
    nonce=“”.join(chr((num>>(i*8))&0xFF)表示范围(16)内的i)
    backend=默认值_backend()
    cipher=cipher(algorithms.AES(key)、modes.CTR(nonce)、backend=backend)
    encryptor=cipher.encryptor()
    密文=encryptor.update(block)#+encryptor.finalize()
    encryptor.finalize()
    t2=时间。时间()
    打印“完成加密”
    打印“总时间:”,t2-t1
    打印“每个aes的时间:”,(t2-t1)/len(块列表)
    打印“每秒不良事件数:”,len(块列表)/(t2-t1)
    
    我错过什么了吗


    有没有办法使方法1更快?

    AES是一种具有多轮置换的分组密码。每一轮都有自己的轮键,需要从“主”键(代码中的
    key
    )派生。调用
    AES.new(key,mode,…)
    将自动派生圆键,但是这个键调度过程相当繁重。与一次调用方法相比,为每个块执行密钥调度将大大降低处理速度,特别是在实际加密代码使用AES-NI指令集的情况下

    此外,正如kennytm在文章中指出的,Python是一种解释语言,因此在Python中迭代块而不是底层本机加密代码(例如,pyCrypto使用C库tomcrypt)必然会导致额外的性能损失


    方法1的代码被破坏,因为您正在为每个块创建一个新的计数器对象,它总是初始化为
    1
    。因此,您使用相同的密钥流对每个块进行异或运算,这会创建一个密钥流,并可能使攻击者推断出明文

    我们可以通过只有一个计数器对象来解决这个问题。同时拥有一个单键时间表可以显著提高性能

    改进的方法1代码:

    ctr = Counter.new(NUM_COUNTER_BITS)
    cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
    for block in block_list:
        cipher.encrypt(block)
    
    pyCrypto的结果:

    1049887 blocks Method 1 total time: 17.31999993324279785156 time for each aes: 1.64970134245e-05 num of aes per sec: 60617.0325662 Improved Method 1 total time: 0.78299999237060546875 time for each aes: 7.45794540146e-07 num of aes per sec: 1340851.86492 Method 2 total time: 0.147000074387 time for each aes: 1.4001513914e-07 num of aes per sec: 7142084.82126 1049887座 方法1 总时间:17.3199939324279785156 每次aes的时间:1.64970134245e-05 每秒不良事件数:60617.0325662 改进方法1 总时间:0.7829999237060546875 每次aes的时间:7.45794540146e-07 每秒不良事件数:1340851.86492 方法2 总时间:0.147000074387 每次aes的时间:1.4001513914e-07 每秒不良事件数:7142084.82126

    AES是一种具有多轮置换的分组密码。每一轮都有自己的轮键,需要从“主”键(代码中的
    key
    )派生。愈伤组织