Перейти к содержанию

Криптография

Выполнение функций криптографии в Node.js обеспечивает встроенный в платформу модуль crypto, который поддерживает алгоритмы для шифрования и расшифровки данных, генерацию сертификатов, хэш-функции и т. д.

Модуль crypto входит не во все сборки Node.js, поэтому его использование в приложении, запускаемом на разных сервера, может быть не всегда возможным. Чтобы проверить доступность модуля, добавьте следующий код.

1
2
3
4
5
6
7
let crypto;

try {
    crypto = require('crypto');
} catch (err) {
    console.log('Crypto module is unavailable');
}

Для получения списка поддерживаемых в Node.js алгоритмов шифрования, выполните у экземпляра модуля crypto функцию getCiphers().

1
2
3
const crypto = require('crypto');

console.log(crypto.getCiphers());

В рамках данной статьи рассмотрены шифрование и расшифровка данных.

Шифрование данных по заданному алгоритму осуществляется в три этапа:

  • Создание объекта Cipher;
  • Добавление к созданному объекту данных, которые необходимо зашифровать;
  • Завершение процесса шифрования.

Объект Cipher создается вызовом метода crypto.createCipheriv(), который принимает три параметра:

  • алгоритм;
  • ключ;
  • вектор инициализации (необязательный).

Обогащение созданного объекта Cipher данными осуществляется с помощью метода [CipherInstance].update(), которому можно передать следующие аргументы:

  • данные для шифрования;
  • кодировка исходных данных (необязательный);
  • кодировка возвращаемого методом значения (необязательный).

Завершение процесса шифрования осуществляется вызовом метода final(), принимающему кодировку зашифрованных данных.

Рассмотрим пример шифрования данных.

cipher.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const crypto = require('crypto');

const iv = crypto.randomBytes(16); //генерация вектора инициализации
const key = crypto.scryptSync('secret', 'salt', 32); //генерация ключа

const encyptedData = crypto
    .createCipheriv('aes-256-cbc', key, iv)
    .update('Any data', 'utf8', 'hex')
    .final('hex');

console.log(encryptedData);

В зависимости от используемого алгоритма длина вектора инициализации может отличаться.

Теперь рассмотрим, как расшифровать зашифрованные данные. В качестве зашифрованных данных возьмем результат из предыдущего примера. Последовательность действий та же, только вместо метода createCipher() используется createDecipher().

decipher.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const crypto = require('crypto');

const iv = crypto.randomBytes(16); //генерация вектора инициализации
const key = crypto.scryptSync('secret', 'salt', 32); //генерация ключа

const decyptedData = crypto
    .createDecipheriv('aes-256-cbc', key, iv)
    .update(encryptedData, 'hex', 'utf8')
    .final('utf8');

console.log(decryptedData); //Any data

Процесс шифрования представляет собой поток. Поэтому пример выше может быть переписан следующим образом.

crypto-stream.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const crypto = require('crypto');

const iv = crypto.randomBytes(16); //генерация вектора инициализации
const key = crypto.scryptSync('secret', 'salt', 32); //генерация ключа

let cipherStream = crypto.createCipheriv(
    'aes-256-cbc',
    key,
    iv
);

let encryptedData = '';

cipherStream.on(
    'data',
    (data) => (encryptedData += data.toString('hex'))
);

cipherStream.write('Any data');
cipherStream.end();

let decipherStream = crypto.createDecipheriv(
    'aes-256-cbc',
    key,
    iv
);

let decryptedData = '';

decipherStream.on(
    'data',
    (data) => (decryptedData += data)
);
decipherStream.on('end', () => console.log(decryptedData)); //'Any data'

decipherStream.write(encryptedData, 'hex');
decipherStream.end();