Chiffrer dans le front-end JS et déchiffrer dans le backend python à l'aide d'AES GCM

Une analyse

J'essaie de chiffrer dans le front-end JS et de déchiffrer dans le backend python à l'aide de l'algorithme cryptographique AES GCM. J'utilise l' API de cryptographie Web pour le front-end JS et la bibliothèque de cryptographie python pour le backend python en tant que bibliothèque cryptographique. J'ai corrigé le IV pour l'instant des deux côtés. J'ai implémenté le code de cryptage-décryptage des deux côtés, ils fonctionnent de chaque côté. Mais je pense que le remplissage est effectué différemment, je n'arrive pas à comprendre comment le remplissage est effectué dans l'API de cryptographie Web. Voici le chiffrement et le déchiffrement du backend Python :

def encrypt(derived_key, secret):
    IV = bytes("ddfbccae-b4c4-11", encoding="utf-8")
    aes = Cipher(algorithms.AES(derived_key), modes.GCM(IV))
    encryptor = aes.encryptor()
    padder = padding.PKCS7(128).padder()
    padded_data = padder.update(secret.encode()) + padder.finalize()
    return encryptor.update(padded_data) + encryptor.finalize()

def decrypt(derived_key, secret): 
    IV = bytes("ddfbccae-b4c4-11", encoding="utf-8")
    aes = Cipher(algorithms.AES(derived_key), modes.GCM(IV))
    decryptor = aes.decryptor()
    decrypted_data = decryptor.update(secret) 
    unpadder = padding.PKCS7(128).unpadder()
    return unpadder.update(decrypted_data) + unpadder.finalize()

Voici le code JS pour le chiffrement et le code de déchiffrement :

async function encrypt(secretKey, message) {
  let iv = "ddfbccae-b4c4-11";
  iv = Uint8Array.from(iv, x => x.charCodeAt(0))
  let encoded = getMessageEncoding(message);
  ciphertext = await window.crypto.subtle.encrypt(
    {
      name: "AES-GCM",
      iv: iv
    },
    secretKey,
    encoded
  );
  return ciphertext;
}

async function decrypt(secretKey, cipherText) {
  iv = "ddfbccae-b4c4-11";
  iv = Uint8Array.from(iv, x => x.charCodeAt(0))
  try {
    let decrypted = await window.crypto.subtle.decrypt(
      {
        name: "AES-GCM",
        iv: iv
      },
      secretKey,
      cipherText
    );

    let dec = new TextDecoder();
    console.log("Decrypted message: ");
    console.log(dec.decode(decrypted));
   
  } catch (e) {
    console.log("error");
    
  }
}

J'essaie de chiffrer côté JS et de déchiffrer côté python. Mais j'ai l'erreur suivante :entrez la description de l'image ici

Si j'essaie de crypter la même chaîne des deux côtés, j'obtiens ces sorties : En python, le texte crypté : \x17O\xadn\x11*I\x94\x99\xc6\x90\x8a\xa9\x9cc=

En JS le texte crypté : \x17O\xadn\x11*I\xdf\xe3F\x81(\x15\xcc\x8c^z\xdf+\x1d\x91K\xbc

Comment résoudre ce problème de remplissage ?

Topaco

GCM est un mode de chiffrement de flux et ne nécessite donc pas de remplissage. Lors du cryptage, une balise d'authentification est implicitement générée, qui est utilisée pour l'authentification lors du décryptage. De plus, un IV/nonce de 12 octets est recommandé pour GCM.

Le code Python posté remplit inutilement et ne prend pas en compte la balise d'authentification, contrairement au code JavaScript, qui peut être la principale raison des différents textes chiffrés. Il est difficile de dire si c'est la seule raison et si le code JavaScript implémente correctement GCM, car la getMessageEncoding()méthode n'a pas été publiée, il n'a donc pas été possible de tester cela.

De plus, les deux codes appliquent un IV/nonce de 16 octets au lieu des 12 octets IV/nonce recommandés.


La cryptographie offre deux implémentations possibles pour GCM. Une implémentation utilise l'architecture des modes de non-authentification comme CBC. Le code Python publié applique cette conception, mais ne prend pas en compte l'authentification et implémente donc GCM de manière incomplète. Un exemple correct pour cette conception peut être trouvé ici .
La cryptographie recommande généralement l'autre approche pour GCM (voir la note de danger ), à savoir la AESGCMclasse, qui effectue une authentification implicite afin que cela ne puisse pas être accidentellement oublié ou mal implémenté.

L'implémentation suivante utilise la AESGCMclasse (et prend également en compte les données authentifiées supplémentaires facultatives ) :

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import base64
#import os

#key = AESGCM.generate_key(bit_length=256)    
#nonce = os.urandom(12)
key = base64.b64decode('MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE=') # fix for testing, AES-256
nonce = base64.b64decode('MDEyMzQ1Njc4OTAx') # fix for testing, 12 bytes

plaintext = b'The quick brown fox jumps over the lazy dog'
aad = b'the aad' # aad = None without additional authenticated data

aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, plaintext, aad)
print('Ciphertext (B64): ' + base64.b64encode(ciphertext).decode('utf8'))
decrypted = aesgcm.decrypt(nonce, ciphertext, aad)
print('Decrypted:        ' + decrypted.decode('utf8'))

avec la sortie :

Output
Ciphertext (B64): JOetStCANhPISvQ6G6IcRBauqbtC8fzRooblayHqkqSPKzLbidx/gBWfLNzBC+ZpcAGnGnHXaI7CB1U=
Decrypted:        The quick brown fox jumps over the lazy dog

La balise d'authentification est ajoutée au texte chiffré, de sorte que le résultat (décodé en Base64) a la longueur du texte en clair (43 octets) plus la longueur de la balise (16 octets, par défaut), ce qui donne un total de 59 octets.

