GeezerVison is showing github.com — crypto: add WebCrypto CryptoJob mode · nodejs/node@e431d93
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/aes.js +16-12Lines changed: 16 additions & 12 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 7 | 7 |
| 8 | 8 | const { | 9 | 9 | AESCipherJob, | 10 | | - kCryptoJobAsync, | | 10 | + kCryptoJobWebCrypto, | 11 | 11 | kKeyVariantAES_CTR_128, | 12 | 12 | kKeyVariantAES_CBC_128, | 13 | 13 | kKeyVariantAES_GCM_128, | @@ -107,7 +107,7 @@ function getVariant(name, length) { | 107 | 107 |
| 108 | 108 | function asyncAesCtrCipher(mode, key, data, algorithm) { | 109 | 109 | return jobPromise(() => new AESCipherJob( | 110 | | - kCryptoJobAsync, | | 110 | + kCryptoJobWebCrypto, | 111 | 111 | mode, | 112 | 112 | getCryptoKeyHandle(key), | 113 | 113 | data, | @@ -118,7 +118,7 @@ function asyncAesCtrCipher(mode, key, data, algorithm) { | 118 | 118 |
| 119 | 119 | function asyncAesCbcCipher(mode, key, data, algorithm) { | 120 | 120 | return jobPromise(() => new AESCipherJob( | 121 | | - kCryptoJobAsync, | | 121 | + kCryptoJobWebCrypto, | 122 | 122 | mode, | 123 | 123 | getCryptoKeyHandle(key), | 124 | 124 | data, | @@ -128,7 +128,7 @@ function asyncAesCbcCipher(mode, key, data, algorithm) { | 128 | 128 |
| 129 | 129 | function asyncAesKwCipher(mode, key, data) { | 130 | 130 | return jobPromise(() => new AESCipherJob( | 131 | | - kCryptoJobAsync, | | 131 | + kCryptoJobWebCrypto, | 132 | 132 | mode, | 133 | 133 | getCryptoKeyHandle(key), | 134 | 134 | data, | @@ -140,7 +140,7 @@ function asyncAesGcmCipher(mode, key, data, algorithm) { | 140 | 140 | const tagByteLength = tagLength / 8; | 141 | 141 |
| 142 | 142 | return jobPromise(() => new AESCipherJob( | 143 | | - kCryptoJobAsync, | | 143 | + kCryptoJobWebCrypto, | 144 | 144 | mode, | 145 | 145 | getCryptoKeyHandle(key), | 146 | 146 | data, | @@ -155,7 +155,7 @@ function asyncAesOcbCipher(mode, key, data, algorithm) { | 155 | 155 | const tagByteLength = tagLength / 8; | 156 | 156 |
| 157 | 157 | return jobPromise(() => new AESCipherJob( | 158 | | - kCryptoJobAsync, | | 158 | + kCryptoJobWebCrypto, | 159 | 159 | mode, | 160 | 160 | getCryptoKeyHandle(key), | 161 | 161 | data, | @@ -175,7 +175,7 @@ function aesCipher(mode, key, data, algorithm) { | 175 | 175 | } | 176 | 176 | } | 177 | 177 |
| 178 | | -async function aesGenerateKey(algorithm, extractable, keyUsages) { | | 178 | +function aesGenerateKey(algorithm, extractable, keyUsages) { | 179 | 179 | const { name, length } = algorithm; | 180 | 180 |
| 181 | 181 | const checkUsages = ['wrapKey', 'unwrapKey']; | @@ -188,14 +188,18 @@ async function aesGenerateKey(algorithm, extractable, keyUsages) { | 188 | 188 | 'Unsupported key usage for an AES key', | 189 | 189 | 'SyntaxError'); | 190 | 190 | } | | 191 | + if (usagesSet.size === 0) { | | 192 | + throw lazyDOMException( | | 193 | + 'Usages cannot be empty when creating a key.', | | 194 | + 'SyntaxError'); | | 195 | + } | 191 | 196 |
| 192 | | - const handle = await jobPromise(() => new SecretKeyGenJob(kCryptoJobAsync, length)); | 193 | | - | 194 | | - return new InternalCryptoKey( | 195 | | - handle, | | 197 | + return jobPromise(() => new SecretKeyGenJob( | | 198 | + kCryptoJobWebCrypto, | | 199 | + length, | 196 | 200 | { name, length }, | 197 | 201 | getUsagesMask(usagesSet), | 198 | | - extractable); | | 202 | + extractable)); | 199 | 203 | } | 200 | 204 |
| 201 | 205 | function aesImportKey( | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/argon2.js +32-35Lines changed: 32 additions & 35 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 3 | 3 | const { | 4 | 4 | FunctionPrototypeCall, | 5 | 5 | MathPow, | 6 | | - StringPrototypeToLowerCase, | 7 | | - TypedArrayPrototypeGetBuffer, | 8 | 6 | Uint8Array, | 9 | 7 | } = primordials; | 10 | 8 |
| @@ -14,14 +12,14 @@ const { | 14 | 12 | Argon2Job, | 15 | 13 | kCryptoJobAsync, | 16 | 14 | kCryptoJobSync, | | 15 | + kCryptoJobWebCrypto, | 17 | 16 | kTypeArgon2d, | 18 | 17 | kTypeArgon2i, | 19 | 18 | kTypeArgon2id, | 20 | 19 | } = internalBinding('crypto'); | 21 | 20 |
| 22 | 21 | const { | 23 | 22 | lazyDOMException, | 24 | | - promisify, | 25 | 23 | } = require('internal/util'); | 26 | 24 |
| 27 | 25 | const { | @@ -30,6 +28,7 @@ const { | 30 | 28 |
| 31 | 29 | const { | 32 | 30 | getArrayBufferOrView, | | 31 | + jobPromise, | 33 | 32 | } = require('internal/crypto/util'); | 34 | 33 |
| 35 | 34 | const { | @@ -143,20 +142,12 @@ function check(algorithm, parameters) { | 143 | 142 | validateString(algorithm, 'algorithm'); | 144 | 143 | validateOneOf(algorithm, 'algorithm', ['argon2d', 'argon2i', 'argon2id']); | 145 | 144 |
| 146 | | - let type; | 147 | | - switch (algorithm) { | 148 | | - case 'argon2d': | 149 | | - type = kTypeArgon2d; | 150 | | - break; | 151 | | - case 'argon2i': | 152 | | - type = kTypeArgon2i; | 153 | | - break; | 154 | | - case 'argon2id': | 155 | | - type = kTypeArgon2id; | 156 | | - break; | 157 | | - default: // unreachable | 158 | | - throw new ERR_CRYPTO_ARGON2_NOT_SUPPORTED(); | 159 | | - } | | 145 | + const type = { | | 146 | + '__proto__': null, | | 147 | + 'argon2d': kTypeArgon2d, | | 148 | + 'argon2i': kTypeArgon2i, | | 149 | + 'argon2id': kTypeArgon2id, | | 150 | + }[algorithm]; | 160 | 151 |
| 161 | 152 | validateObject(parameters, 'parameters'); | 162 | 153 |
| @@ -193,7 +184,6 @@ function check(algorithm, parameters) { | 193 | 184 | return { message, nonce, secret, associatedData, tagLength, passes, parallelism, memory, type }; | 194 | 185 | } | 195 | 186 |
| 196 | | -const argon2Promise = promisify(argon2); | 197 | 187 | function validateArgon2DeriveBitsLength(length) { | 198 | 188 | if (length === null) | 199 | 189 | throw lazyDOMException('length cannot be null', 'OperationError'); | @@ -211,32 +201,39 @@ function validateArgon2DeriveBitsLength(length) { | 211 | 201 | } | 212 | 202 | } | 213 | 203 |
| 214 | | -async function argon2DeriveBits(algorithm, baseKey, length) { | | 204 | +function argon2DeriveBits(algorithm, baseKey, length) { | 215 | 205 | validateArgon2DeriveBitsLength(length); | 216 | 206 |
| 217 | | - let result; | | 207 | + const type = { | | 208 | + '__proto__': null, | | 209 | + 'Argon2d': kTypeArgon2d, | | 210 | + 'Argon2i': kTypeArgon2i, | | 211 | + 'Argon2id': kTypeArgon2id, | | 212 | + }[algorithm.name]; | | 213 | + | | 214 | + let message; | 218 | 215 | try { | 219 | | - result = await argon2Promise( | 220 | | - StringPrototypeToLowerCase(algorithm.name), | 221 | | - { | 222 | | - // TODO(panva): call the job directly without needing to re-export the handle | 223 | | - message: getCryptoKeyHandle(baseKey).export(), | 224 | | - nonce: algorithm.nonce, | 225 | | - parallelism: algorithm.parallelism, | 226 | | - tagLength: length / 8, | 227 | | - memory: algorithm.memory, | 228 | | - passes: algorithm.passes, | 229 | | - secret: algorithm.secretValue, | 230 | | - associatedData: algorithm.associatedData, | 231 | | - }, | 232 | | - ); | | 216 | + // TODO(panva): call the job directly without needing to re-export the handle | | 217 | + message = getCryptoKeyHandle(baseKey).export(); | 233 | 218 | } catch (err) { | 234 | 219 | throw lazyDOMException( | 235 | 220 | 'The operation failed for an operation-specific reason', | 236 | 221 | { name: 'OperationError', cause: err }); | 237 | 222 | } | 238 | 223 |
| 239 | | - return TypedArrayPrototypeGetBuffer(result); | | 224 | + const empty = new Uint8Array(0); | | 225 | + | | 226 | + return jobPromise(() => new Argon2Job( | | 227 | + kCryptoJobWebCrypto, | | 228 | + message, | | 229 | + algorithm.nonce, | | 230 | + algorithm.parallelism, | | 231 | + length / 8, | | 232 | + algorithm.memory, | | 233 | + algorithm.passes, | | 234 | + algorithm.secretValue === undefined ? empty : algorithm.secretValue, | | 235 | + algorithm.associatedData === undefined ? empty : algorithm.associatedData, | | 236 | + type)); | 240 | 237 | } | 241 | 238 |
| 242 | 239 | module.exports = { | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/cfrg.js +24-36Lines changed: 24 additions & 36 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -10,7 +10,7 @@ const { Buffer } = require('buffer'); | 10 | 10 |
| 11 | 11 | const { | 12 | 12 | SignJob, | 13 | | - kCryptoJobAsync, | | 13 | + kCryptoJobWebCrypto, | 14 | 14 | kKeyFormatDER, | 15 | 15 | kKeyFormatRawPublic, | 16 | 16 | kSignJobModeSign, | @@ -75,7 +75,7 @@ function verifyAcceptableCfrgKeyUse(name, isPublic, usages) { | 75 | 75 | } | 76 | 76 | } | 77 | 77 |
| 78 | | -async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | | 78 | +function cfrgGenerateKey(algorithm, extractable, keyUsages) { | 79 | 79 | const { name } = algorithm; | 80 | 80 |
| 81 | 81 | const usageSet = new SafeSet(keyUsages); | @@ -99,23 +99,13 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | 99 | 99 | } | 100 | 100 | break; | 101 | 101 | } | 102 | | - let nid; | 103 | | - switch (name) { | 104 | | - case 'Ed25519': | 105 | | - nid = EVP_PKEY_ED25519; | 106 | | - break; | 107 | | - case 'Ed448': | 108 | | - nid = EVP_PKEY_ED448; | 109 | | - break; | 110 | | - case 'X25519': | 111 | | - nid = EVP_PKEY_X25519; | 112 | | - break; | 113 | | - case 'X448': | 114 | | - nid = EVP_PKEY_X448; | 115 | | - break; | 116 | | - } | 117 | | - | 118 | | - const handles = await jobPromise(() => new NidKeyPairGenJob(kCryptoJobAsync, nid)); | | 102 | + const nid = { | | 103 | + '__proto__': null, | | 104 | + 'Ed25519': EVP_PKEY_ED25519, | | 105 | + 'Ed448': EVP_PKEY_ED448, | | 106 | + 'X25519': EVP_PKEY_X25519, | | 107 | + 'X448': EVP_PKEY_X448, | | 108 | + }[name]; | 119 | 109 |
| 120 | 110 | let publicUsages; | 121 | 111 | let privateUsages; | @@ -136,21 +126,19 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | 136 | 126 |
| 137 | 127 | const keyAlgorithm = { name }; | 138 | 128 |
| 139 | | - const publicKey = | 140 | | - new InternalCryptoKey( | 141 | | - handles[0], | 142 | | - keyAlgorithm, | 143 | | - getUsagesMask(publicUsages), | 144 | | - true); | 145 | | - | 146 | | - const privateKey = | 147 | | - new InternalCryptoKey( | 148 | | - handles[1], | 149 | | - keyAlgorithm, | 150 | | - getUsagesMask(privateUsages), | 151 | | - extractable); | | 129 | + if (privateUsages.size === 0) { | | 130 | + throw lazyDOMException( | | 131 | + 'Usages cannot be empty when creating a key.', | | 132 | + 'SyntaxError'); | | 133 | + } | 152 | 134 |
| 153 | | - return { __proto__: null, privateKey, publicKey }; | | 135 | + return jobPromise(() => new NidKeyPairGenJob( | | 136 | + kCryptoJobWebCrypto, | | 137 | + nid, | | 138 | + keyAlgorithm, | | 139 | + getUsagesMask(publicUsages), | | 140 | + getUsagesMask(privateUsages), | | 141 | + extractable)); | 154 | 142 | } | 155 | 143 |
| 156 | 144 | function cfrgExportKey(key, format) { | @@ -251,15 +239,15 @@ function cfrgImportKey( | 251 | 239 | extractable); | 252 | 240 | } | 253 | 241 |
| 254 | | -async function eddsaSignVerify(key, data, algorithm, signature) { | | 242 | +function eddsaSignVerify(key, data, algorithm, signature) { | 255 | 243 | const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify; | 256 | 244 | const type = mode === kSignJobModeSign ? 'private' : 'public'; | 257 | 245 |
| 258 | 246 | if (getCryptoKeyType(key) !== type) | 259 | 247 | throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError'); | 260 | 248 |
| 261 | | - return await jobPromise(() => new SignJob( | 262 | | - kCryptoJobAsync, | | 249 | + return jobPromise(() => new SignJob( | | 250 | + kCryptoJobWebCrypto, | 263 | 251 | mode, | 264 | 252 | getCryptoKeyHandle(key), | 265 | 253 | undefined, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/chacha20_poly1305.js +12-8Lines changed: 12 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 7 | 7 | const { | 8 | 8 | ChaCha20Poly1305CipherJob, | 9 | 9 | SecretKeyGenJob, | 10 | | - kCryptoJobAsync, | | 10 | + kCryptoJobWebCrypto, | 11 | 11 | } = internalBinding('crypto'); | 12 | 12 |
| 13 | 13 | const { | @@ -39,15 +39,15 @@ function validateKeyLength(length) { | 39 | 39 |
| 40 | 40 | function c20pCipher(mode, key, data, algorithm) { | 41 | 41 | return jobPromise(() => new ChaCha20Poly1305CipherJob( | 42 | | - kCryptoJobAsync, | | 42 | + kCryptoJobWebCrypto, | 43 | 43 | mode, | 44 | 44 | getCryptoKeyHandle(key), | 45 | 45 | data, | 46 | 46 | algorithm.iv, | 47 | 47 | algorithm.additionalData)); | 48 | 48 | } | 49 | 49 |
| 50 | | -async function c20pGenerateKey(algorithm, extractable, keyUsages) { | | 50 | +function c20pGenerateKey(algorithm, extractable, keyUsages) { | 51 | 51 | const { name } = algorithm; | 52 | 52 |
| 53 | 53 | const checkUsages = ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']; | @@ -58,14 +58,18 @@ async function c20pGenerateKey(algorithm, extractable, keyUsages) { | 58 | 58 | `Unsupported key usage for a ${algorithm.name} key`, | 59 | 59 | 'SyntaxError'); | 60 | 60 | } | | 61 | + if (usagesSet.size === 0) { | | 62 | + throw lazyDOMException( | | 63 | + 'Usages cannot be empty when creating a key.', | | 64 | + 'SyntaxError'); | | 65 | + } | 61 | 66 |
| 62 | | - const handle = await jobPromise(() => new SecretKeyGenJob(kCryptoJobAsync, 256)); | 63 | | - | 64 | | - return new InternalCryptoKey( | 65 | | - handle, | | 67 | + return jobPromise(() => new SecretKeyGenJob( | | 68 | + kCryptoJobWebCrypto, | | 69 | + 256, | 66 | 70 | { name }, | 67 | 71 | getUsagesMask(usagesSet), | 68 | | - extractable); | | 72 | + extractable)); | 69 | 73 | } | 70 | 74 |
| 71 | 75 | function c20pImportKey( | |
|