>我正在使用以下AES密码实现:-
import hashlib
from Crypto.Cipher import AES
class AESCipher:
def __init__(self, key):
self.BS = 128
try:
self.key = hashlib.sha256(key.encode()).digest()[:self.BS]
except:
self.key = hashlib.sha256(key).digest()[:self.BS]
self.iv = Random.new().read(AES.block_size)
def encrypt(self, raw):
raw = self._pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return base64.b64encode(self.iv + cipher.encrypt(raw))
def decrypt(self, enc):
enc = base64.b64decode(enc)
self.iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode()
def _pad(self, s):
return s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS).encode()
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
二进制编码字典对象的加密不会导致错误,但是当我尝试解密相同的加密对象时,会引发以下异常:-
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode()
builtins.UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte
我尝试使用"ISO"和"拉丁"编码和解码功能。但在那之后,局域网另一端的套接字将其识别为字符串而不是字典对象。
我的问题:- 我在这里做错了什么?
附加信息 :-
key = 'SHSJDS-DSJBSJDS-DSKNDS' # some thing following this pattern
bin_json_object = pickle.dumps(dict_object)
enc_json_object = AESenc(bin_json_object, key)
def AESenc(self, data, key):
return AESCipher(key).encrypt(data)
def AESdec(self, data, key):
return AESCipher(key).decrypt(data)
例如,如果我在上面的代码中使用"ISO-8859-1"编码:-
字典对象的二进制编码表示:-
b'x80x03}qx00(Xx02x00x00x00idqx01X$x00x00x0096e09f6c-1e80-4cd1-9225-159e35bcacb4qx02Xx0cx00x00x00request_codeqx03Kx01Xx0ex00x00x00payload_lengthqx04K!Xx0bx00x00x00session_keyqx05Nu.'
二进制编码字典对象的加密表示:-
b'cZi+L4Wi51B5oDGQKlFb9bioxKH3TFRO1piECklafwTe6GYm/VeVjJaCDKiI+o6f6CcUnMvx+2EfEwcHCH/KDDeHTivIUou7WGVrd1P++HxfYNutY/aOn30Y/yiICvwWRHBn/3zU3xXvr/4XrtoVddM2cQEgXupIcC99TIxurrr8CCZd74ZnWj6QB8quCtHD'
但是,如果我现在尝试通过套接字在同一 LAN 上的其他节点上解密相同的内容。我得到以下解密表示:-
}q(XidqX$96e09f6c-1e80-4cd1-9225-159e35bcacb4qX
request_codeqKXpayload_lengthqK!X
session_keyqNu.
这与同一字典对象的原始二进制表示形式完全不同。并产生以下异常:-
data = pickle.loads(data)
builtins.TypeError: 'str' does not support the buffer interface
经过数小时的调试,我得到了一个工作代码,但我无法理解为什么它会起作用。如果有人可以在评论中解释这一点,请。修改版AES密码:-
class AESCipher:
def __init__(self, key):
self.BS = AES.block_size
try:
self.key = hashlib.sha256(key.encode('ISO-8859-1')).digest()[:self.BS]
except:
self.key = hashlib.sha256(key).digest()[:self.BS]
self.iv = Random.new().read(AES.block_size)
def encrypt(self, raw):
raw = self._pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return base64.b64encode(self.iv + cipher.encrypt(raw))
def decrypt(self, enc):
enc = base64.b64decode(enc)
self.iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('ISO-8859-1')
def _pad(self, s):
return s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS).encode('ISO-8859-1')
@staticmethod
def _unpad(s):
print('returning : ', s[:-ord(s[len(s)-1:])])
return s[:-ord(s[len(s)-1:])]
现在无需修改 AES 加密和解密功能。我在代码中引入了以下变体。每当另一个节点收到二进制流时,它首先使用 AES 解密功能对其进行解密。但是在解密后,编码的字典对象必须使用"ISO-8859-1"再次编码,如下所示:-
dict_object = self.AESdecryption(binary_stream, self.session_key)
dict = pickle.loads(dict_object.encode('ISO-8859-1'))
print(dict)
上面生成正确的字典对象。但我不明白的是,当字典对象以"ISO-8859-1"编码加密,然后以"ISO-8859-1"编码在其他节点上解密时,那么为什么在将其传递给 pickle.loads(( 之前,我必须再次对其进行编码才能获得原始字典对象。请问有人可以解释为什么会发生这种情况?