Pour les tests, une clé prédéfinie et IV/nonce sont utilisés en vue d'une comparaison avec le résultat du code JavaScript. Notez qu'en pratique une paire clé/IV ne peut être utilisée qu'une seule fois pour des raisons de sécurité, ce qui est particulièrement important pour le mode GCM, par exemple ici . Par conséquent, un IV/nonce aléatoire est généralement généré pour chaque chiffrement.


L' API WebCrypto est une API de bas niveau pour la cryptographie et ne fournit pas de méthodes pour l'encodage/décodage Base64. Dans ce qui suit, js-base64 est utilisé pour plus de simplicité. Tout comme le code Python, la balise est ajoutée au texte chiffré.

Une implémentation possible pour AES-GCM en utilisant la clé et IV/nonce du code Python qui est fonctionnellement essentiellement le même que le code JavaScript publié est :

(async () => {      
    var key = Base64.toUint8Array('MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE='); // fix for testing, AES-256
    var nonce = Base64.toUint8Array('MDEyMzQ1Njc4OTAx'); // fix for testing, 12 bytes

    var plaintext = new TextEncoder().encode("The quick brown fox jumps over the lazy dog");
    var aad = new TextEncoder().encode('the aad');
                
    var keyImported = await await crypto.subtle.importKey(
        "raw",
        key,
        { name: "AES-GCM" },
        true,
        ["decrypt", "encrypt"]
    );
                
    var ciphertext = await await crypto.subtle.encrypt(
        { name: "AES-GCM", iv: nonce, additionalData: aad }, // { name: "AES-GCM", iv: nonce } without additional authenticated data
        keyImported,
        plaintext
    );
    console.log('Ciphertext (Base64):\n', Base64.fromUint8Array(new Uint8Array(ciphertext)).replace(/(.{48})/g,'$1\n'));
              
    var decrypted = await await crypto.subtle.decrypt(
        { name: "AES-GCM", iv: nonce, additionalData: aad }, // { name: "AES-GCM", iv: nonce } without additional authenticated data
        keyImported,
        ciphertext
    );
    console.log('Plaintext:\n', new TextDecoder().decode(decrypted).replace(/(.{48})/g,'$1\n'));
})();
<script src="https://cdn.jsdelivr.net/npm/[email protected]/base64.min.js"></script>

avec la sortie :

Ciphertext (Base64):
 JOetStCANhPISvQ6G6IcRBauqbtC8fzRooblayHqkqSPKzLbidx/gBWfLNzBC+ZpcAGnGnHXaI7CB1U=
Plaintext:
 The quick brown fox jumps over the lazy dog

où le texte chiffré est le même que celui du code Python.

Cet article est collecté sur Internet, veuillez indiquer la source lors de la réimpression.

En cas d'infraction, veuillez [email protected] Supprimer.

modifier le
0

laisse moi dire quelques mots

0commentaires
connexionAprès avoir participé à la revue

Articles connexes

le cryptage RSA: Chiffrer dans Android / java, décryptez en python (cryptographie)

Déchiffrer le contenu encodé aes-128-gcm avec JAVA Cipher en utilisant PHP OpenSSL

Chiffrer efficacement les fichiers à l'aide d'AES en Java

Comment chiffrer à l'aide de crypto AES dans nodejs?

Comment déchiffrer un texte chiffré dans Go qui est chiffré dans vuejs à l'aide du package aes-js

Impossible de déchiffrer après AES-GCM + Base64 dans Go

Crypter la charge utile à l'aide d'une clé et iv par l'algorithme AES / GCM / NoPadding dans le nœud js et décrypter en java

Impossible de déchiffrer le GCM AES-256 avec Java

Tenter de déchiffrer le texte chiffré dans une fonction Lambda à l'aide de KMS entraîne un délai d'expiration

Chiffrer et déchiffrer AES

Chiffrer / Crypter et déchiffrer les mots de passe dans les fichiers .properties à l'aide de Talend Data Integration

Android Studio ne peut pas déchiffrer le message dans AES

Comment chiffrer et déchiffrer dans Angular 6

Chiffrer AES dans Cryptojs, décrypter dans Pycrypto

Chiffrer dans ColdFusion, déchiffrer en C #

Impossible de déchiffrer le blob envoyé par le serveur Java dans le client python

Déchiffrer AES dans l'exemple C++

Crypter AES dans Terminal et déchiffrer en PHP

Puis-je déchiffrer le flux GCM AES dans Bouncy Castle en utilisant n'importe quoi ayant une interface SkippingCipher?

Crypter le fichier audio mp3 pendant le téléchargement et le déchiffrer pendant la lecture dans Android

Comment chiffrer et déchiffrer à l'aide de la clé privée et de la clé publique ECDSA générées dans la structure Hyperledger

Chiffrer et déchiffrer à l'aide de certificats dans .NET Core C#

Android : chiffrer plusieurs fichiers dans un seul fichier et déchiffrer l'un d'entre eux

Crypter et déchiffrer le hachage sha256 dans Postgresql

Crypter dans Node.JS Crypto (aes-256-cbc) puis déchiffrer dans OpenSSL CLI

Comment chiffrer et déchiffrer symétriquement certaines données en C# à l'aide d'AES ?

Déchiffrer XOR dans le nœud js

Avantages de l'utilisation du chiffrement AES pour chiffrer et déchiffrer le mot de passe par rapport au stockage du mot de passe dans le coffre-fort JBOSS

Avantages de l'utilisation du chiffrement AES pour chiffrer et déchiffrer le mot de passe par rapport au stockage du mot de passe dans le coffre-fort JBOSS

TOP liste

chaudétiquette

Archive