用python编写AES-CTR解密例程

时间:2018-11-12 20:14:33

标签: python cryptography aes ctr-mode

我有以下代码

func encrypt(key, data string) (string, error) {
    byteKey := []byte(key)
    plaintext := []byte(data)

    block, err := aes.NewCipher(byteKey)
    if err != nil {
        return "", err
    }
    ciphertext := make([]byte, len(plaintext))
    stream := cipher.NewCTR(block, byteKey[aes.BlockSize:])
    stream.XORKeyStream(ciphertext, plaintext)
    return base64.StdEncoding.EncodeToString(ciphertext), nil
}

byteKey = []byte("4e8f1670f502a3d40717709e5f80d67c") (不确定语法是否正确,但这是十六进制的关键。)

我的任务是用任何一种语言编写解密例程,这是我到目前为止所要做的:

import base64
from Crypto.Cipher import AES

def decrypt(ct):
        key = '4e8f1670f502a3d40717709e5f80d67c'.decode('hex')
        nonce = 0
        ct1 = base64.b64decode(ct)
        cipher = AES.new(key, mode=AES.MODE_CTR, counter=lambda: nonce)
        print str(cipher.decrypt(ct1))

我做错了什么,我只是不知道是什么。请专家帮忙吗?预先感谢。

1 个答案:

答案 0 :(得分:2)

提示:考虑计数器模式如何工作。您的代码中的初始计数器值是多少,后续值是什么?他们应该是什么?


counter=lambda: nonce

这是一个常数函数,始终返回相同的值,该值在程序中为0。但这不是您需要传递给counter的东西:您需要传递一个函数,该函数每次调用时都会返回当前计数器值。例如,如果初始计数器值为0,则此函数必须在首次调用时返回0,在第二次调用时返回1,在第二次调用时返回2,以此类推。更准确地说,它必须返回'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',然后返回{{ 1}}等。

此处的Python接口设计不良。它过于灵活,但是这种灵活性在实践中从没有用过,因此很难正确使用API​​。此外,documentation根本不清楚:

  

'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'(可调用)-(仅MODE_CTR)。返回下一个计数器块的有状态函数,该计数器块是counter个字节的字节串。为了获得更好的性能,请使用Crypto.Util.Counter

实际上,您非常需要使用block_size来使用Crypto.Util.Counter,不仅仅是为了“性能”,而且只是为了使计算正确。别难过:您不是第一个尝试过这个的人。

面对一个您可能不知道的API,接下来您可能会转向Stack Overflow…,这个问题已经在PyCrypto problem using AES+CTR处得到了回答,但是请注意,这个问题已经有7年没有了。正确的答案,尽管有一个被认可和接受的答案。我的答案显示了如何使用MODE_CTRcounter

第二个问题可能是初始计数器值。为点击率模式选择初始计数器值的主要策略有两种:

  • 对于一次性密钥,请从0开始,并且因为它是众所周知的常数,所以不要随消息一起发送ICV。
  • 对于多次使用的密钥,每次生成一个随机值,然后在密文的开头发送ICV。

我对您发布的加密代码中的API不熟悉。但是,由于它返回的密文长度与明文长度相同,因此它可能使用恒定的ICV(对于一次性密钥来说是好的,但如果密钥被重用则会带来灾难性的后果),很可能为0。仍然,请查阅该文档API。

(如果您需要进一步的编码帮助,请在Stack Overflow而不是Cryptography上提问,因为编码问题不在Cryptography.SE上。并且请务必发布complete code to reproduce the problem,包括输入和输出。)