Python usa Crypto para descriptografia AES e criptografia de arquivos

 Prefácio : Ao escrever um programa hoje:

Modo de criptografia: AES/CBC/PKCS5Padding
Vetor de inicialização de criptografia: Matriz de bytes vazia com comprimento 16

Eu nunca entendi como representar uma matriz de bytes vazia com um comprimento de 16

Aí usei o modo ECB e descobri que a senha era a mesma do exemplo que ele deu, e a cabeça era grande.

Contexto : Para necessidades de trabalho, alguns dados são criptografados para transmissão e a outra parte usa AES para criptografar a senha, e os dados descriptografados precisam ser obtidos.
Objetivo : Descriptografar com sucesso um arquivo com uma chave.
Palavras-chave : AES_ECB, AES_CBC, problemas de criptografia AES em Java e Python,

criptografia AES


1. Problemas encontrados

Receba a chave e o arquivo criptografado da seguinte maneira. Uma chave é necessária para descriptografar as informações.
Dados conhecidos por serem criptografados com AES

key = 'Fcniggersm'
message = 'gYknrv3zMWYXEpRLDL0n8q+6s68DKapAfRpBDhN1XGM='

Descriptografar endereço de teste


2. Introdução ao Algoritmo AES

Explicação detalhada do algoritmo AES : Advanced Encryption Standard, que é um algoritmo de criptografia simétrico, o AES possui apenas uma chave, que é usada para criptografia e descriptografia.

Existem cinco métodos de criptografia AES: ECB , CBC , CTR, CFB, OFB.
O método de criptografia CBC é recomendado do ponto de vista da segurança. Este artigo apresenta a implementação Python dos métodos de criptografia CBC e ECB.

A criptografia CBC requer uma chave de dezesseis dígitos (chave) e uma criptografia de dezesseis dígitos iv (offset)
ECB não requer iv

Os dados recebidos possuem apenas chaves e nenhum deslocamento. Portanto, o ECB é usado para processar o texto cifrado.


3. Preparação

python Ao usar o AES no Windows, você precisa instalar o módulo pycryptodome
python Ao usar o AES no Linux, você precisa instalar o módulo pycrypto

import base64
from Crypto.Cipher import AES
from Crypto import Random
import os
import base64
import json

4. Descriptografia e Criptografia AES-ECB

1. Processamento de chaves

O processamento direto da chave relatará um erro: 'A chave AES deve ter 16, 24 ou 32 bytes de comprimento'
porque a chave&vi recebida pelo AES deve ter um comprimento fixo.
Preencha a Chave até que ela atenda à especificação.

def add_to_16(text):
    while len(text) % 16 != 0:
        text += '\0'
    return (text)

key = 'Fcniggersm'
key = add_to_16(key) 

2. Processamento de texto cifrado

É possível que seja reportado um erro ao processar o texto cifrado: 'Erro: Preenchimento incorreto'.
Isso ocorre porque o comprimento do texto cifrado não atende às especificações. Basta preencher a string decodificada por base64 com um sinal de igual.

def decode_base64(data):
    missing_padding = 4-len(data)%4
    if missing_padding:
        data += b'='*missing_padding
    return (data)

message = 'gYknrv3zMWYXEpRLDL0n8q+6s68DKapAfRpBDhN1XGM='
encrypt_data = message 
encrypt_data = decode_base64(encrypt_data)

3. Processamento de descriptografia

A descriptografia obtém com sucesso um e, em seguida, decodifica um para obter dados.

cipher = AES.new(key)
result2 = base64.b64decode(encrypt_data)
a = cipher.decrypt(result2)

a = a.decode('utf-8','ignore')
a = a.rstrip('\n')
a = a.rstrip('\t')
a = a.rstrip('\r')
a = a.replace('\x06','')
print('\n','data:',a)

#data: 儒雅随和,加大力度

4. Processamento de criptografia

Da mesma forma, os caracteres podem ser criptografados e os métodos de criptografia e descriptografia AES podem ser implementados .

 # encoding:utf-8

def encrypt(data, password):
    bs = AES.block_size
    pad = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs)
    cipher = AES.new(password)
    data = cipher.encrypt(pad(data))
    return (data)
    
if __name__ == '__main__':
    data = 'ni hao'
    password = 'aesrsasec' #16,24,32位长的密码
    password = add_to_16(password)        
    encrypt_data = encrypt(data, password)
    encrypt_data = base64.b64encode(encrypt_data)
    print ('encrypt_data:', encrypt_data)

5. Descriptografia e criptografia AES-CBC

Comparado com CBC & ECB, há mais um vi (offset).
cipher = AES.new(self.__key, AES.MODE_CBC, iv)
python AES criptografia e descriptografia simétrica bidirecional

# encoding:utf-8
import base64
from Crypto.Cipher import AES
from Crypto import Random
 
