Τεκμηρίωση Κρυπτογράφησης

Μάθετε πώς λειτουργεί η κρυπτογράφηση AES-256-GCM. Πλήρης τεκμηρίωση με παραδείγματα κώδικα για την υλοποίηση κρυπτογράφησης από την πλευρά του πελάτη.

Πώς λειτουργεί

Παραγωγή Κλειδιού

Ο κωδικός πρόσβασής σας χρησιμοποιείται για την παραγωγή ενός κλειδιού AES 256-bit χρησιμοποιώντας PBKDF2 με SHA-256 και 600.000 επαναλήψεις. Αυτό καθιστά τις επιθέσεις brute-force υπολογιστικά δαπανηρές.

Τυχαίες Τιμές

Ένα τυχαίο salt 128-bit και ένα IV (Διάνυσμα Αρχικοποίησης) 96-bit παράγονται χρησιμοποιώντας κρυπτογραφικά ασφαλή παραγωγή τυχαίων αριθμών για κάθε κρυπτογράφηση.

Κρυπτογράφηση AES-256-GCM

Τα δεδομένα κρυπτογραφούνται χρησιμοποιώντας AES-256-GCM (Galois/Counter Mode), το οποίο παρέχει τόσο εμπιστευτικότητα όσο και επαλήθευση αυθεντικότητας.

Μορφή Εξόδου

Η έξοδος μορφοποιείται ως v1:salt:iv:ciphertext όπου όλα τα στοιχεία είναι κωδικοποιημένα σε base64.

Συναρτήσεις κρυπτογράφησης

Παραγωγή Κλειδιού

Παραγωγή Κλειδιού AES από Κωδικό Πρόσβασης
Χρησιμοποιεί PBKDF2 με SHA-256 και 600.000 επαναλήψεις για την παραγωγή ενός κλειδιού AES-GCM 256-bit από τον κωδικό πρόσβασης.
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']
    );
}

Βοηθητικά

Βοηθητικές Συναρτήσεις
Εργαλεία κωδικοποίησης και αποκωδικοποίησης Base64 για πίνακες byte.
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;
}

Κρυπτογράφηση

Κρυπτογράφηση Δεδομένων
Κρυπτογραφεί απλό κείμενο χρησιμοποιώντας AES-256-GCM με τυχαίο salt και IV. Επιστρέφει μορφοποιημένο φορτίο.
/**
 * 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(':');
}

Αποκρυπτογράφηση

Αποκρυπτογράφηση Δεδομένων
Αποκρυπτογραφεί ένα φορτίο v1 πίσω σε απλό κείμενο χρησιμοποιώντας τον αρχικό κωδικό πρόσβασης.
/**
 * 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);
}

Πλήρες Παράδειγμα

Κώδικας Έτοιμος για Χρήση
Αντιγράψτε και επικολλήστε αυτό το πλήρες παράδειγμα στην κονσόλα του προγράμματος περιήγησής σας ή στο αρχείο JavaScript.
/**
 * 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);
})();

Αναμενόμενη Έξοδος

Αναμενόμενη Έξοδος Κονσόλας
Αρχικό: Hello World
Κρυπτογραφημένο: v1:aBcDeFgHiJkLmNoP...:qRsTuVwXyZ...:encrypted_data...
Αποκρυπτογραφημένο: Hello World

Σημείωση: Η κρυπτογραφημένη έξοδος θα είναι διαφορετική κάθε φορά λόγω της τυχαίας παραγωγής salt και IV, αλλά η αποκρυπτογράφηση θα επιστρέφει πάντα το αρχικό μήνυμα.

Είστε έτοιμοι να το δοκιμάσετε;

Χρησιμοποιήστε το διαδραστικό εργαλείο κρυπτογράφησης για να δείτε αυτή την κρυπτογράφηση σε δράση.

Δοκιμάστε το Εργαλείο Κρυπτογράφησης

Σχεδόν δεν χρησιμοποιούμε cookies

Χρησιμοποιούμε μόνο απολύτως απαραίτητα cookies, που ενισχύουν την ασφάλεια του ιστότοπου και βελτιώνουν την εμπειρία χρήστη. Δεν παρακολουθούμε τις ενέργειες ή τη δραστηριότητά σας.