Шифрование / дешифрование с использованием AES / CBC / PKCS7Padding

Мне нужна помощь в шифровании с помощью AES / CBC / PKCS7Padding. Мне нужны такие же результаты, как Вот.

-5

Решение

Вот как это сделать, используя популярные 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'

Просто для удовольствия, вот реализация, которая не требует сторонних пакетов.
Как правило, никто не будет делать такого рода вещи, так как первое правило крипто: «Не бросайте свой собственный крипто!». Но вот некоторый код AES, который я написал как часть проблемы Cryptopals. 😉 Он выполняет кодирование AES ECB, напрямую вызывая стандартную библиотеку OpenSSL через ctypes, а затем использует ее для выполнения шифрования / дешифрования CBC.

Этот код был разработан и протестирован в системе Linux с Python 3.6.0, но он также должен работать и в 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'
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector