Метод subtle.encrypt

Метод crypto.subtle.encrypt() выполняет шифрование данных с использованием заданного алгоритма и криптографического ключа. Он является частью Web Crypto API и относится к интерфейсу SubtleCrypto, предоставляемому объектом crypto.subtle в браузерной среде.

Метод работает исключительно с бинарными данными (ArrayBuffer или типизированные массивы), не поддерживает строки напрямую и всегда возвращает результат в виде Promise<ArrayBuffer>.


crypto.subtle.encrypt(algorithm, key, data)

Параметры

algorithm Объект, описывающий используемый алгоритм шифрования и его параметры. Структура зависит от выбранного алгоритма:

  • AES-GCM
  • AES-CBC
  • RSA-OAEP
  • ChaChaKey (в некоторых реализациях)
  • и др.

key Объект CryptoKey, полученный ранее через crypto.subtle.generateKey, importKey или deriveKey. Ключ должен иметь назначение "encrypt".

data Исходные данные для шифрования в формате:

  • ArrayBuffer
  • TypedArray
  • DataView

Общий принцип работы

Шифрование в Web Crypto API происходит в изолированном контексте браузера и не блокирует основной поток выполнения. Все операции выполняются асинхронно через Promise.

const encrypted = await crypto.subtle.encrypt(algorithm, key, data);

Результатом всегда является ArrayBuffer, содержащий зашифрованный текст (ciphertext) и, в зависимости от алгоритма, дополнительные данные (например, IV или authentication tag в случае AES-GCM).


Преобразование строк в данные

Так как API работает только с бинарными данными, строки необходимо предварительно кодировать:

const encoder = new TextEncoder();
const data = encoder.encode("Секретное сообщение");

Обратное преобразование выполняется через TextDecoder после расшифровки.


Пример использования AES-GCM

AES-GCM является одним из наиболее часто используемых симметричных алгоритмов благодаря встроенной аутентификации данных.

Генерация ключа

const key = await crypto.subtle.generateKey(
  {
    name: "AES-GCM",
    length: 256
  },
  true,
  ["encrypt", "decrypt"]
);

Подготовка данных и IV

IV (initialization vector) должен быть уникальным для каждого шифрования:

const iv = crypto.getRandomValues(new Uint8Array(12));

const encoder = new TextEncoder();
const data = encoder.encode("Конфиденциальная информация");

Шифрование

const encrypted = await crypto.subtle.encrypt(
  {
    name: "AES-GCM",
    iv: iv
  },
  key,
  data
);

Результат encrypted содержит зашифрованные данные вместе с аутентификационным тегом.


RSA-OAEP шифрование

RSA используется для шифрования небольших объёмов данных или ключей.

Импорт публичного ключа

const publicKey = await crypto.subtle.importKey(
  "jwk",
  jwkPublicKey,
  {
    name: "RSA-OAEP",
    hash: "SHA-256"
  },
  true,
  ["encrypt"]
);

Шифрование

const encoder = new TextEncoder();
const data = encoder.encode("Сообщение для RSA");

const encrypted = await crypto.subtle.encrypt(
  {
    name: "RSA-OAEP"
  },
  publicKey,
  data
);

Особенности алгоритмов

AES-GCM

  • Поддерживает аутентификацию данных
  • Требует уникального IV
  • Оптимален для симметричного шифрования больших данных

AES-CBC

  • Не предоставляет встроенной аутентификации
  • Требует ручной обработки целостности
  • Устаревающий подход по сравнению с GCM

RSA-OAEP

  • Используется для шифрования ключей (hybrid encryption)
  • Ограничен по размеру данных (зависит от длины ключа)
  • Требует асимметричной пары ключей

Типы данных и представление результата

Метод всегда возвращает ArrayBuffer. Для дальнейшей передачи или хранения часто используется преобразование в Base64:

function arrayBufferToBase64(buffer) {
  const bytes = new Uint8Array(buffer);
  let binary = "";
  for (let i = 0; i < bytes.byteLength; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary);
}

Ошибки и исключения

Метод может отклонить Promise в следующих случаях:

1. Неверный алгоритм

Если объект algorithm не соответствует поддерживаемому формату.

2. Несовместимый ключ

Если ключ:

  • не предназначен для шифрования (["decrypt"] вместо ["encrypt"])
  • создан для другого алгоритма

3. Неправильный формат данных

Если data не является ArrayBuffer-совместимым типом.

4. Нарушение требований алгоритма

Например:

  • отсутствие IV в AES-GCM
  • слишком длинные данные для RSA-OAEP

Производительность и ограничения

Web Crypto API реализован на уровне браузера и использует нативные криптографические библиотеки, поэтому:

  • операции выполняются быстрее, чем JS-реализации криптографии
  • доступ к данным ограничен sandbox-моделью браузера
  • отсутствует возможность извлечения ключей, если они помечены как extractable: false

Безопасные практики

Уникальность IV

В алгоритмах типа AES-GCM повторное использование IV с одним ключом приводит к компрометации данных.

Ограничение RSA

RSA не предназначен для больших сообщений. Типичный подход — гибридное шифрование:

  • RSA шифрует AES-ключ
  • AES шифрует данные

Контроль экспорта ключей

extractable: false

снижает риск утечки ключа через exportKey.


Типичные сценарии использования

  • шифрование пользовательских данных перед отправкой на сервер
  • защищённое хранение информации в IndexedDB
  • реализация end-to-end encryption в веб-приложениях
  • защита локальных токенов и секретов

Взаимодействие с другими методами SubtleCrypto

crypto.subtle.encrypt() часто используется вместе с:

  • generateKey() — создание ключей
  • importKey() — загрузка внешних ключей
  • exportKey() — экспорт (ограниченно)
  • decrypt() — обратная операция
  • digest() — хеширование перед шифрованием или для проверки целостности

Структура результата AES-GCM

Результирующий ArrayBuffer включает:

  • ciphertext
  • authentication tag (обычно 16 байт в конце)

Это позволяет одновременно обеспечивать конфиденциальность и целостность данных без дополнительных механизмов.


Частые ошибки разработки

Повторное использование IV

Приводит к утечке информации о XOR-структуре данных.

Хранение ключей в открытом виде

Нарушает смысл использования Web Crypto API.

Использование строк вместо бинарных данных

Метод не принимает строки напрямую и всегда требует кодирования.


Пример полного цикла AES-GCM

const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 },
  true,
  ["encrypt", "decrypt"]
);

const iv = crypto.getRandomValues(new Uint8Array(12));
const encoder = new TextEncoder();
const data = encoder.encode("Тестовое сообщение");

const encrypted = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv },
  key,
  data
);

Метод crypto.subtle.encrypt() является базовым строительным блоком криптографических операций в браузере и определяет модель безопасного симметричного и асимметричного шифрования в Web Crypto API.