Python Pycrypto:递增CTR模式

Python Pycrypto:递增CTR模式,python,aes,encryption,pycrypto,Python,Aes,Encryption,Pycrypto,还是没法让它发挥作用。我的问题是如何使解密行工作。以下是我写的: class IVCounter(object): @staticmethod def incrIV(self): temp = hex(int(self, 16)+1)[2:34] return array.array('B', temp.decode("hex")).tostring() def decryptCTR(key, ciphertext): iv = ci

还是没法让它发挥作用。我的问题是如何使解密行工作。以下是我写的:

class IVCounter(object):
    @staticmethod
    def incrIV(self):
        temp = hex(int(self, 16)+1)[2:34]
        return array.array('B', temp.decode("hex")).tostring()


def decryptCTR(key, ciphertext):

    iv = ciphertext[:32] #extracts the first 32 characters of the ciphertext

    #convert the key into a 16 byte string
    key = array.array('B', key.decode("hex")).tostring()

    print AES.new(key, AES.MODE_CTR, counter=IVCounter.incrIV(iv)).decrypt(ciphertext)
    return
我的错误消息是:

ValueError:“计数器”参数必须是可调用对象

我就是搞不懂pycrypto想让我如何将第三个参数组织成新的

有人能帮忙吗?谢谢

编辑 在实现了下面的建议后,将生成新代码。还是卡住了

class IVCounter(object):
    def __init__(self, start=1L):
        print start #outputs the number 1 (not my IV as hoped)
        self.value = long(start)

   def __call__(self):
        print self.value  #outputs 1 - need this to be my iv in long int form
        print self.value + 1L  #outputs 2
        self.value += 1L
        return somehow_convert_this_to_a_bitstring(self.value) #to be written

def decryptCTR(key, ciphertext):

    iv = ciphertext[:32] #extracts the first 32 characters of the ciphertext
    iv = int(iv, 16)

    #convert the key into a 16 byte string
    key = array.array('B', key.decode("hex")).tostring()

    ctr = IVCounter()
    Crypto.Util.Counter.new(128, initial_value = iv)

    print AES.new(key, AES.MODE_CTR, counter=ctr).decrypt(ciphertext)
    return
编辑仍无法使其正常工作。非常沮丧,完全没有想法。下面是最新的代码:(请注意,我的输入字符串是32位十六进制字符串,必须以两位数对进行解释才能转换为长整数。)

TypeError:CTR计数器函数返回的字符串长度不是16


在Python中,将函数视为对象是完全有效的。将任何定义
\uuuuu call\uuuu(self,…)
的对象视为函数也是完全有效的

所以你想要的可能是这样的:

class IVCounter(object):
    def __init__(self, start=1L):
        self.value = long(start)
    def __call__(self):
        self.value += 1L
        return somehow_convert_this_to_a_bitstring(self.value)

ctr = IVCounter()
... make some keys and ciphertext ...
print AES.new(key, AES.MODE_CTR, counter=ctr).decrypt(ciphertext)
但是,PyCrypto为您提供了一种计数器方法,它应该比纯Python快得多:

import Crypto.Util.Counter
ctr = Crypto.Util.Counter.new(NUM_COUNTER_BITS)
ctr
现在是一个有状态函数(同时也是一个可调用对象),每次调用它时都会递增并返回其内部状态。然后你就可以做了

print AES.new(key, AES.MODE_CTR, counter=ctr).decrypt(ciphertext)
和以前一样

下面是一个在CTR模式下使用Crypto.Cipher.AES和用户指定的初始化向量的工作示例:

import Crypto.Cipher.AES
import Crypto.Util.Counter

key = "0123456789ABCDEF" # replace this with a sensible value, preferably the output of a hash
iv = "0000000000009001" # replace this with a RANDOMLY GENERATED VALUE, and send this with the ciphertext!

plaintext = "Attack at dawn" # replace with your actual plaintext

ctr = Crypto.Util.Counter.new(128, initial_value=long(iv.encode("hex"), 16))

cipher = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CTR, counter=ctr)
print cipher.encrypt(plaintext)

当然可以在CTR模式下,初始化向量只是计数器的初始值。如果要将特定IV传递给正在创建的计数器,只需执行ctr=Crypto.Util.counter.new(NUM_counter_BITS,initial_value=9000001L),其中initial_value是长整数形式的IV。我们之所以认为CTR是有状态函数的原因是因为它在内部存储了自己的计数器。每次调用
ctr()
,其内部计数器都会递增1。因此,通过用IV初始化这个函数,然后你就增加了你的IV。如果你看我的例子,而不是很理解它,可调用对象(把它看作C++函数)可以在初始化时采取一个参数“开始”;然后,它自己的内部计数器被设置为您想要的任何值。每次调用
IVCounter
的特定实例时,它自己的内部计数器(已初始化)都会递增。原则上,您可以定义多个
IVCounter
实例,它们都是相互独立的。当然可以@usr55410。当前代码有两个问题:初始化变量
iv
后,不使用该变量;如果您正在使用my IVCounter,您需要说
ctr=IVCounter(long(iv))
或类似的话来设置计数器的初始状态。如果您使用的是Crypto.Util.Counter(速度首选),您需要说
ctr=Crypto.Util.Counter.new(256,long(iv))
。第二个问题(前面也解决了这个问题)是Crypto.Util.Counter.new返回一个函数,您不会在任何地方分配它。另外,请注意另一件事:PyCrypto的加密例程期望(并返回)bytestring,在加密形式下,它肯定无法远程读取。您需要了解如何将字符串转换为十六进制表示形式,以及如何将字符串转换为十六进制表示形式;这不是一个很难解决的问题,例如在。还有最后一件事:由于您通常希望iv是长的(比int通常提供的长得多),因此您需要使用
long()
来声明iv,而不是
int()
。1:我的密钥字符串是二进制数据;我的IV字符串是一个十六进制字符串(例如
baadf00d
)。2:解密前需要重置计数器,即使用相同的IV创建一个新计数器,然后使用新计数器创建一个新密码上下文,并使用该计数器进行解密。
import Crypto.Cipher.AES
import Crypto.Util.Counter

key = "0123456789ABCDEF" # replace this with a sensible value, preferably the output of a hash
iv = "0000000000009001" # replace this with a RANDOMLY GENERATED VALUE, and send this with the ciphertext!

plaintext = "Attack at dawn" # replace with your actual plaintext

ctr = Crypto.Util.Counter.new(128, initial_value=long(iv.encode("hex"), 16))

cipher = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CTR, counter=ctr)
print cipher.encrypt(plaintext)