diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2021-09-12 02:24:03 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-11 16:54:03 -0400 |
commit | 0cb22d4cba76cf86486db3d311a6a4c61b93d953 (patch) | |
tree | 41364e69b146a4bd413bd2e3e400e3f984a596df /ext/crypto/00_crypto.js | |
parent | 40c63d1255642b8d70d7b5ce5b85a50f6af8a00d (diff) |
feat(ext/crypto): implement HKDF operations (#11865)
Co-authored-by: Luca Casonato <lucacasonato@yahoo.com>
Diffstat (limited to 'ext/crypto/00_crypto.js')
-rw-r--r-- | ext/crypto/00_crypto.js | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 0e5a511e5..2cb7a3bb2 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -61,6 +61,11 @@ RsaPssParams: {}, EcdsaParams: { hash: "HashAlgorithmIdentifier" }, HmacImportParams: { hash: "HashAlgorithmIdentifier" }, + HkdfParams: { + hash: "HashAlgorithmIdentifier", + salt: "BufferSource", + info: "BufferSource", + }, Pbkdf2Params: { hash: "HashAlgorithmIdentifier", salt: "BufferSource" }, RsaOaepParams: { label: "BufferSource" }, }; @@ -97,9 +102,11 @@ }, "importKey": { "HMAC": "HmacImportParams", + "HKDF": null, "PBKDF2": null, }, "deriveBits": { + "HKDF": "HkdfParams", "PBKDF2": "Pbkdf2Params", }, "encrypt": { @@ -893,6 +900,51 @@ // TODO(@littledivy): RSASSA-PKCS1-v1_5 // TODO(@littledivy): RSA-PSS // TODO(@littledivy): ECDSA + case "HKDF": { + if (format !== "raw") { + throw new DOMException("Format not supported", "NotSupportedError"); + } + + // 1. + if ( + ArrayPrototypeFind( + keyUsages, + (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), + ) !== undefined + ) { + throw new DOMException("Invalid key usages", "SyntaxError"); + } + + // 2. + if (extractable !== false) { + throw new DOMException( + "Key must not be extractable", + "SyntaxError", + ); + } + + // 3. + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, { + type: "raw", + data: keyData, + }); + + // 4-8. + const algorithm = { + name: "HKDF", + }; + const key = constructKey( + "secret", + false, + usageIntersection(keyUsages, recognisedUsages), + algorithm, + handle, + ); + + // 9. + return key; + } case "PBKDF2": { // 1. if (format !== "raw") { @@ -1604,6 +1656,51 @@ return buf.buffer; } + case "HKDF": { + // 1. + if (length === null || length === 0 || length % 8 !== 0) { + throw new DOMException("Invalid length", "OperationError"); + } + + const handle = baseKey[_handle]; + const keyDerivationKey = WeakMapPrototypeGet(KEY_STORE, handle); + + if (ArrayBufferIsView(normalizedAlgorithm.salt)) { + normalizedAlgorithm.salt = new Uint8Array( + normalizedAlgorithm.salt.buffer, + normalizedAlgorithm.salt.byteOffset, + normalizedAlgorithm.salt.byteLength, + ); + } else { + normalizedAlgorithm.salt = new Uint8Array(normalizedAlgorithm.salt); + } + normalizedAlgorithm.salt = TypedArrayPrototypeSlice( + normalizedAlgorithm.salt, + ); + + if (ArrayBufferIsView(normalizedAlgorithm.info)) { + normalizedAlgorithm.info = new Uint8Array( + normalizedAlgorithm.info.buffer, + normalizedAlgorithm.info.byteOffset, + normalizedAlgorithm.info.byteLength, + ); + } else { + normalizedAlgorithm.info = new Uint8Array(normalizedAlgorithm.info); + } + normalizedAlgorithm.info = TypedArrayPrototypeSlice( + normalizedAlgorithm.info, + ); + + const buf = await core.opAsync("op_crypto_derive_bits", { + key: keyDerivationKey, + algorithm: "HKDF", + hash: normalizedAlgorithm.hash.name, + info: normalizedAlgorithm.info, + length, + }, normalizedAlgorithm.salt); + + return buf.buffer; + } default: throw new DOMException("Not implemented", "NotSupportedError"); } |