使用AES / CBC / PKCS7Padding进行加密/解密 [英] Encryption/Decryption using AES/CBC/PKCS7Padding

查看:402
本文介绍了使用AES / CBC / PKCS7Padding进行加密/解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用AES / CBC / PKCS7Padding进行加密时,我需要帮助。我需要与此处相同的结果。

I need help in encrypting with AES/CBC/PKCS7Padding. I need the same results like here.

推荐答案

以下是使用流行的 cryptography 库。此代码改编自其文档。它使用问题中最初给出的数据,密钥和IV。

Here's how to do this task using the popular cryptography library. This code was adapted from their documentation. It uses the data, key, and IV that were initially given in the question.

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'






只是为了好玩,这里的实现不需要第3派对套餐。
通常,人们不会做这种事情,因为加密的第一个规则是不要自己滚加密!。但是,这是我作为Cryptopals挑战的一部分编写的一些AES代码。 ;)通过ctypes直接调用标准OpenSSL库来进行AES ECB编码,然后使用它来执行CBC加密/解密。


Just for fun, here's an implementation that requires no 3rd-party packages. Normally, one wouldn't do this sort of thing, since the first rule of crypto is "Don't roll your own crypto!". But here's some AES code I wrote as part of the Cryptopals challenge. ;) It does AES ECB encoding by directly calling the standard OpenSSL library via ctypes, and then uses that to perform CBC encryption / decryption.

此代码是在以下代码上开发和测试的运行Python 3.6.0的Linux系统,但它也应在Windows上运行。我认为它也可以在OSX上正常运行。

This code was developed and tested on a Linux system running Python 3.6.0, but it should also run on Windows. I assume it will also run correctly on 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'

这篇关于使用AES / CBC / PKCS7Padding进行加密/解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