def encrypt(data, password):
    bs = AES.block_size
    pad = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs)
    iv = Random.new().read(bs)
    cipher = AES.new(password, AES.MODE_CBC, iv)
    data = cipher.encrypt(pad(data))
    data = iv + data
    return (data)
 
def decrypt(data, password):
    bs = AES.block_size
    if len(data) <= bs:
        return (data)
    unpad = lambda s : s[0:-ord(s[-1])]
    iv = data[:bs]
    cipher = AES.new(password, AES.MODE_CBC, iv)
    data  = unpad(cipher.decrypt(data[bs:]))
    return (data)
 
if __name__ == '__main__':
    data = 'd437814d9185a290af20514d9341b710'
    password = '78f40f2c57eee727a4be179049cecf89' #16,24,32位长的密码
    encrypt_data = encrypt(data, password)
    encrypt_data = base64.b64encode(encrypt_data)
    print ('encrypt_data:', encrypt_data)
 
 
    encrypt_data = base64.b64decode(encrypt_data)
    decrypt_data = decrypt(encrypt_data, password)
    print ('decrypt_data:', decrypt_data)

6. Criptografia Java e erro de descriptografia Python.

No trabalho real do AES, descobriu-se que o arquivo criptografado pelo Java da outra parte e o texto cifrado criptografado por seu próprio Python eram diferentes, resultando em erros de descriptografia entre plataformas.

Razões para possíveis erros:
1. Algoritmo de preenchimento
2. Tamanho do segmento

Consulte o erro de plataforma cruzada AES_CFB


7. Erro de descriptografia no Linux

Ele roda sem erro no windows, mas reporta um erro quando roda no Lnuix.
①, erro new() faltando 1 argumento posicional necessário: 'modo'
precisa ser adicionado no linux, o segundo parâmetro, selecione o modo de criptografia (desta vez, escolha ECB)

cipher = AES.new(key ,AES.MODE_ECB)

②, Erro Tipo de objeto <class 'str'> não pode ser passado para o código C
A chave passada no linux deve estar na forma de bytes, e a chave é processada

key = key.encode('utf-8')
cipher = AES.new(key ,AES.MODE_ECB)

8. Resumo

1. Ao lidar com criptografia AES, você deve concordar com um método de criptografia específico.
2. Chave, vi deve ter um comprimento compatível.
3. O texto cifrado também precisa ser preenchido.
4. O Windows ECB adiciona automaticamente o parâmetro cipher e a chave pode ser uma string. No Linux, você precisa preencher os parâmetros completos e processar a chave em bytes.


nove, outro

1. pad e unpad são função de preenchimento e função de preenchimento inverso, respectivamente. Como a criptografia AES tem um requisito de comprimento para o texto criptografado, ele deve ser um múltiplo do número de bytes de chave. O comprimento do encryptKey aqui após a decodificação base64 é de 16 bytes.
2. Na verdade, existem três tipos de criptografia AES, AES-128, AES-192 e AES-256, correspondendo aos três comprimentos de chave de 128 bits (16 bytes), 192 bits (24 bytes) e 256 bits (32 bytes) ). Obviamente, quanto maior a chave, maior a segurança e mais tempo leva para criptografar e descriptografar. O padrão é AES-128, que é totalmente seguro.

Extensão do Algoritmo de Preenchimento

O algoritmo de preenchimento usado aqui, na verdade, tem um termo apropriado chamado pkcs7padding.
A explicação simples é compensar os bits ausentes: a string de preenchimento consiste em uma sequência de bytes e cada byte preenche o comprimento da sequência de bytes de preenchimento.
Se você deseja preencher 8 bytes, o valor do byte preenchido é 0x08; se deseja preencher 7 bytes, o valor preenchido é 0x07; e assim por diante.
Se o comprimento do texto for exatamente um múltiplo do comprimento do BlockSize, um valor do comprimento do BlockSize também será preenchido. A vantagem disso é que o número de bytes preenchidos pode ser conhecido de acordo com o valor preenchido do último Byte.

Na verdade, o modo padrão para implementar o algoritmo de criptografia AES em java é Cipher.getInstance("AES/ECB/PKCS5Padding")
PKCS#5 é um subconjunto de PKCS#7 em termos de preenchimento: PKCS#5 é apenas para 8 bytes ( BlockSize=8) para preenchimento, o conteúdo do preenchimento é 0x01-0x08; mas PKCS#7 não é apenas preenchimento para 8 bytes, seu intervalo de BlockSize é de 1-255 bytes.
No entanto, como o AES não possui um bloco de 64 bits (8 bytes), se o PKCS5 for usado, o PKCS7 será essencialmente usado.



Autor: Ziger,
Link: https://www.jianshu.com/p/5b38b4187b54
Fonte: Jianshu
Os direitos autorais pertencem ao autor. Para reimpressão comercial, por favor, entre em contato com o autor para autorização, para reimpressão não comercial, por favor, indique a fonte.

Acho que você gosta

Origin blog.csdn.net/m0_54219225/article/details/121532111
Recomendado
Clasificación