Python 3DES CBC 模式加密解密
3DES 加密
def des3_cbc_encrypt(secret_key, secret_value, iv): """ 3DES CBC 加密算法 :param secret_key: 加密的密钥长度24位,不足补0,超过24位,截取前24位 :param secret_value:加密串不是8的倍数,用空格补全成8的倍数 :param iv: 长度为8偏移量 :return: """ length = DES3.block_size secret_value = secret_value + (length - len(secret_value) % length) * chr(length - len(secret_value) % length) if len(secret_key) > 24: # 长度大于24 截取前24位 secret_key = secret_key[0:24] else: # 不足24位进行0补全 secret_key = secret_key + '\0' * (24 - len(secret_key) % 24) res = DES3.new(secret_key.encode("utf-8"), DES3.MODE_CBC, iv) ciphertext = res.encrypt(secret_value.encode("utf-8")) return base64.b64encode(ciphertext).decode("utf-8")
加密中文时,如果先将加密字符串补齐8的倍数,再次加密时转成字节以后长度就会不等于8的倍数,因为utf-8编码一个汉字占三个字节导致,所以补全时需要先转码再去判断是否需要补全;
将上述代码优化为
def des3_cbc_encrypt(secret_key, secret_value, iv): """ 3DES CBC 加密算法 :param secret_key: 加密的密钥长度24位,不足补0,超过24位,截取前24位 :param secret_value:加密串不是8的倍数,用空格补全成8的倍数 :param iv: 长度为8偏移量 :return: """ length = DES3.block_size print(len(secret_value.encode("utf-8"))) encode_secret_value = secret_value.encode("utf-8") # 先编码再次去判断是否补全 secret_value = secret_value + (length - len(encode_secret_value) % length) * chr( length - len(encode_secret_value) % length) if len(secret_key) > 24: # 长度大于24 截取前24位 secret_key = secret_key[0:24] else: # 不足24位进行0补全 secret_key = secret_key + '\0' * (24 - len(secret_key) % 24) res = DES3.new(secret_key.encode("utf-8"), DES3.MODE_CBC, iv) ciphertext = res.encrypt(secret_value.encode("utf-8")) return base64.b64encode(ciphertext).decode("utf-8")
3DES解密
def des3_cbc_decrypt(secret_key, secret_value, iv): """ 3DES CBC 解密算法 :param secret_key: 加密的密钥长度24位,不足补0,超过24位,截取前24位 :param secret_value:加密串不是8的倍数,用空格补全成8的倍数 :param iv: 长度为8偏移量 :return: """ unpad = lambda s: s[0:-ord(s[-1])] if len(secret_key) > 24: secret_key = secret_key[0:24] else: secret_key = secret_key + '\0' * (24 - len(secret_key) % 24) res = DES3.new(secret_key.encode("utf-8"), DES3.MODE_CBC, iv) base64_decrypted = base64.b64decode(secret_value.encode("utf-8")) encrypt_text = res.decrypt(base64_decrypted) result = unpad(encrypt_text.decode())return result
注意:
iv 需要转换成字节或者字节数组
# 转换成字节数组 bytearray([1, 2, 3, 4, 5, 9, 7, 8]) # 转换成字节 第①种 s =b"1234567890" 第②种 bytes("1234567890", encoding="utf8") 第③种 "1234567890".encode("utf8")