| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 16afd10 commit 3f47a2f
25 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2927,6 +2927,7 @@ const Cipher Cipher::AES_256_GCM = Cipher::FromNid(NID_aes_256_gcm); | |||
| 2927 | 2927 | const Cipher Cipher::AES_128_KW = Cipher::FromNid(NID_id_aes128_wrap); | |
| 2928 | 2928 | const Cipher Cipher::AES_192_KW = Cipher::FromNid(NID_id_aes192_wrap); | |
| 2929 | 2929 | const Cipher Cipher::AES_256_KW = Cipher::FromNid(NID_id_aes256_wrap); | |
| 2930 | + const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305); | ||
| 2930 | 2931 | ||
| 2931 | 2932 | bool Cipher::isGcmMode() const { | |
| 2932 | 2933 | if (!cipher_) return false; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -373,6 +373,7 @@ class Cipher final { | |||
| 373 | 373 | static const Cipher AES_128_KW; | |
| 374 | 374 | static const Cipher AES_192_KW; | |
| 375 | 375 | static const Cipher AES_256_KW; | |
| 376 | + static const Cipher CHACHA20_POLY1305; | ||
| 376 | 377 | ||
| 377 | 378 | struct CipherParams { | |
| 378 | 379 | int padding; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,191 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const { | ||
| 4 | + ArrayBufferIsView, | ||
| 5 | + ArrayBufferPrototypeSlice, | ||
| 6 | + ArrayFrom, | ||
| 7 | + PromiseReject, | ||
| 8 | + SafeSet, | ||
| 9 | + TypedArrayPrototypeSlice, | ||
| 10 | + } = primordials; | ||
| 11 | + | ||
| 12 | + const { | ||
| 13 | + ChaCha20Poly1305CipherJob, | ||
| 14 | + KeyObjectHandle, | ||
| 15 | + kCryptoJobAsync, | ||
| 16 | + kWebCryptoCipherDecrypt, | ||
| 17 | + kWebCryptoCipherEncrypt, | ||
| 18 | + } = internalBinding('crypto'); | ||
| 19 | + | ||
| 20 | + const { | ||
| 21 | + hasAnyNotIn, | ||
| 22 | + jobPromise, | ||
| 23 | + validateKeyOps, | ||
| 24 | + kHandle, | ||
| 25 | + kKeyObject, | ||
| 26 | + } = require('internal/crypto/util'); | ||
| 27 | + | ||
| 28 | + const { | ||
| 29 | + lazyDOMException, | ||
| 30 | + promisify, | ||
| 31 | + } = require('internal/util'); | ||
| 32 | + | ||
| 33 | + const { | ||
| 34 | + InternalCryptoKey, | ||
| 35 | + SecretKeyObject, | ||
| 36 | + createSecretKey, | ||
| 37 | + } = require('internal/crypto/keys'); | ||
| 38 | + | ||
| 39 | + const { | ||
| 40 | + randomBytes: _randomBytes, | ||
| 41 | + } = require('internal/crypto/random'); | ||
| 42 | + | ||
| 43 | + const randomBytes = promisify(_randomBytes); | ||
| 44 | + | ||
| 45 | + function validateKeyLength(length) { | ||
| 46 | + if (length !== 256) | ||
| 47 | + throw lazyDOMException('Invalid key length', 'DataError'); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + function c20pCipher(mode, key, data, algorithm) { | ||
| 51 | + let tag; | ||
| 52 | + switch (mode) { | ||
| 53 | + case kWebCryptoCipherDecrypt: { | ||
| 54 | + const slice = ArrayBufferIsView(data) ? | ||
| 55 | + TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice; | ||
| 56 | + | ||
| 57 | + if (data.byteLength < 16) { | ||
| 58 | + return PromiseReject(lazyDOMException( | ||
| 59 | + 'The provided data is too small.', | ||
| 60 | + 'OperationError')); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + tag = slice(data, -16); | ||
| 64 | + data = slice(data, 0, -16); | ||
| 65 | + break; | ||
| 66 | + } | ||
| 67 | + case kWebCryptoCipherEncrypt: | ||
| 68 | + tag = 16; | ||
| 69 | + break; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + return jobPromise(() => new ChaCha20Poly1305CipherJob( | ||
| 73 | + kCryptoJobAsync, | ||
| 74 | + mode, | ||
| 75 | + key[kKeyObject][kHandle], | ||
| 76 | + data, | ||
| 77 | + algorithm.iv, | ||
| 78 | + tag, | ||
| 79 | + algorithm.additionalData)); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + async function c20pGenerateKey(algorithm, extractable, keyUsages) { | ||
| 83 | + const { name } = algorithm; | ||
| 84 | + | ||
| 85 | + const checkUsages = ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']; | ||
| 86 | + | ||
| 87 | + const usagesSet = new SafeSet(keyUsages); | ||
| 88 | + if (hasAnyNotIn(usagesSet, checkUsages)) { | ||
| 89 | + throw lazyDOMException( | ||
| 90 | + `Unsupported key usage for a ${algorithm.name} key`, | ||
| 91 | + 'SyntaxError'); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + const keyData = await randomBytes(32).catch((err) => { | ||
| 95 | + throw lazyDOMException( | ||
| 96 | + 'The operation failed for an operation-specific reason' + | ||
| 97 | + `[${err.message}]`, | ||
| 98 | + { name: 'OperationError', cause: err }); | ||
| 99 | + }); | ||
| 100 | + | ||
| 101 | + return new InternalCryptoKey( | ||
| 102 | + createSecretKey(keyData), | ||
| 103 | + { name }, | ||
| 104 | + ArrayFrom(usagesSet), | ||
| 105 | + extractable); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + function c20pImportKey( | ||
| 109 | + algorithm, | ||
| 110 | + format, | ||
| 111 | + keyData, | ||
| 112 | + extractable, | ||
| 113 | + keyUsages) { | ||
| 114 | + const { name } = algorithm; | ||
| 115 | + const checkUsages = ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']; | ||
| 116 | + | ||
| 117 | + const usagesSet = new SafeSet(keyUsages); | ||
| 118 | + if (hasAnyNotIn(usagesSet, checkUsages)) { | ||
| 119 | + throw lazyDOMException( | ||
| 120 | + `Unsupported key usage for a ${algorithm.name} key`, | ||
| 121 | + 'SyntaxError'); | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + let keyObject; | ||
| 125 | + switch (format) { | ||
| 126 | + case 'KeyObject': { | ||
| 127 | + keyObject = keyData; | ||
| 128 | + break; | ||
| 129 | + } | ||
| 130 | + case 'raw-secret': { | ||
| 131 | + keyObject = createSecretKey(keyData); | ||
| 132 | + break; | ||
| 133 | + } | ||
| 134 | + case 'jwk': { | ||
| 135 | + if (!keyData.kty) | ||
| 136 | + throw lazyDOMException('Invalid keyData', 'DataError'); | ||
| 137 | + | ||
| 138 | + if (keyData.kty !== 'oct') | ||
| 139 | + throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError'); | ||
| 140 | + | ||
| 141 | + if (usagesSet.size > 0 && | ||
| 142 | + keyData.use !== undefined && | ||
| 143 | + keyData.use !== 'enc') { | ||
| 144 | + throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError'); | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + validateKeyOps(keyData.key_ops, usagesSet); | ||
| 148 | + | ||
| 149 | + if (keyData.ext !== undefined && | ||
| 150 | + keyData.ext === false && | ||
| 151 | + extractable === true) { | ||
| 152 | + throw lazyDOMException( | ||
| 153 | + 'JWK "ext" Parameter and extractable mismatch', | ||
| 154 | + 'DataError'); | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + const handle = new KeyObjectHandle(); | ||
| 158 | + try { | ||
| 159 | + handle.initJwk(keyData); | ||
| 160 | + } catch (err) { | ||
| 161 | + throw lazyDOMException( | ||
| 162 | + 'Invalid keyData', { name: 'DataError', cause: err }); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + if (keyData.alg !== undefined && keyData.alg !== 'C20P') { | ||
| 166 | + throw lazyDOMException( | ||
| 167 | + 'JWK "alg" does not match the requested algorithm', | ||
| 168 | + 'DataError'); | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + keyObject = new SecretKeyObject(handle); | ||
| 172 | + break; | ||
| 173 | + } | ||
| 174 | + default: | ||
| 175 | + return undefined; | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + validateKeyLength(keyObject.symmetricKeySize * 8); | ||
| 179 | + | ||
| 180 | + return new InternalCryptoKey( | ||
| 181 | + keyObject, | ||
| 182 | + { name }, | ||
| 183 | + keyUsages, | ||
| 184 | + extractable); | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + module.exports = { | ||
| 188 | + c20pCipher, | ||
| 189 | + c20pGenerateKey, | ||
| 190 | + c20pImportKey, | ||
| 191 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -199,6 +199,10 @@ const { | |||
| 199 | 199 | result = require('internal/crypto/aes') | |
| 200 | 200 | .aesImportKey(algorithm, 'KeyObject', this, extractable, keyUsages); | |
| 201 | 201 | break; | |
| 202 | + case 'ChaCha20-Poly1305': | ||
| 203 | + result = require('internal/crypto/chacha20_poly1305') | ||
| 204 | + .c20pImportKey(algorithm, 'KeyObject', this, extractable, keyUsages); | ||
| 205 | + break; | ||
| 202 | 206 | case 'HKDF': | |
| 203 | 207 | // Fall through | |
| 204 | 208 | case 'PBKDF2': | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -245,13 +245,13 @@ const kSupportedAlgorithms = { | |||
| 245 | 245 | 'encrypt': { | |
| 246 | 246 | 'RSA-OAEP': 'RsaOaepParams', | |
| 247 | 247 | 'AES-CBC': 'AesCbcParams', | |
| 248 | - 'AES-GCM': 'AesGcmParams', | ||
| 248 | + 'AES-GCM': 'AeadParams', | ||
| 249 | 249 | 'AES-CTR': 'AesCtrParams', | |
| 250 | 250 | }, | |
| 251 | 251 | 'decrypt': { | |
| 252 | 252 | 'RSA-OAEP': 'RsaOaepParams', | |
| 253 | 253 | 'AES-CBC': 'AesCbcParams', | |
| 254 | - 'AES-GCM': 'AesGcmParams', | ||
| 254 | + 'AES-GCM': 'AeadParams', | ||
| 255 | 255 | 'AES-CTR': 'AesCtrParams', | |
| 256 | 256 | }, | |
| 257 | 257 | 'get key length': { | |
@@ -290,6 +290,14 @@ const experimentalAlgorithms = ObjectEntries({ | |||
| 290 | 290 | 'SHA3-256': { digest: null }, | |
| 291 | 291 | 'SHA3-384': { digest: null }, | |
| 292 | 292 | 'SHA3-512': { digest: null }, | |
| 293 | + 'ChaCha20-Poly1305': { | ||
| 294 | + 'encrypt': 'AeadParams', | ||
| 295 | + 'decrypt': 'AeadParams', | ||
| 296 | + 'generateKey': null, | ||
| 297 | + 'importKey': null, | ||
| 298 | + 'exportKey': null, | ||
| 299 | + 'get key length': null, | ||
| 300 | + }, | ||
| 293 | 301 | }); | |
| 294 | 302 | ||
| 295 | 303 | for (const { 0: algorithm, 1: nid } of [ | |
@@ -325,7 +333,7 @@ for (let i = 0; i < experimentalAlgorithms.length; i++) { | |||
| 325 | 333 | } | |
| 326 | 334 | ||
| 327 | 335 | const simpleAlgorithmDictionaries = { | |
| 328 | - AesGcmParams: { iv: 'BufferSource', additionalData: 'BufferSource' }, | ||
| 336 | + AeadParams: { iv: 'BufferSource', additionalData: 'BufferSource' }, | ||
| 329 | 337 | RsaHashedKeyGenParams: { hash: 'HashAlgorithmIdentifier' }, | |
| 330 | 338 | EcKeyGenParams: {}, | |
| 331 | 339 | HmacKeyGenParams: { hash: 'HashAlgorithmIdentifier' }, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -155,6 +155,11 @@ async function generateKey( | |||
| 155 | 155 | result = await require('internal/crypto/aes') | |
| 156 | 156 | .aesGenerateKey(algorithm, extractable, keyUsages); | |
| 157 | 157 | break; | |
| 158 | + case 'ChaCha20-Poly1305': | ||
| 159 | + resultType = 'CryptoKey'; | ||
| 160 | + result = await require('internal/crypto/chacha20_poly1305') | ||
| 161 | + .c20pGenerateKey(algorithm, extractable, keyUsages); | ||
| 162 | + break; | ||
| 158 | 163 | case 'ML-DSA-44': | |
| 159 | 164 | // Fall through | |
| 160 | 165 | case 'ML-DSA-65': | |
@@ -252,6 +257,8 @@ function getKeyLength({ name, length, hash }) { | |||
| 252 | 257 | case 'HKDF': | |
| 253 | 258 | case 'PBKDF2': | |
| 254 | 259 | return null; | |
| 260 | + case 'ChaCha20-Poly1305': | ||
| 261 | + return 256; | ||
| 255 | 262 | } | |
| 256 | 263 | } | |
| 257 | 264 | ||
@@ -431,7 +438,7 @@ async function exportKeyRawSeed(key) { | |||
| 431 | 438 | } | |
| 432 | 439 | } | |
| 433 | 440 | ||
| 434 | - async function exportKeyRawSecret(key) { | ||
| 441 | + async function exportKeyRawSecret(key, format) { | ||
| 435 | 442 | switch (key.algorithm.name) { | |
| 436 | 443 | case 'AES-CTR': | |
| 437 | 444 | // Fall through | |
@@ -443,6 +450,11 @@ async function exportKeyRawSecret(key) { | |||
| 443 | 450 | // Fall through | |
| 444 | 451 | case 'HMAC': | |
| 445 | 452 | return key[kKeyObject][kHandle].export().buffer; | |
| 453 | + case 'ChaCha20-Poly1305': | ||
| 454 | + if (format === 'raw-secret') { | ||
| 455 | + return key[kKeyObject][kHandle].export().buffer; | ||
| 456 | + } | ||
| 457 | + return undefined; | ||
| 446 | 458 | default: | |
| 447 | 459 | return undefined; | |
| 448 | 460 | } | |
@@ -504,6 +516,9 @@ async function exportKeyJWK(key) { | |||
| 504 | 516 | parameters.alg = require('internal/crypto/aes') | |
| 505 | 517 | .getAlgorithmName(key.algorithm.name, key.algorithm.length); | |
| 506 | 518 | break; | |
| 519 | + case 'ChaCha20-Poly1305': | ||
| 520 | + parameters.alg = 'C20P'; | ||
| 521 | + break; | ||
| 507 | 522 | case 'HMAC': { | |
| 508 | 523 | const alg = normalizeHashName( | |
| 509 | 524 | key.algorithm.hash.name, | |
@@ -563,7 +578,7 @@ async function exportKey(format, key) { | |||
| 563 | 578 | } | |
| 564 | 579 | case 'raw-secret': { | |
| 565 | 580 | if (key.type === 'secret') { | |
| 566 | - result = await exportKeyRawSecret(key); | ||
| 581 | + result = await exportKeyRawSecret(key, format); | ||
| 567 | 582 | } | |
| 568 | 583 | break; | |
| 569 | 584 | } | |
@@ -581,7 +596,7 @@ async function exportKey(format, key) { | |||
| 581 | 596 | } | |
| 582 | 597 | case 'raw': { | |
| 583 | 598 | if (key.type === 'secret') { | |
| 584 | - result = await exportKeyRawSecret(key); | ||
| 599 | + result = await exportKeyRawSecret(key, format); | ||
| 585 | 600 | } else if (key.type === 'public') { | |
| 586 | 601 | result = await exportKeyRawPublic(key, format); | |
| 587 | 602 | } | |
@@ -687,6 +702,10 @@ async function importKey( | |||
| 687 | 702 | result = require('internal/crypto/aes') | |
| 688 | 703 | .aesImportKey(algorithm, format, keyData, extractable, keyUsages); | |
| 689 | 704 | break; | |
| 705 | + case 'ChaCha20-Poly1305': | ||
| 706 | + result = require('internal/crypto/chacha20_poly1305') | ||
| 707 | + .c20pImportKey(algorithm, format, keyData, extractable, keyUsages); | ||
| 708 | + break; | ||
| 690 | 709 | case 'HKDF': | |
| 691 | 710 | // Fall through | |
| 692 | 711 | case 'PBKDF2': | |
@@ -975,6 +994,9 @@ async function cipherOrWrap(mode, algorithm, key, data, op) { | |||
| 975 | 994 | case 'AES-GCM': | |
| 976 | 995 | return require('internal/crypto/aes') | |
| 977 | 996 | .aesCipher(mode, key, data, algorithm); | |
| 997 | + case 'ChaCha20-Poly1305': | ||
| 998 | + return require('internal/crypto/chacha20_poly1305') | ||
| 999 | + .c20pCipher(mode, key, data, algorithm); | ||
| 978 | 1000 | case 'AES-KW': | |
| 979 | 1001 | if (op === 'wrapKey' || op === 'unwrapKey') { | |
| 980 | 1002 | return require('internal/crypto/aes') | |
| Back | FazBrowse Home | New Git URL |
0 commit comments