← Cloudflare Workers / workers / runtime-apis
Web Crypto
Контекст
Web Crypto API предоставляет набор низкоуровневых функций для типовых криптографических задач. Среда выполнения Workers реализует этот API полностью, но с некоторыми отличиями в поддерживаемые алгоритмы по сравнению с теми, что реализованы в большинстве браузеров.
Выполнение криптографических операций через Web Crypto API значительно быстрее, чем их выполнение исключительно на JavaScript. Если вам нужны криптографические операции с высокой нагрузкой на CPU, используйте для этого Web Crypto API.
Web Crypto API реализован через SubtleCrypto интерфейс, доступный через глобальный crypto.subtle привязку. Простой пример вычисления дайджеста (также известного как хеш):
const myText = new TextEncoder().encode('Hello world!');
const myDigest = await crypto.subtle.digest(
{
name: 'SHA-256',
},
myText // The data you want to hash as an ArrayBuffer
);
console.log(new Uint8Array(myDigest));К распространённым сценариям использования относятся подписание запросов.
Конструкторы
-
crypto.DigestStream(algorithm)DigestStream- Нестандартное расширение
cryptoAPI, который поддерживает вычисление хеша по потоковым данным.DigestStreamсам по себе являетсяWritableStreamкоторый не сохраняет записанные в него данные. Вместо этого он автоматически генерирует хеш-дайджест по завершении потока данных.
- Нестандартное расширение
Параметры
-
algorithmstring | object- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
Использование
export default {
async fetch(req) {
// Fetch from origin
const res = await fetch(req);
// We need to read the body twice so we `tee` it (get two instances)
const [bodyOne, bodyTwo] = res.body.tee();
// Make a new response so we can set the headers (responses from `fetch` are immutable)
const newRes = new Response(bodyOne, res);
// Create a SHA-256 digest stream and pipe the body into it
const digestStream = new crypto.DigestStream("SHA-256");
bodyTwo.pipeTo(digestStream);
// Get the final result
const digest = await digestStream.digest;
// Turn it into a hex string
const hexString = [...new Uint8Array(digest)]
.map(b => b.toString(16).padStart(2, '0'))
.join('')
// Set a header with the SHA-256 hash and return the response
newRes.headers.set("x-content-digest", `SHA-256=${hexString}`);
return newRes;
}
}export default {
async fetch(req): Promise<Response> {
// Fetch from origin
const res = await fetch(req);
// We need to read the body twice so we `tee` it (get two instances)
const [bodyOne, bodyTwo] = res.body.tee();
// Make a new response so we can set the headers (responses from `fetch` are immutable)
const newRes = new Response(bodyOne, res);
// Create a SHA-256 digest stream and pipe the body into it
const digestStream = new crypto.DigestStream("SHA-256");
bodyTwo.pipeTo(digestStream);
// Get the final result
const digest = await digestStream.digest;
// Turn it into a hex string
const hexString = [...new Uint8Array(digest)]
.map(b => b.toString(16).padStart(2, '0'))
.join('')
// Set a header with the SHA-256 hash and return the response
newRes.headers.set("x-content-digest", `SHA-256=${hexString}`);
return newRes;
}
} satisfies ExportedHandler;Методы
-
crypto.randomUUID(): string- Генерирует новый случайный UUID (версии 4), как определено в RFC 4122 ↗.
-
crypto.getRandomValues(bufferArrayBufferView): ArrayBufferView- Заполняет переданный
ArrayBufferViewкриптографически надежными случайными значениями и возвращаетbuffer.
- Заполняет переданный
Параметры
-
bufferArrayBufferView- Должно быть одним из типов: Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | BigInt64Array | BigUint64Array.
Методы SubtleCrypto
Доступ ко всем этим методам осуществляется через crypto.subtle ↗, который также подробно описан на MDN.
encrypt
-
encrypt(algorithm, key, data): Promise<ArrayBuffer>- Возвращает Promise, который выполняется с зашифрованными данными, соответствующими открытому тексту, алгоритму и ключу, переданным в качестве параметров.
Параметры
-
algorithmобъект- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
keyCryptoKey -
dataBufferSource
decrypt
-
decrypt(algorithm, key, data): Promise<ArrayBuffer>- Возвращает Promise, который выполняется с открытыми данными, соответствующими зашифрованному тексту, алгоритму и ключу, переданным в качестве параметров.
Параметры
-
algorithmобъект- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
keyCryptoKey -
dataBufferSource
подписать
-
sign(algorithm, key, data): Promise<ArrayBuffer>- Возвращает Promise, который выполняется с подписью, соответствующей тексту, алгоритму и ключу, переданным в качестве параметров.
Параметры
-
algorithmstring | object- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
keyCryptoKey -
dataArrayBuffer
подтвердить
-
verify(algorithm, key, signature, data): Promise<boolean>- Возвращает Promise, который выполняется со значением Boolean, указывающим, соответствует ли переданная в качестве параметра подпись тексту, алгоритму и ключу, также переданным в качестве параметров.
Параметры
-
algorithmstring | object- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
keyCryptoKey -
signatureArrayBuffer -
dataArrayBuffer
digest
-
digest(algorithm, data): Promise<ArrayBuffer>- Возвращает Promise, который выполняется с дайджестом, сформированным на основе алгоритма и текста, переданных в качестве параметров.
Параметры
-
algorithmstring | object- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
dataArrayBuffer
generateKey
-
generateKey(algorithm, extractable, keyUsages): Promise<CryptoKey> | Promise<CryptoKeyPair>- Возвращает Promise, который выполняется с только что сгенерированным
CryptoKey, для симметричных алгоритмов, либоCryptoKeyPair, содержащий два новых сгенерированных ключа, для асимметричных алгоритмов. Например, чтобы сгенерировать новый ключ AES-GCM:
let keyPair = await crypto.subtle.generateKey( { name: 'AES-GCM', length: 256, }, true, ['encrypt', 'decrypt'] ); - Возвращает Promise, который выполняется с только что сгенерированным
Параметры
-
algorithmобъект- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
extractablebool -
keyUsagesArray- Массив строк, указывающий возможные варианты использования нового ключа ↗.
deriveKey
-
deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages): Promise<CryptoKey>- Возвращает Promise, который выполняется с только что сгенерированным
CryptoKeyпроизводного от базового ключа и конкретного алгоритма, переданных в качестве параметров.
- Возвращает Promise, который выполняется с только что сгенерированным
Параметры
-
algorithmобъект- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
baseKeyCryptoKey -
derivedKeyAlgorithmobject- Определяет алгоритм, для которого будет использоваться производный ключ в формат, специфичный для алгоритма ↗.
-
extractablebool -
keyUsagesArray- Массив строк, указывающий возможные варианты использования нового ключа ↗
deriveBits
-
deriveBits(algorithm, baseKey, length): Promise<ArrayBuffer>- Возвращает Promise, который выполняется с только что сгенерированным буфером псевдослучайных бит, полученных из базового ключа и конкретного алгоритма, переданных в качестве параметров. Он возвращает Promise, который будет выполнен с
ArrayBufferсодержащий производные биты. Этот метод очень похож наderiveKey(), за исключением того, чтоderiveKey()возвращаетCryptoKeyобъект, а неArrayBuffer. По сути,deriveKey()состоит изderiveBits()а затемimportKey().
- Возвращает Promise, который выполняется с только что сгенерированным буфером псевдослучайных бит, полученных из базового ключа и конкретного алгоритма, переданных в качестве параметров. Он возвращает Promise, который будет выполнен с
Параметры
-
algorithmобъект- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
baseKeyCryptoKey -
lengthint- Длина получаемой битовой строки.
importKey
-
importKey(format, keyData, algorithm, extractable, keyUsages): Promise<CryptoKey>- Преобразовать ключ из некоторого внешнего переносимого формата в
CryptoKeyдля использования с Web Crypto API.
- Преобразовать ключ из некоторого внешнего переносимого формата в
Параметры
-
formatstring- Описывает формат импортируемого ключа ↗.
-
keyDataArrayBuffer -
algorithmобъект- Описывает алгоритм, который будет использоваться, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
-
extractablebool -
keyUsagesArray- Массив строк, указывающий возможные варианты использования нового ключа ↗
exportKey
-
exportKey(formatstring, keyCryptoKey): Promise<ArrayBuffer>- Преобразовать
CryptoKeyв переносимый формат, еслиCryptoKeyэтоextractable.
- Преобразовать
Параметры
-
formatstring- Описывает формат, в котором будет экспортирован ключ ↗.
-
keyCryptoKey
wrapKey
-
wrapKey(format, key, wrappingKey, wrapAlgo): Promise<ArrayBuffer>- Преобразовать
CryptoKeyв переносимый формат, а затем зашифровать другим ключом. Это делаетCryptoKeyподходит для хранения или передачи в недоверенных средах.
- Преобразовать
Параметры
-
formatstring- Описывает формат, в котором будет экспортирован ключ ↗ перед шифрованием.
-
keyCryptoKey -
wrappingKeyCryptoKey -
wrapAlgoобъект- Описывает алгоритм, который будет использоваться для шифрования экспортированного ключа, включая все необходимые параметры, в формат, специфичный для алгоритма ↗.
unwrapKey
-
unwrapKey(format, key, unwrappingKey, unwrapAlgo,: Promise<CryptoKey>
unwrappedKeyAlgo, extractable, keyUsages)- Преобразовать ключ, обёрнутый с помощью
wrapKey()обратно вCryptoKey.
- Преобразовать ключ, обёрнутый с помощью
Параметры
-
formatstring- Описывает формат данных ключа для распаковки ↗.
-
keyCryptoKey -
unwrappingKeyCryptoKey -
unwrapAlgoобъект- Описывает алгоритм, использованный для шифрования обёрнутого ключа, в формате, специфичном для алгоритма ↗.
-
unwrappedKeyAlgoобъект- Описывает ключ, который нужно развернуть, в формате, специфичном для алгоритма ↗.
-
extractablebool -
keyUsagesArray- Массив строк, указывающий возможные варианты использования нового ключа ↗
timingSafeEqual
-
timingSafeEqual(a, b): bool- Сравнивает два буфера способом, устойчивым к атакам по времени. Это нестандартное расширение Web Crypto API.
Параметры
-
aArrayBuffer | TypedArray -
bArrayBuffer | TypedArray
Поддерживаемые алгоритмы
Workers реализует все операции Стандарт WebCrypto ↗, как показано в следующей таблице.
Галочка (✓) означает, что данная функция считается полностью поддерживаемой согласно спецификации.
Значок x (✘) означает, что эта функция входит в спецификацию, но не реализована.
Если функция реализует операцию лишь частично, подробности указаны ниже.
| Алгоритм | sign() verify() |
encrypt() decrypt() |
digest() | deriveBits() deriveKey() |
generateKey() | wrapKey() unwrapKey() |
exportKey() | importKey() |
|---|---|---|---|---|---|---|---|---|
| RSASSA PKCS1 v1.5 | ✓ | ✓ | ✓ | ✓ | ||||
| RSA PSS | ✓ | ✓ | ✓ | ✓ | ||||
| RSA OAEP | ✓ | ✓ | ✓ | ✓ | ✓ | |||
| ECDSA | ✓ | ✓ | ✓ | ✓ | ||||
| ECDH | ✓ | ✓ | ✓ | ✓ | ||||
| Ed255191 | ✓ | ✓ | ✓ | ✓ | ||||
| X255191 | ✓ | ✓ | ✓ | ✓ | ||||
| NODE ED255192 | ✓ | ✓ | ✓ | ✓ | ||||
| AES CTR | ✓ | ✓ | ✓ | ✓ | ✓ | |||
| AES CBC | ✓ | ✓ | ✓ | ✓ | ✓ | |||
| AES GCM | ✓ | ✓ | ✓ | ✓ | ✓ | |||
| AES KW | ✓ | ✓ | ✓ | ✓ | ||||
| HMAC | ✓ | ✓ | ✓ | ✓ | ||||
| SHA 1 | ✓ | |||||||
| SHA 256 | ✓ | |||||||
| SHA 384 | ✓ | |||||||
| SHA 512 | ✓ | |||||||
| MD53 | ✓ | |||||||
| HKDF | ✓ | ✓ | ||||||
| PBKDF2 | ✓ | ✓ |
Сноски:
-
Алгоритмы, указанные в Secure Curves API ↗.
-
Устаревшая нестандартная реализация EdDSA поддерживается для кривой Ed25519 в дополнение к версии Secure Curves. Поскольку этот алгоритм нестандартный, при его использовании учитывайте следующее:
- Используйте
NODE-ED25519в качестве алгоритма иnamedCurveпараметры. - В отличие от NodeJS, Cloudflare не поддерживает прямой импорт приватных ключей.
- Реализация алгоритма может со временем меняться. Хотя Cloudflare не может гарантировать это на данный момент, компания будет стремиться сохранять обратную совместимость и совместимость с поведением NodeJS. О значимых изменениях совместимости будет сообщаться в примечаниях к выпуску и в этой документации для разработчиков.
- Используйте
-
MD5 не входит в стандарт WebCrypto, но поддерживается в Cloudflare Workers для взаимодействия с устаревшими системами, которым требуется MD5. MD5 считается слабым алгоритмом. Не полагайтесь на MD5 для обеспечения безопасности.