python自己本身的AES解密实现起来没有问题,但是跟java适配就会出现问题,下面整理一下实现过程中出现的几个问题和代码:
一. 字符串
1.1 加密
1. 使用的是Crypto.Cipher.AES的加密包,
iv = b’1234567890123456’,secret_key = b"0(^v91195]'C6_8
]h>1[:P<,}dm#"
2. 加密前需要补全16位,比如字符串13位,后面补的就是“\03\03\03”
3. 加密是需要是bytes,cipher0.encrypt(fdata),fdata是bytes
4. 加密后需要用base64编码:base64.b64encode(enc_bytes)
代码如下:
def encrypt_str(self, src_str, secret_key):
"""encrypt string function.
Args:
src_str: plaintext string, bytes/str
public_key: AES public key, bytes
secret_key: AES secret key, bytes
Reutrns:
enc_str: encrypted string, bytes
"""
if isinstance(src_str, str):
src_str = src_str.encode('utf-8')
assert isinstance(src_str, bytes)
public_key = self.PUBLIC_KEY
# instantiate AES cipher
cipher0 = AES.new(secret_key, AES.MODE_CFB, public_key, segment_size=128)
fdata = self.__pad(src_str)
enc_bytes = cipher0.encrypt(fdata)
enc_bytes = base64.b64encode(enc_bytes)
return enc_bytes
1.2 解密
1. 使用的是Crypto.Cipher.AES的加密包,
iv = b’1234567890123456’,secret_key = b"0(^v91195]'C6_8
]h>1[:P<,}dm#"
2. 用base64解码,base64.b64decode(enc_bytes)
3. 解密是需要是bytes,cipher0.decrypt(fdata),fdata是bytes
4. 解密是需要将加密时补的内容去除:src_data[:-ord(src_data[-1:])]
代码如下:
def decrypt_str(self, enc_bytes, secret_key):
"""decrypt string function.
Args:
enc_bytes: plaintext string, bytes
secret_key: AES secret key, bytes
Return:
dec_bytes: decrypted string, bytes
"""
if isinstance(enc_bytes, str):
enc_bytes = enc_bytes.encode('utf-8')
assert isinstance(enc_bytes, bytes)
aes_public_key = self.AES_PUBLIC_KEY
decipher0 = AES.new(secret_key, AES.MODE_CFB, aes_public_key, segment_size=128)
enc_bytes = base64.b64decode(enc_bytes)
dec_bytes = decipher0.decrypt(enc_bytes)
dec_bytes = self.__unpad(dec_bytes)
return dec_bytes
二. 文件
2.1 加密
1. 加密的步骤如字符串
2. 文件存在读取问题,如果文件过大,一次性将文件读入内存会出现问题,
所以我们需要将文件分批读取
3. 加密时buffer_size = 16
×
\times
× 3
×
\times
× 1024
16 AES加密需要;3 base64编码需要;1024这个随意设置即可
代码如下:
def __encrypt_stream_batchs(self, file_in, file_out, public_key, secret_key, input_length):
"""encrypt binary stream function.
Args:
file_in: input binary stream
file_out: output binary stream
public_key: AES public key
secret_key: AES secret key
"""
BUFFER_SIZE = self.ENCRYPT_BUFFER_SIZE
AES_BLOCK_SIZE = self.AES_BLOCK_SIZE
# validate bufferSize
if BUFFER_SIZE % AES_BLOCK_SIZE != 0:
raise ValueError("Buffer size must be a multiple of AES block size.")
# instantiate AES cipher
encryptor0 = AES.new(secret_key, AES.MODE_CFB, public_key, segment_size=128)
# encrypt file while reading it
read_file_size = 0
while read_file_size < input_length:
# try to read BUFFER_SIZE bytes
fdata = file_in.read(BUFFER_SIZE)
bytes_read = len(fdata)
read_file_size += bytes_read
if bytes_read < BUFFER_SIZE:
fdata = self.__pad(fdata)
cText = encryptor0.encrypt(fdata)
cText = base64.b64encode(cText)
file_out.write(cText)
1.2 解密
1. 解密的步骤如字符串解密
2. 文件存在读取问题,需要将文件分批读取
3. 加密时buffer_size = 16
×
\times
× 4
×
\times
× 1024
16 AES解密需要;4 base64解码需要;1024这个随意设置即可
代码如下:
def __decrypt_stream_batchs(self, file_in, file_out, public_key, secret_key, input_length):
"""encrypt binary stream function.
Args:
file_in: input binary stream,str
file_out: output binary stream,str
public_key: AES public key,16 bits
secret_key: AES secret key,16 bits
input_length: input stream length,int
"""
BUFFER_SIZE = self.DECRYPT_BUFFER_SIZE
AES_BLOCK_SIZE = self.AES_BLOCK_SIZE
# validate bufferSize
if BUFFER_SIZE % AES_BLOCK_SIZE != 0:
raise ValueError("Buffer size must be a multiple of AES block size")
# instantiate another AES cipher
decryptor0 = AES.new(secret_key, AES.MODE_CFB, public_key, segment_size=128)
# 处理BUFFER_SIZE数据
while file_in.tell() < input_length - BUFFER_SIZE:
cText = file_in.read(BUFFER_SIZE)
cText = base64.b64decode(cText)
file_out.write(decryptor0.decrypt(cText))
# 处理剩余数据
cText = bytes()
if file_in.tell() != input_length:
cText = file_in.read(BUFFER_SIZE)
cText = base64.b64decode(cText)
if len(cText) % AES_BLOCK_SIZE != 0:
raise ValueError("File is corrupted.")
# decrypt last block
de_text = decryptor0.decrypt(cText)
de_text = self.__unpad(de_text)
file_out.write(de_text)
完整代码见我上传的资源:
https://download.csdn.net/download/peach_orange/11824472