使用 AES/CBC/PKCS7Padding 加密/解密

用户1318741

我需要使用 AES/CBC/PKCS7Padding 进行加密的帮助。我需要像这里一样的结果

PM 2环

以下是如何使用流行的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'

只是为了好玩,这里有一个不需要 3rd-party 包的实现。通常情况下,人们不会做这种事情,因为加密的第一条规则是“不要推出自己的加密!”。但这是我在 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'

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用mcrypt加密/解密

来自分类Dev

使用加密加密后无法解密数据

来自分类Dev

使用Java的RSA加密/解密

来自分类Dev

无法使用加密解密cryptocurrencyValue

来自分类Dev

在iOS中使用AES / CBC / PKCS7Padding 128位算法在Android中加密的解密字符串的问题

来自分类Dev

Delphi 7-使用DEC加密,然后使用PHP OpenSSL解密

来自分类Dev

使用CryptoJS加密并使用PHP解密

来自分类Dev

使用CryptoJS加密数据并使用AESCipherService解密

来自分类Dev

使用Jasypt加密和解密密码

来自分类Dev

使用ZipArchive类进行加密/解密

来自分类Dev

使用AES算法进行加密和解密

来自分类Dev

使用密码算法加密解密显示错误

来自分类Dev

使用Java进行AES加密和解密

来自分类Dev

使用C ++进行加密和解密

来自分类Dev

使用Rijndael的不同Delphi / PHP加密-解密

来自分类Dev

使用SIP TLS进行加密/解密

来自分类Dev

使用iOS加密;用.Net解密

来自分类Dev

使用Android和PHP加密/解密

来自分类Dev

使用Jasypt加密和解密密码

来自分类Dev

如何使用Qt加密/解密/播放视频?

来自分类Dev

使用Spring Security进行AES加密/解密

来自分类Dev

使用LuaJit进行FFI加密/解密

来自分类Dev

如何使用OpenSSL解密加密的私钥?

来自分类Dev

使用RSA OAEP加密和解密

来自分类Dev

使用新的 php 版本加密解密问题

来自分类Dev

无法在 Nodejs 中使用加密模块解密

来自分类Dev

使用加密與解密的身份驗證

来自分类Dev

如何使用openssl解密加密文件?

来自分类Dev

OpenSSL加密/解密仅解密前7个左右的字符?