- Acasă
- Documentație criptare
Documentație Criptare
Află cum funcționează criptarea noastră AES-256-GCM. Documentație completă cu exemple de cod pentru implementarea criptării pe partea clientului.
Capitole
Cum funcționează
Derivarea Cheii
Parola ta este utilizată pentru a deriva o cheie AES de 256 de biți folosind PBKDF2 cu SHA-256 și 600.000 de iterații. Acest lucru face atacurile brute-force costisitoare din punct de vedere computațional.
Valori Aleatorii
Un salt aleatoriu de 128 de biți și un IV (Vector de Inițializare) de 96 de biți sunt generate folosind generarea de numere aleatorii sigură criptografic pentru fiecare criptare.
Criptare AES-256-GCM
Datele sunt criptate folosind AES-256-GCM (Galois/Counter Mode), care oferă atât confidențialitate, cât și verificarea autenticității.
Formatul Rezultatului
Rezultatul este formatat ca v1:salt:iv:ciphertext unde toate componentele sunt codificate base64.
Funcții de criptare
Derivare Cheie
async function deriveAesGcmKey(password, saltBytes) {
const te = new TextEncoder();
const baseKey = await crypto.subtle.importKey(
'raw',
te.encode(password),
{ name: 'PBKDF2' },
false,
['deriveKey']
);
return crypto.subtle.deriveKey(
{
name: 'PBKDF2',
hash: 'SHA-256',
salt: saltBytes,
iterations: 600000, // OWASP 2025 recommended minimum
},
baseKey,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
}
Funcții ajutătoare
function bytesToBase64(bytes) {
let binary = '';
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
function base64ToBytes(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
Criptează
/**
* Build combined key from password and salt key
* Format: "password:saltKey"
*/
function buildCombinedKey(password, saltKey) {
if (saltKey) {
return password + ':' + saltKey;
}
return password;
}
async function encrypt(plainText, password, saltKey = '') {
const te = new TextEncoder();
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const combinedKey = buildCombinedKey(password, saltKey);
const key = await deriveAesGcmKey(combinedKey, salt);
const cipherBuf = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
te.encode(plainText)
);
return [
'v1',
bytesToBase64(salt),
bytesToBase64(iv),
bytesToBase64(new Uint8Array(cipherBuf)),
].join(':');
}
Decriptează
/**
* Build combined key from password and salt key
* Format: "password:saltKey"
*/
function buildCombinedKey(password, saltKey) {
if (saltKey) {
return password + ':' + saltKey;
}
return password;
}
async function decrypt(payload, password, saltKey = '') {
const td = new TextDecoder();
const [version, saltB64, ivB64, cipherB64] = payload.split(':');
if (version !== 'v1') {
throw new Error('Unsupported payload version');
}
const salt = base64ToBytes(saltB64);
const iv = base64ToBytes(ivB64);
const ciphertext = base64ToBytes(cipherB64);
const combinedKey = buildCombinedKey(password, saltKey);
const key = await deriveAesGcmKey(combinedKey, salt);
const plainBuf = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv },
key,
ciphertext
);
return td.decode(plainBuf);
}
Exemplu Complet
/**
* AES-256-GCM Encryption/Decryption Example
* Encrypts "Hello World" and decrypts it back
*/
// Salt key (RK) - used to strengthen password-based encryption
const SALT_KEY = '9x=1KO2tUFw#G:ARZd>Ff)s(^H+DWY4MpgJ:Cp_pCUU|og$>6a.bS.;ij9Wnw';
// Helper functions
function bytesToBase64(bytes) {
let binary = '';
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
function base64ToBytes(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
/**
* Build combined key from password and salt key
* Format: "password:saltKey"
*/
function buildCombinedKey(password, saltKey) {
if (saltKey) {
return password + ':' + saltKey;
}
return password;
}
/**
* Version configuration for encryption payloads
* v1: 150,000 iterations (legacy)
* v2: 600,000 iterations (current, OWASP 2025 recommended)
*/
const VERSION_CONFIG = {
v1: { iterations: 150000 },
v2: { iterations: 600000 },
};
const CURRENT_VERSION = 'v2';
// Derive AES-256 key from password using PBKDF2
async function deriveAesGcmKey(password, saltBytes, iterations) {
const te = new TextEncoder();
const baseKey = await crypto.subtle.importKey(
'raw',
te.encode(password),
{ name: 'PBKDF2' },
false,
['deriveKey']
);
return crypto.subtle.deriveKey(
{
name: 'PBKDF2',
hash: 'SHA-256',
salt: saltBytes,
iterations: iterations,
},
baseKey,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
}
// Encrypt function (uses v2 with 600,000 iterations)
async function encrypt(plainText, password, saltKey = '') {
const te = new TextEncoder();
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const combinedKey = buildCombinedKey(password, saltKey);
const iterations = VERSION_CONFIG[CURRENT_VERSION].iterations;
const key = await deriveAesGcmKey(combinedKey, salt, iterations);
const cipherBuf = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
te.encode(plainText)
);
return [
CURRENT_VERSION,
bytesToBase64(salt),
bytesToBase64(iv),
bytesToBase64(new Uint8Array(cipherBuf)),
].join(':');
}
// Decrypt function (supports both v1 and v2)
async function decrypt(payload, password, saltKey = '') {
const td = new TextDecoder();
const [version, saltB64, ivB64, cipherB64] = payload.split(':');
const versionConfig = VERSION_CONFIG[version];
if (!versionConfig) {
throw new Error('Unsupported payload version: ' + version);
}
const salt = base64ToBytes(saltB64);
const iv = base64ToBytes(ivB64);
const ciphertext = base64ToBytes(cipherB64);
const combinedKey = buildCombinedKey(password, saltKey);
const key = await deriveAesGcmKey(combinedKey, salt, versionConfig.iterations);
const plainBuf = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv },
key,
ciphertext
);
return td.decode(plainBuf);
}
// Example usage
(async () => {
const message = 'Hello World';
const password = 'my-secret-password';
console.log('Original:', message);
// Encrypt with salt key (uses v2)
const encrypted = await encrypt(message, password, SALT_KEY);
console.log('Encrypted:', encrypted);
// Decrypt with same salt key (supports v1 and v2)
const decrypted = await decrypt(encrypted, password, SALT_KEY);
console.log('Decrypted:', decrypted);
})();
Rezultat Așteptat
Original: Hello World Criptat: v1:aBcDeFgHiJkLmNoP...:qRsTuVwXyZ...:encrypted_data... Decriptat: Hello World
Notă: Rezultatul criptat va fi diferit de fiecare dată datorită generării aleatorii a salt-ului și IV-ului, dar decriptarea va returna întotdeauna mesajul original.
Gata să încerci?
Folosește instrumentul nostru interactiv de criptare pentru a vedea această criptare în acțiune.
Încearcă Instrumentul de Criptare