GeezerVison is showing github.com — crypto: unify asymmetric key import through KeyObjectHandle::Init · nodejs/node@6cc4cf8
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 +8-23Lines changed: 8 additions & 23 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -10,6 +10,8 @@ const { | 10 | 10 | AESCipherJob, | 11 | 11 | KeyObjectHandle, | 12 | 12 | kCryptoJobAsync, | | 13 | + kKeyFormatJWK, | | 14 | + kKeyTypeSecret, | 13 | 15 | kKeyVariantAES_CTR_128, | 14 | 16 | kKeyVariantAES_CBC_128, | 15 | 17 | kKeyVariantAES_GCM_128, | @@ -30,7 +32,6 @@ const { | 30 | 32 | const { | 31 | 33 | hasAnyNotIn, | 32 | 34 | jobPromise, | 33 | | - validateKeyOps, | 34 | 35 | kHandle, | 35 | 36 | kKeyObject, | 36 | 37 | } = require('internal/crypto/util'); | @@ -47,6 +48,10 @@ const { | 47 | 48 | kAlgorithm, | 48 | 49 | } = require('internal/crypto/keys'); | 49 | 50 |
| | 51 | +const { | | 52 | + validateJwk, | | 53 | +} = require('internal/crypto/webcrypto_util'); | | 54 | + | 50 | 55 | const { | 51 | 56 | generateKey: _generateKey, | 52 | 57 | } = require('internal/crypto/keygen'); | @@ -245,31 +250,11 @@ function aesImportKey( | 245 | 250 | break; | 246 | 251 | } | 247 | 252 | case 'jwk': { | 248 | | - if (!keyData.kty) | 249 | | - throw lazyDOMException('Invalid keyData', 'DataError'); | 250 | | - | 251 | | - if (keyData.kty !== 'oct') | 252 | | - throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError'); | 253 | | - | 254 | | - if (usagesSet.size > 0 && | 255 | | - keyData.use !== undefined && | 256 | | - keyData.use !== 'enc') { | 257 | | - throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError'); | 258 | | - } | 259 | | - | 260 | | - validateKeyOps(keyData.key_ops, usagesSet); | 261 | | - | 262 | | - if (keyData.ext !== undefined && | 263 | | - keyData.ext === false && | 264 | | - extractable === true) { | 265 | | - throw lazyDOMException( | 266 | | - 'JWK "ext" Parameter and extractable mismatch', | 267 | | - 'DataError'); | 268 | | - } | | 253 | + validateJwk(keyData, 'oct', extractable, usagesSet, 'enc'); | 269 | 254 |
| 270 | 255 | const handle = new KeyObjectHandle(); | 271 | 256 | try { | 272 | | - handle.initJwk(keyData); | | 257 | + handle.init(kKeyTypeSecret, keyData, kKeyFormatJWK, null, null); | 273 | 258 | } catch (err) { | 274 | 259 | throw lazyDOMException( | 275 | 260 | 'Invalid keyData', { name: 'DataError', cause: err }); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/cfrg.js +20-137Lines changed: 20 additions & 137 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -6,33 +6,22 @@ const { | 6 | 6 | TypedArrayPrototypeGetBuffer, | 7 | 7 | } = primordials; | 8 | 8 |
| 9 | | -const { Buffer } = require('buffer'); | 10 | | - | 11 | 9 | const { | 12 | | - KeyObjectHandle, | 13 | 10 | SignJob, | 14 | 11 | kCryptoJobAsync, | 15 | 12 | kKeyFormatDER, | 16 | | - kKeyTypePrivate, | 17 | | - kKeyTypePublic, | | 13 | + kKeyFormatRawPublic, | 18 | 14 | kSignJobModeSign, | 19 | 15 | kSignJobModeVerify, | 20 | 16 | kWebCryptoKeyFormatPKCS8, | 21 | 17 | kWebCryptoKeyFormatRaw, | 22 | 18 | kWebCryptoKeyFormatSPKI, | 23 | 19 | } = internalBinding('crypto'); | 24 | 20 |
| 25 | | -const { | 26 | | - codes: { | 27 | | - ERR_CRYPTO_INVALID_JWK, | 28 | | - }, | 29 | | -} = require('internal/errors'); | 30 | | - | 31 | 21 | const { | 32 | 22 | getUsagesUnion, | 33 | 23 | hasAnyNotIn, | 34 | 24 | jobPromise, | 35 | | - validateKeyOps, | 36 | 25 | kHandle, | 37 | 26 | kKeyObject, | 38 | 27 | } = require('internal/crypto/util'); | @@ -48,13 +37,16 @@ const { | 48 | 37 |
| 49 | 38 | const { | 50 | 39 | InternalCryptoKey, | 51 | | - PrivateKeyObject, | 52 | | - PublicKeyObject, | 53 | | - createPrivateKey, | 54 | | - createPublicKey, | 55 | 40 | kKeyType, | 56 | 41 | } = require('internal/crypto/keys'); | 57 | 42 |
| | 43 | +const { | | 44 | + importDerKey, | | 45 | + importJwkKey, | | 46 | + importRawKey, | | 47 | + validateJwk, | | 48 | +} = require('internal/crypto/webcrypto_util'); | | 49 | + | 58 | 50 | const generateKeyPair = promisify(_generateKeyPair); | 59 | 51 |
| 60 | 52 | function verifyAcceptableCfrgKeyUse(name, isPublic, usages) { | @@ -81,39 +73,6 @@ function verifyAcceptableCfrgKeyUse(name, isPublic, usages) { | 81 | 73 | } | 82 | 74 | } | 83 | 75 |
| 84 | | -function createCFRGRawKey(name, keyData, isPublic) { | 85 | | - const handle = new KeyObjectHandle(); | 86 | | - | 87 | | - switch (name) { | 88 | | - case 'Ed25519': | 89 | | - case 'X25519': | 90 | | - if (keyData.byteLength !== 32) { | 91 | | - throw lazyDOMException( | 92 | | - `${name} raw keys must be exactly 32-bytes`, 'DataError'); | 93 | | - } | 94 | | - break; | 95 | | - case 'Ed448': | 96 | | - if (keyData.byteLength !== 57) { | 97 | | - throw lazyDOMException( | 98 | | - `${name} raw keys must be exactly 57-bytes`, 'DataError'); | 99 | | - } | 100 | | - break; | 101 | | - case 'X448': | 102 | | - if (keyData.byteLength !== 56) { | 103 | | - throw lazyDOMException( | 104 | | - `${name} raw keys must be exactly 56-bytes`, 'DataError'); | 105 | | - } | 106 | | - break; | 107 | | - } | 108 | | - | 109 | | - const keyType = isPublic ? kKeyTypePublic : kKeyTypePrivate; | 110 | | - if (!handle.initEDRaw(name, keyData, keyType)) { | 111 | | - throw lazyDOMException('Invalid keyData', 'DataError'); | 112 | | - } | 113 | | - | 114 | | - return isPublic ? new PublicKeyObject(handle) : new PrivateKeyObject(handle); | 115 | | -} | 116 | | - | 117 | 76 | async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | 118 | 77 | const { name } = algorithm; | 119 | 78 |
| @@ -243,113 +202,36 @@ function cfrgImportKey( | 243 | 202 | } | 244 | 203 | case 'spki': { | 245 | 204 | verifyAcceptableCfrgKeyUse(name, true, usagesSet); | 246 | | - try { | 247 | | - keyObject = createPublicKey({ | 248 | | - key: keyData, | 249 | | - format: 'der', | 250 | | - type: 'spki', | 251 | | - }); | 252 | | - } catch (err) { | 253 | | - throw lazyDOMException( | 254 | | - 'Invalid keyData', { name: 'DataError', cause: err }); | 255 | | - } | | 205 | + keyObject = importDerKey(keyData, true); | 256 | 206 | break; | 257 | 207 | } | 258 | 208 | case 'pkcs8': { | 259 | 209 | verifyAcceptableCfrgKeyUse(name, false, usagesSet); | 260 | | - try { | 261 | | - keyObject = createPrivateKey({ | 262 | | - key: keyData, | 263 | | - format: 'der', | 264 | | - type: 'pkcs8', | 265 | | - }); | 266 | | - } catch (err) { | 267 | | - throw lazyDOMException( | 268 | | - 'Invalid keyData', { name: 'DataError', cause: err }); | 269 | | - } | | 210 | + keyObject = importDerKey(keyData, false); | 270 | 211 | break; | 271 | 212 | } | 272 | 213 | case 'jwk': { | 273 | | - if (!keyData.kty) | 274 | | - throw lazyDOMException('Invalid keyData', 'DataError'); | 275 | | - if (keyData.kty !== 'OKP') | 276 | | - throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError'); | | 214 | + const expectedUse = (name === 'X25519' || name === 'X448') ? 'enc' : 'sig'; | | 215 | + validateJwk(keyData, 'OKP', extractable, usagesSet, expectedUse); | | 216 | + | 277 | 217 | if (keyData.crv !== name) | 278 | 218 | throw lazyDOMException( | 279 | 219 | 'JWK "crv" Parameter and algorithm name mismatch', 'DataError'); | 280 | | - const isPublic = keyData.d === undefined; | 281 | | - | 282 | | - if (usagesSet.size > 0 && keyData.use !== undefined) { | 283 | | - let checkUse; | 284 | | - switch (name) { | 285 | | - case 'Ed25519': | 286 | | - // Fall through | 287 | | - case 'Ed448': | 288 | | - checkUse = 'sig'; | 289 | | - break; | 290 | | - case 'X25519': | 291 | | - // Fall through | 292 | | - case 'X448': | 293 | | - checkUse = 'enc'; | 294 | | - break; | 295 | | - } | 296 | | - if (keyData.use !== checkUse) | 297 | | - throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError'); | 298 | | - } | 299 | | - | 300 | | - validateKeyOps(keyData.key_ops, usagesSet); | 301 | | - | 302 | | - if (keyData.ext !== undefined && | 303 | | - keyData.ext === false && | 304 | | - extractable === true) { | 305 | | - throw lazyDOMException( | 306 | | - 'JWK "ext" Parameter and extractable mismatch', | 307 | | - 'DataError'); | 308 | | - } | 309 | 220 |
| 310 | 221 | if (keyData.alg !== undefined && (name === 'Ed25519' || name === 'Ed448')) { | 311 | | - if (keyData.alg !== name && keyData.alg !== 'EdDSA') { | | 222 | + if (keyData.alg !== name && keyData.alg !== 'EdDSA') | 312 | 223 | throw lazyDOMException( | 313 | | - 'JWK "alg" does not match the requested algorithm', | 314 | | - 'DataError'); | 315 | | - } | | 224 | + 'JWK "alg" does not match the requested algorithm', 'DataError'); | 316 | 225 | } | 317 | 226 |
| 318 | | - if (!isPublic && typeof keyData.x !== 'string') { | 319 | | - throw lazyDOMException('Invalid JWK', 'DataError'); | 320 | | - } | 321 | | - | 322 | | - verifyAcceptableCfrgKeyUse( | 323 | | - name, | 324 | | - isPublic, | 325 | | - usagesSet); | 326 | | - | 327 | | - try { | 328 | | - const publicKeyObject = createCFRGRawKey( | 329 | | - name, | 330 | | - Buffer.from(keyData.x, 'base64'), | 331 | | - true); | 332 | | - | 333 | | - if (isPublic) { | 334 | | - keyObject = publicKeyObject; | 335 | | - } else { | 336 | | - keyObject = createCFRGRawKey( | 337 | | - name, | 338 | | - Buffer.from(keyData.d, 'base64'), | 339 | | - false); | 340 | | - | 341 | | - if (!createPublicKey(keyObject).equals(publicKeyObject)) { | 342 | | - throw new ERR_CRYPTO_INVALID_JWK(); | 343 | | - } | 344 | | - } | 345 | | - } catch (err) { | 346 | | - throw lazyDOMException('Invalid keyData', { name: 'DataError', cause: err }); | 347 | | - } | | 227 | + const isPublic = keyData.d === undefined; | | 228 | + verifyAcceptableCfrgKeyUse(name, isPublic, usagesSet); | | 229 | + keyObject = importJwkKey(isPublic, keyData); | 348 | 230 | break; | 349 | 231 | } | 350 | 232 | case 'raw': { | 351 | 233 | verifyAcceptableCfrgKeyUse(name, true, usagesSet); | 352 | | - keyObject = createCFRGRawKey(name, keyData, true); | | 234 | + keyObject = importRawKey(true, keyData, kKeyFormatRawPublic, name); | 353 | 235 | break; | 354 | 236 | } | 355 | 237 | default: | @@ -381,6 +263,7 @@ async function eddsaSignVerify(key, data, algorithm, signature) { | 381 | 263 | undefined, | 382 | 264 | undefined, | 383 | 265 | undefined, | | 266 | + undefined, | 384 | 267 | data, | 385 | 268 | undefined, | 386 | 269 | undefined, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/chacha20_poly1305.js +8-23Lines changed: 8 additions & 23 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -9,12 +9,13 @@ const { | 9 | 9 | ChaCha20Poly1305CipherJob, | 10 | 10 | KeyObjectHandle, | 11 | 11 | kCryptoJobAsync, | | 12 | + kKeyFormatJWK, | | 13 | + kKeyTypeSecret, | 12 | 14 | } = internalBinding('crypto'); | 13 | 15 |
| 14 | 16 | const { | 15 | 17 | hasAnyNotIn, | 16 | 18 | jobPromise, | 17 | | - validateKeyOps, | 18 | 19 | kHandle, | 19 | 20 | kKeyObject, | 20 | 21 | } = require('internal/crypto/util'); | @@ -30,6 +31,10 @@ const { | 30 | 31 | createSecretKey, | 31 | 32 | } = require('internal/crypto/keys'); | 32 | 33 |
| | 34 | +const { | | 35 | + validateJwk, | | 36 | +} = require('internal/crypto/webcrypto_util'); | | 37 | + | 33 | 38 | const { | 34 | 39 | randomBytes: _randomBytes, | 35 | 40 | } = require('internal/crypto/random'); | @@ -107,31 +112,11 @@ function c20pImportKey( | 107 | 112 | break; | 108 | 113 | } | 109 | 114 | case 'jwk': { | 110 | | - if (!keyData.kty) | 111 | | - throw lazyDOMException('Invalid keyData', 'DataError'); | 112 | | - | 113 | | - if (keyData.kty !== 'oct') | 114 | | - throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError'); | 115 | | - | 116 | | - if (usagesSet.size > 0 && | 117 | | - keyData.use !== undefined && | 118 | | - keyData.use !== 'enc') { | 119 | | - throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError'); | 120 | | - } | 121 | | - | 122 | | - validateKeyOps(keyData.key_ops, usagesSet); | 123 | | - | 124 | | - if (keyData.ext !== undefined && | 125 | | - keyData.ext === false && | 126 | | - extractable === true) { | 127 | | - throw lazyDOMException( | 128 | | - 'JWK "ext" Parameter and extractable mismatch', | 129 | | - 'DataError'); | 130 | | - } | | 115 | + validateJwk(keyData, 'oct', extractable, usagesSet, 'enc'); | 131 | 116 |
| 132 | 117 | const handle = new KeyObjectHandle(); | 133 | 118 | try { | 134 | | - handle.initJwk(keyData); | | 119 | + handle.init(kKeyTypeSecret, keyData, kKeyFormatJWK, null, null); | 135 | 120 | } catch (err) { | 136 | 121 | throw lazyDOMException( | 137 | 122 | 'Invalid keyData', { name: 'DataError', cause: err }); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/crypto/cipher.js +3-3Lines changed: 3 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -64,7 +64,7 @@ const { StringDecoder } = require('string_decoder'); | 64 | 64 |
| 65 | 65 | function rsaFunctionFor(method, defaultPadding, keyType) { | 66 | 66 | return (options, buffer) => { | 67 | | - const { format, type, data, passphrase } = | | 67 | + const { format, type, data, passphrase, namedCurve } = | 68 | 68 | keyType === 'private' ? | 69 | 69 | preparePrivateKey(options) : | 70 | 70 | preparePublicOrPrivateKey(options); | @@ -76,8 +76,8 @@ function rsaFunctionFor(method, defaultPadding, keyType) { | 76 | 76 | if (oaepLabel !== undefined) | 77 | 77 | oaepLabel = getArrayBufferOrView(oaepLabel, 'key.oaepLabel', encoding); | 78 | 78 | buffer = getArrayBufferOrView(buffer, 'buffer', encoding); | 79 | | - return method(data, format, type, passphrase, buffer, padding, oaepHash, | 80 | | - oaepLabel); | | 79 | + return method(data, format, type, passphrase, namedCurve, buffer, | | 80 | + padding, oaepHash, oaepLabel); | 81 | 81 | }; | 82 | 82 | } | 83 | 83 |
| |
|