Je veux faire un chiffrement et un déchiffrement AES sur une chaîne. mais la clé et le message doivent être en octets, j'ai donc converti le message en octets en procédant comme suit:

b"string"

Voici mon code AES:

# Encryption
encryption_suite = AES.new(b'1234567812345678', AES.MODE_OCB)
cipher_text = encryption_suite.encrypt(b"A really secret message. Not for prying eyes.")

# Decryption
decryption_suite = AES.new(b'1234567812345678', AES.MODE_OCB)
plaintext = decryption_suite.decrypt(cipher_text)

Cependant, je dois retourner le texte brut déchiffré en chaîne pour être lisible. Actuellement, le texte en clair ressemble à ceci:

B'x \ x85 \ x92 \ x9d \ xe6 \ x0bJ \ xfe \ x9b (\ x10G \ x8e \ x05 \ xc5 \ xf4 \ xcdA9 \ xc18 \ xb8_ \ xf9vbmK \ x16 \ xf8 \ xa3 \ xb6 ''

J'ai essayé d'utiliser

plaintext.decode(encoding='windows-1252')

Et

plaintext.decode("utf-8").strip('\x00')

Mais tout ce que je reçois est ceci:

UnicodeDecodeError: le codec 'charmap' ne peut pas décoder l'octet 0x9d en position 3: les caractères sont mappés sur

Ou ca:

UnicodeDecodeError: le codec 'utf-8' ne peut pas décoder l'octet 0xb1 en position 1: octet de début invalide

J'ai besoin de reconvertir ces octets en une chaîne lisible .. si vous pouvez aider, ce serait apprécié.

3
MNS 23 mai 2018 à 09:36

3 réponses

Meilleure réponse

Le principal problème avec votre code est que vous ne fournissez pas de nonce à AES.new(). OCB nécessite un nonce; si vous n'en fournissez pas, un nonce aléatoire sera créé chaque fois que vous créerez un nouvel objet AES, et le déchiffrement échouera donc.

À partir des docs:

nonce (chaîne d'octets): une valeur non répétable, de longueur comprise entre 1 et 15 octets. S'il n'est pas présent, un nonce aléatoire de la longueur recommandée (15 octets) sera créé.

Vous avez deux options, soit créer un nonce et le transmettre à AES.new() (en cryptage et décryptage), soit utiliser le nonce aléatoire créé par AES pendant le cryptage.

Ensuite, OCB est un algorithme de chiffrement authentifié, mais il semble que vous ne vérifiez pas le MAC. Ceci est important car le MAC vérifie l'intégrité du texte chiffré.

Les méthodes de chiffrement et de déchiffrement de AES acceptent et renvoient des octets. Vous pouvez convertir le texte en clair (s'il s'agit de texte) en chaîne avec .decode(). Si vous voulez convertir le texte chiffré en chaîne, vous devrez d'abord le coder en base64, afin de coder les octets bruts en caractères ASCII (n'oubliez pas de décoder avant le déchiffrement). b64encode() renvoie également des octets mais peut être facilement converti en chaîne.

Un exemple,

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from base64 import b64encode

key = get_random_bytes(16) # A 16 byte key for AES-128
nonce = get_random_bytes(15)
message = "A really secret message. Not for prying eyes.".encode()

cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
ciphertext, mac = cipher.encrypt_and_digest(message)

cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, mac)

print(b64encode(ciphertext).decode())
#CSwHy3ir3MZ7yvZ4CzHbgYOsKgzhMqjq6wEuutU7vJJTJ0c38ExWkAY1QkLO
print(plaintext.decode())
#A really secret message. Not for prying eyes.

Notez que si .decrypt_and_verify() ne parvient pas à vérifier le MAC, une exception ValueError sera levée, vous pouvez donc utiliser un bloc try-except. Les valeurs nonce et mac ne sont pas secrètes et il est sûr de les stocker à côté du texte chiffré.

Enfin, si vous prévoyez de dériver une clé à partir d'une phrase secrète, vous devez utiliser un KDF basé sur un mot de passe. Les KDF créent des clés fortes, utilisent du sel et des itérations, et ils sont très résistants aux attaques fruteforce. Vous trouverez des fonctions KDF dans Crypto.Protocol.KDF.

6
t.m.adam 26 mars 2019 à 01:00

Je pense que votre encodage est "ISO-8859-1". Vous pouvez donc faire:

plaintext.decode("ISO-8859-1")
0
Pelonomi Moiloa 26 juin 2019 à 14:01

Vous ne pouvez pas convertir des données binaires en chaîne, car ce n'est pas par nature une chaîne. Ce sont des données binaires. Les chances que la sortie de votre cryptage se produise, par hasard, pour être une chaîne UTF8 correctement formatée sont assez peu probables.

Vous devriez plutôt regarder base64. Il gonfle les données (3 octets à 4 caractères) mais convient mieux à votre cas d'utilisation.

ÉDITER:. Mon erreur, j'ai mal compris votre question. La sortie que vous avez n'est pas correcte, le premier octet n'est pas un «1» en UTF8. Il s'agit probablement d'un problème de chiffrement / déchiffrement.

1
Luke Joshua Park 23 mai 2018 à 06:53