我在Ubuntu 16.04上使用Python2.7和pycryptodome 3.6.6和Golang1.10.4。
我选择的加密算法是AES-CTR-128。但是由Python和Golang加密的数据有不同的结果。因此,在这两种语言编写的应用程序之间进行通信存在问题。
这是我的实现:
蟒:
#coding=utf-8
from __future__ import absolute_import
import binascii
from Crypto.Cipher import AES
from Crypto.Util import Counter
def hexlify(binary):
return binascii.hexlify(binary)
class AES_CTR(object):
def __init__(self, key, iv):
assert len(key) == 16
assert len(iv) == 16
ctr = Counter.new(128)
self.aes = AES.new(key, AES.MODE_CTR, counter=ctr)
def encrypt(self, plain_data):
return self.aes.encrypt(plain_data)
def decrypt(self, encrypted_data):
return self.aes.decrypt(encrypted_data)
if __name__ == '__main__':
aes = AES_CTR('abcdef0123456789', '0123456789abcdef')
print hexlify(aes.encrypt("hello")) #print '9b1a038478'
print hexlify(aes.encrypt("hello")) #print '8751ea0448'
print hexlify(aes.encrypt("world")) #print 'b6aa7c286b'
戈朗
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
)
type AESCipher struct {
iv []byte
stream cipher.Stream
}
func NewAESCipher(key []byte, iv []byte) *AESCipher {
if (len(iv) != 16 || len(key) != 16) {
panic("iv length or key length error")
}
block, err := aes.NewCipher(key)
if (err != nil) {
panic(err)
}
return &AESCipher {
iv: iv,
stream: cipher.NewCTR(block, iv),
}
}
func (cipher *AESCipher) Encrypt(buffer []byte) []byte {
encrypted := make([]byte, len(buffer))
cipher.stream.XORKeyStream(encrypted, buffer)
return encrypted
}
func (cipher *AESCipher) Decrypt(buffer []byte) []byte {
decrypted := make([]byte, len(buffer))
cipher.stream.XORKeyStream(decrypted, buffer)
return decrypted
}
func main() {
iv := []byte("0123456789abcdef")
key := []byte("abcdef0123456789")
cipher := NewAESCipher(key, iv)
encrypted1 := cipher.Encrypt([]byte("hello"))
fmt.Println(hex.EncodeToString(encrypted1)) // print '94ee8ac46a'
encrypted2 := cipher.Encrypt([]byte("hello"))
fmt.Println(hex.EncodeToString(encrypted2)) // print 'b36d48ad7e'
encrypted3 := cipher.Encrypt([]byte("world"))
fmt.Println(hex.EncodeToString(encrypted3)) // print '7302071a9c'
}
问题解决了。
接受这个答案,pycryptodome的默认实现是不正确的。我们可以更改Counter
以使其按预期工作。
ctr = Counter.new(128, initial_value=bytes_to_long(iv))
现在它完美运行。
你可以通过根本不使用 Counter
类来简化你的代码,这里记录了:
self.aes = AES.new(key, AES.MODE_CTR, initial_value=iv)
试试这个:
ctr = Counter.new(128, initial_value= int.frombytes(iv.encode(),'little'))
IV 始终作为整数值和字节格式的键传递。从上述链接中检查文档