在使用AES / CBC / PKCS7Padding进行加密时,我需要帮助.我需要像here一样的结果.
解决方法:
这是使用流行的cryptography
库执行此任务的方法.此代码改编自其文档.它使用问题中最初提供的数据,密钥和IV.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
from base64 import b64decode, b64encode
backend = default_backend()
padder = padding.PKCS7(128).padder()
unpadder = padding.PKCS7(128).unpadder()
data = b'demo'
data = padder.update(data) + padder.finalize()
key = b64decode('HJkPmTz+uY7wd0p1+w//DABgbvPq9/230RwEG2sJ9mo=')
iv = b64decode('AAAAAAAAAAAAAAAAAAAAAA==')
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
encryptor = cipher.encryptor()
ct = encryptor.update(data) + encryptor.finalize()
ct_out = b64encode(ct)
print(ct_out)
decryptor = cipher.decryptor()
plain = decryptor.update(ct) + decryptor.finalize()
plain = unpadder.update(plain) + unpadder.finalize()
print(plain)
产量
b'W2FEImF2qrAjaJ/LV+bgQA=='
b'demo'
只是为了好玩,这是一个不需要第三方软件包的实现.
通常,人们不会做这种事情,因为加密的第一个规则是“不要自行加密!”.但是,这是我作为Cryptopals挑战的一部分编写的一些AES代码. ;)通过ctypes直接调用标准OpenSSL库来进行AES ECB编码,然后使用它来执行CBC加密/解密.
该代码是在运行Python 3.6.0的Linux系统上开发和测试的,但也应该在Windows上运行.我认为它也可以在OSX上正常运行.
import os
from base64 import b64decode, b64encode
from ctypes import *
AES_MAXNR = 14
AES_BLOCK_SIZE = 16
DECODE = 0
ENCODE = 1
class AES_KEY(Structure):
_fields_ = [
("rd_key", c_long * 4 *(AES_MAXNR + 1)),
("rounds", c_int),
]
crypto = cdll.LoadLibrary("libeay32.dll" if os.name == "nt" else "libssl.so")
# Function prototypes
AES_set_encrypt_key = crypto.AES_set_encrypt_key
AES_set_encrypt_key.restype = c_int
# userKey, bits, key
AES_set_encrypt_key.argtypes = [c_char_p, c_int, POINTER(AES_KEY)]
AES_set_decrypt_key = crypto.AES_set_decrypt_key
AES_set_decrypt_key.restype = c_int
# userKey, bits, key
AES_set_decrypt_key.argtypes = [c_char_p, c_int, POINTER(AES_KEY)]
AES_ecb_encrypt = crypto.AES_ecb_encrypt
AES_ecb_encrypt.restype = None
#in, out, key, enc(1=encode, 0=decode)
AES_ecb_encrypt.argtypes = [c_char_p, c_char_p, POINTER(AES_KEY), c_int]
set_key = (AES_set_decrypt_key, AES_set_encrypt_key)
def set_aes_key(key, encode):
''' Create an AES encoding or decoding key '''
keylen = len(key)
valid = {16, 24, 32}
if keylen not in valid:
msg = f'Key length must be one of {valid}, not {keylen}'
raise ValueError(msg)
aes_key = AES_KEY()
rc = set_key[encode](c_char_p(key), keylen * 8, byref(aes_key))
if rc != 0:
# I don't think we can get here...
raise ValueError('Error generating AES key', rc)
return aes_key
def aes_ecb(block, aes_key, encode):
''' Encrypt or decrypt a single block '''
outbuff = create_string_buffer(AES_BLOCK_SIZE)
AES_ecb_encrypt(c_char_p(block), outbuff, byref(aes_key), encode)
return outbuff.raw
def PKCS7_pad(data):
padsize = AES_BLOCK_SIZE - len(data) % AES_BLOCK_SIZE
return data + bytes([padsize]) * padsize
def PKCS7_unpad(data):
offset = data[-1]
return data[:-offset]
def xor_bytes(a, b):
size = len(a)
a = int.from_bytes(a, 'big')
b = int.from_bytes(b, 'big')
return (a ^ b).to_bytes(size, 'big')
def aes_cbc_encode(data, key, iv):
ekey = set_aes_key(key, ENCODE)
data = PKCS7_pad(data)
cipher = []
for block in zip(*[iter(data)] * AES_BLOCK_SIZE):
block = bytes(block)
coded = aes_ecb(xor_bytes(iv, block), ekey, ENCODE)
cipher.append(coded)
iv = coded
return b''.join(cipher)
def aes_cbc_decode(data, key, iv):
dkey = set_aes_key(key, DECODE)
plain = []
for block in zip(*[iter(data)] * AES_BLOCK_SIZE):
block = bytes(block)
decoded = aes_ecb(block, dkey, DECODE)
plain.append(xor_bytes(iv, decoded))
iv = block
plain[-1] = PKCS7_unpad(plain[-1])
return b''.join(plain)
# Test
data = b'demo'
key = b64decode('HJkPmTz+uY7wd0p1+w//DABgbvPq9/230RwEG2sJ9mo=')
iv = b64decode('AAAAAAAAAAAAAAAAAAAAAA==')
cipher = aes_cbc_encode(data, key, iv)
out = b64encode(cipher)
print(out)
plain = aes_cbc_decode(cipher, key, iv)
print(plain)
产量
b'W2FEImF2qrAjaJ/LV+bgQA=='
b'demo'