AES_ENCRYPT() și AES_DECRYPT() în MySQL

Criptare și hash MySQL 5.0+ (KDF: 8.0.30+)

Criptează și decriptează date cu algoritmul AES; fără cheie, datele nu pot fi citite.

Sintaxă
AES_ENCRYPT(text, cheie [, vector_init [, kdf, sare [, info | iteratii]]])
AES_DECRYPT(text_criptat, cheie [, vector_init [, kdf, sare [, info | iteratii]]])

Ce face AES_ENCRYPT() și AES_DECRYPT()

AES_ENCRYPT() criptează un text cu o cheie și returnează un șir binar. AES_DECRYPT() face operația inversă, cu aceeași cheie. Dacă cheia este greșită, rezultatul este de obicei NULL (uneori date fără sens). Rezultatul decriptării este binar; transformă-l în text cu CAST(... AS CHAR).

Modul de criptare vine din variabila block_encryption_mode, implicit aes-128-ecb. Modurile mai sigure (de exemplu aes-256-cbc) cer și un vector de inițializare de cel puțin 16 octeți, generat de obicei cu RANDOM_BYTES(16) și păstrat lângă datele criptate.

Cel mai sigur mod de a da cheia este printr-o funcție de derivare a cheii (KDF): 'hkdf' sau 'pbkdf2_hmac', cu o „sare” aleatorie. Fără KDF, cheia ar trebui să aibă cel mult 16 octeți; una mai lungă produce un avertisment. Coloanele pentru date criptate trebuie să fie binare: VARBINARY sau BLOB.

Parametri

Parametru Descriere
text Datele de criptat.
text_criptat Rezultatul lui AES_ENCRYPT().
cheie Cheia (sau parola din care se derivă cheia, cu KDF).
vector_init Opțional. Vectorul de inițializare, obligatoriu pentru modurile CBC, CFB și OFB; '' pentru ECB cu KDF.
kdf Opțional. 'hkdf' sau 'pbkdf2_hmac'.
sare Opțional. Date aleatorii adăugate la derivarea cheii.
info | iteratii Opțional. Informații de context (pentru hkdf) sau numărul de iterații (pentru pbkdf2_hmac, implicit 1000).

Ce returnează

Un șir binar (criptat sau decriptat) sau NULL.

Exemple

Exemplul 1: Criptare și decriptare simplă

Rezultatul criptării este binar, așa că îl afișăm cu HEX().

SELECT HEX(AES_ENCRYPT('Ana Popescu', 'cheie de 16 oct')) AS criptat,
       CAST(AES_DECRYPT(AES_ENCRYPT('Ana Popescu', 'cheie de 16 oct'), 'cheie de 16 oct') AS CHAR) AS decriptat,
       AES_DECRYPT(AES_ENCRYPT('Ana Popescu', 'cheie de 16 oct'), 'alta cheie') AS cheie_gresita;

Rezultat

+----------------------------------+-------------+---------------+
| criptat                          | decriptat   | cheie_gresita |
+----------------------------------+-------------+---------------+
| 16F497ED20F3C0A7DDCE29874916EE88 | Ana Popescu | NULL          |
+----------------------------------+-------------+---------------+

Exemplul 2: Coloană criptată cu cheie derivată (PBKDF2)

CREATE TABLE clienti (
  id INT PRIMARY KEY,
  nume VARCHAR(30),
  cnp_criptat VARBINARY(64)
);

INSERT INTO clienti VALUES
  (1, 'Ana', AES_ENCRYPT('2900101223344', 'parola aplicatiei', '', 'pbkdf2_hmac', 'sare-ana', 10000));

SELECT nume,
       HEX(cnp_criptat) AS in_tabel,
       CAST(AES_DECRYPT(cnp_criptat, 'parola aplicatiei', '', 'pbkdf2_hmac', 'sare-ana', 10000) AS CHAR) AS cnp
FROM clienti;

Rezultat

+------+----------------------------------+---------------+
| nume | in_tabel                         | cnp           |
+------+----------------------------------+---------------+
| Ana  | 4232E1051C6A98E474CB537FD7F5A037 | 2900101223344 |
+------+----------------------------------+---------------+

Exemplul 3: Mod CBC, cu vector de inițializare

În modul aes-256-cbc, vectorul de inițializare este obligatoriu. Îl generăm aleatoriu și îl folosim la ambele operații.

SET block_encryption_mode = 'aes-256-cbc';
SET @iv = RANDOM_BYTES(16);
SET @criptat = AES_ENCRYPT('comanda 1042', 'parola', @iv, 'hkdf', 'sare', 'magazin');

SELECT CAST(AES_DECRYPT(@criptat, 'parola', @iv, 'hkdf', 'sare', 'magazin') AS CHAR) AS decriptat;

Rezultat

+--------------+
| decriptat    |
+--------------+
| comanda 1042 |
+--------------+

Greșeli frecvente

  • Salvezi rezultatul în VARCHAR. Conversia setului de caractere poate strica octeții; folosește VARBINARY sau BLOB.
  • Folosești o parolă lungă direct ca cheie. MySQL afișează un avertisment, iar cheia este slabă; folosește o funcție KDF (pbkdf2_hmac sau hkdf).
  • Pierzi vectorul de inițializare sau sarea. Fără ele, datele nu mai pot fi decriptate; salvează-le lângă datele criptate (nu sunt secrete).

Comenzi înrudite

  • RANDOM_BYTES(): Returnează un șir de octeți aleatorii, sigur pentru criptografie (chei, token-uri, vectori AES).
  • SHA2(): Calculează suma de control SHA-2 (SHA-224, SHA-256, SHA-384 sau SHA-512) a unui text.
  • HEX() și UNHEX(): HEX() transformă un număr sau un text în hexazecimal; UNHEX() face conversia inversă.