| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ccd756d commit b46d52b
25 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,6 +9,8 @@ const { | |||
| 9 | 9 | AESCipherJob, | |
| 10 | 10 | KeyObjectHandle, | |
| 11 | 11 | kCryptoJobAsync, | |
| 12 | + kKeyFormatJWK, | ||
| 13 | + kKeyTypeSecret, | ||
| 12 | 14 | kKeyVariantAES_CTR_128, | |
| 13 | 15 | kKeyVariantAES_CBC_128, | |
| 14 | 16 | kKeyVariantAES_GCM_128, | |
@@ -29,7 +31,6 @@ const { | |||
| 29 | 31 | const { | |
| 30 | 32 | hasAnyNotIn, | |
| 31 | 33 | jobPromise, | |
| 32 | - validateKeyOps, | ||
| 33 | 34 | kHandle, | |
| 34 | 35 | kKeyObject, | |
| 35 | 36 | } = require('internal/crypto/util'); | |
@@ -46,6 +47,10 @@ const { | |||
| 46 | 47 | kAlgorithm, | |
| 47 | 48 | } = require('internal/crypto/keys'); | |
| 48 | 49 | ||
| 50 | + const { | ||
| 51 | + validateJwk, | ||
| 52 | + } = require('internal/crypto/webcrypto_util'); | ||
| 53 | + | ||
| 49 | 54 | const { | |
| 50 | 55 | generateKey: _generateKey, | |
| 51 | 56 | } = require('internal/crypto/keygen'); | |
@@ -244,31 +249,11 @@ function aesImportKey( | |||
| 244 | 249 | break; | |
| 245 | 250 | } | |
| 246 | 251 | case 'jwk': { | |
| 247 | - if (!keyData.kty) | ||
| 248 | - throw lazyDOMException('Invalid keyData', 'DataError'); | ||
| 249 | - | ||
| 250 | - if (keyData.kty !== 'oct') | ||
| 251 | - throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError'); | ||
| 252 | - | ||
| 253 | - if (usagesSet.size > 0 && | ||
| 254 | - keyData.use !== undefined && | ||
| 255 | - keyData.use !== 'enc') { | ||
| 256 | - throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError'); | ||
| 257 | - } | ||
| 258 | - | ||
| 259 | - validateKeyOps(keyData.key_ops, usagesSet); | ||
| 260 | - | ||
| 261 | - if (keyData.ext !== undefined && | ||
| 262 | - keyData.ext === false && | ||
| 263 | - extractable === true) { | ||
| 264 | - throw lazyDOMException( | ||
| 265 | - 'JWK "ext" Parameter and extractable mismatch', | ||
| 266 | - 'DataError'); | ||
| 267 | - } | ||
| 252 | + validateJwk(keyData, 'oct', extractable, usagesSet, 'enc'); | ||
| 268 | 253 | ||
| 269 | 254 | const handle = new KeyObjectHandle(); | |
| 270 | 255 | try { | |
| 271 | - handle.initJwk(keyData); | ||
| 256 | + handle.init(kKeyTypeSecret, keyData, kKeyFormatJWK, null, null); | ||
| 272 | 257 | } catch (err) { | |
| 273 | 258 | throw lazyDOMException( | |
| 274 | 259 | 'Invalid keyData', { name: 'DataError', cause: err }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,32 +3,27 @@ | |||
| 3 | 3 | const { | |
| 4 | 4 | SafeSet, | |
| 5 | 5 | StringPrototypeToLowerCase, | |
| 6 | + TypedArrayPrototypeGetBuffer, | ||
| 6 | 7 | } = primordials; | |
| 7 | 8 | ||
| 8 | 9 | const { Buffer } = require('buffer'); | |
| 9 | 10 | ||
| 10 | 11 | const { | |
| 11 | - ECKeyExportJob, | ||
| 12 | - KeyObjectHandle, | ||
| 13 | 12 | SignJob, | |
| 14 | 13 | kCryptoJobAsync, | |
| 15 | - kKeyTypePrivate, | ||
| 16 | - kKeyTypePublic, | ||
| 14 | + kKeyFormatDER, | ||
| 15 | + kKeyFormatRawPublic, | ||
| 17 | 16 | kSignJobModeSign, | |
| 18 | 17 | kSignJobModeVerify, | |
| 18 | + kWebCryptoKeyFormatPKCS8, | ||
| 19 | + kWebCryptoKeyFormatRaw, | ||
| 20 | + kWebCryptoKeyFormatSPKI, | ||
| 19 | 21 | } = internalBinding('crypto'); | |
| 20 | 22 | ||
| 21 | - const { | ||
| 22 | - codes: { | ||
| 23 | - ERR_CRYPTO_INVALID_JWK, | ||
| 24 | - }, | ||
| 25 | - } = require('internal/errors'); | ||
| 26 | - | ||
| 27 | 23 | const { | |
| 28 | 24 | getUsagesUnion, | |
| 29 | 25 | hasAnyNotIn, | |
| 30 | 26 | jobPromise, | |
| 31 | - validateKeyOps, | ||
| 32 | 27 | kHandle, | |
| 33 | 28 | kKeyObject, | |
| 34 | 29 | } = require('internal/crypto/util'); | |
@@ -44,13 +39,16 @@ const { | |||
| 44 | 39 | ||
| 45 | 40 | const { | |
| 46 | 41 | InternalCryptoKey, | |
| 47 | - PrivateKeyObject, | ||
| 48 | - PublicKeyObject, | ||
| 49 | - createPrivateKey, | ||
| 50 | - createPublicKey, | ||
| 51 | 42 | kKeyType, | |
| 52 | 43 | } = require('internal/crypto/keys'); | |
| 53 | 44 | ||
| 45 | + const { | ||
| 46 | + importDerKey, | ||
| 47 | + importJwkKey, | ||
| 48 | + importRawKey, | ||
| 49 | + validateJwk, | ||
| 50 | + } = require('internal/crypto/webcrypto_util'); | ||
| 51 | + | ||
| 54 | 52 | const generateKeyPair = promisify(_generateKeyPair); | |
| 55 | 53 | ||
| 56 | 54 | function verifyAcceptableCfrgKeyUse(name, isPublic, usages) { | |
@@ -77,39 +75,6 @@ function verifyAcceptableCfrgKeyUse(name, isPublic, usages) { | |||
| 77 | 75 | } | |
| 78 | 76 | } | |
| 79 | 77 | ||
| 80 | - function createCFRGRawKey(name, keyData, isPublic) { | ||
| 81 | - const handle = new KeyObjectHandle(); | ||
| 82 | - | ||
| 83 | - switch (name) { | ||
| 84 | - case 'Ed25519': | ||
| 85 | - case 'X25519': | ||
| 86 | - if (keyData.byteLength !== 32) { | ||
| 87 | - throw lazyDOMException( | ||
| 88 | - `${name} raw keys must be exactly 32-bytes`, 'DataError'); | ||
| 89 | - } | ||
| 90 | - break; | ||
| 91 | - case 'Ed448': | ||
| 92 | - if (keyData.byteLength !== 57) { | ||
| 93 | - throw lazyDOMException( | ||
| 94 | - `${name} raw keys must be exactly 57-bytes`, 'DataError'); | ||
| 95 | - } | ||
| 96 | - break; | ||
| 97 | - case 'X448': | ||
| 98 | - if (keyData.byteLength !== 56) { | ||
| 99 | - throw lazyDOMException( | ||
| 100 | - `${name} raw keys must be exactly 56-bytes`, 'DataError'); | ||
| 101 | - } | ||
| 102 | - break; | ||
| 103 | - } | ||
| 104 | - | ||
| 105 | - const keyType = isPublic ? kKeyTypePublic : kKeyTypePrivate; | ||
| 106 | - if (!handle.initEDRaw(name, keyData, keyType)) { | ||
| 107 | - throw lazyDOMException('Invalid keyData', 'DataError'); | ||
| 108 | - } | ||
| 109 | - | ||
| 110 | - return isPublic ? new PublicKeyObject(handle) : new PrivateKeyObject(handle); | ||
| 111 | - } | ||
| 112 | - | ||
| 113 | 78 | async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | |
| 114 | 79 | const { name } = algorithm; | |
| 115 | 80 | ||
@@ -171,7 +136,7 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | |||
| 171 | 136 | case 'X25519': | |
| 172 | 137 | // Fall through | |
| 173 | 138 | case 'X448': | |
| 174 | - publicUsages = new SafeSet(); | ||
| 139 | + publicUsages = []; | ||
| 175 | 140 | privateUsages = getUsagesUnion(usageSet, 'deriveKey', 'deriveBits'); | |
| 176 | 141 | break; | |
| 177 | 142 | } | |
@@ -196,10 +161,29 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) { | |||
| 196 | 161 | } | |
| 197 | 162 | ||
| 198 | 163 | function cfrgExportKey(key, format) { | |
| 199 | - return jobPromise(() => new ECKeyExportJob( | ||
| 200 | - kCryptoJobAsync, | ||
| 201 | - format, | ||
| 202 | - key[kKeyObject][kHandle])); | ||
| 164 | + try { | ||
| 165 | + switch (format) { | ||
| 166 | + case kWebCryptoKeyFormatRaw: { | ||
| 167 | + const handle = key[kKeyObject][kHandle]; | ||
| 168 | + return TypedArrayPrototypeGetBuffer( | ||
| 169 | + key[kKeyType] === 'private' ? handle.rawPrivateKey() : handle.rawPublicKey()); | ||
| 170 | + } | ||
| 171 | + case kWebCryptoKeyFormatSPKI: { | ||
| 172 | + return TypedArrayPrototypeGetBuffer( | ||
| 173 | + key[kKeyObject][kHandle].export(kKeyFormatDER, kWebCryptoKeyFormatSPKI)); | ||
| 174 | + } | ||
| 175 | + case kWebCryptoKeyFormatPKCS8: { | ||
| 176 | + return TypedArrayPrototypeGetBuffer( | ||
| 177 | + key[kKeyObject][kHandle].export(kKeyFormatDER, kWebCryptoKeyFormatPKCS8, null, null)); | ||
| 178 | + } | ||
| 179 | + default: | ||
| 180 | + return undefined; | ||
| 181 | + } | ||
| 182 | + } catch (err) { | ||
| 183 | + throw lazyDOMException( | ||
| 184 | + 'The operation failed for an operation-specific reason', | ||
| 185 | + { name: 'OperationError', cause: err }); | ||
| 186 | + } | ||
| 203 | 187 | } | |
| 204 | 188 | ||
| 205 | 189 | function cfrgImportKey( | |
@@ -220,113 +204,42 @@ function cfrgImportKey( | |||
| 220 | 204 | } | |
| 221 | 205 | case 'spki': { | |
| 222 | 206 | verifyAcceptableCfrgKeyUse(name, true, usagesSet); | |
| 223 | - try { | ||
| 224 | - keyObject = createPublicKey({ | ||
| 225 | - key: keyData, | ||
| 226 | - format: 'der', | ||
| 227 | - type: 'spki', | ||
| 228 | - }); | ||
| 229 | - } catch (err) { | ||
| 230 | - throw lazyDOMException( | ||
| 231 | - 'Invalid keyData', { name: 'DataError', cause: err }); | ||
| 232 | - } | ||
| 207 | + keyObject = importDerKey(keyData, true); | ||
| 233 | 208 | break; | |
| 234 | 209 | } | |
| 235 | 210 | case 'pkcs8': { | |
| 236 | 211 | verifyAcceptableCfrgKeyUse(name, false, usagesSet); | |
| 237 | - try { | ||
| 238 | - keyObject = createPrivateKey({ | ||
| 239 | - key: keyData, | ||
| 240 | - format: 'der', | ||
| 241 | - type: 'pkcs8', | ||
| 242 | - }); | ||
| 243 | - } catch (err) { | ||
| 244 | - throw lazyDOMException( | ||
| 245 | - 'Invalid keyData', { name: 'DataError', cause: err }); | ||
| 246 | - } | ||
| 212 | + keyObject = importDerKey(keyData, false); | ||
| 247 | 213 | break; | |
| 248 | 214 | } | |
| 249 | 215 | case 'jwk': { | |
| 250 | - if (!keyData.kty) | ||
| 251 | - throw lazyDOMException('Invalid keyData', 'DataError'); | ||
| 252 | - if (keyData.kty !== 'OKP') | ||
| 253 | - throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError'); | ||
| 216 | + const expectedUse = (name === 'X25519' || name === 'X448') ? 'enc' : 'sig'; | ||
| 217 | + validateJwk(keyData, 'OKP', extractable, usagesSet, expectedUse); | ||
| 218 | + | ||
| 254 | 219 | if (keyData.crv !== name) | |
| 255 | 220 | throw lazyDOMException( | |
| 256 | 221 | 'JWK "crv" Parameter and algorithm name mismatch', 'DataError'); | |
| 257 | - const isPublic = keyData.d === undefined; | ||
| 258 | - | ||
| 259 | - if (usagesSet.size > 0 && keyData.use !== undefined) { | ||
| 260 | - let checkUse; | ||
| 261 | - switch (name) { | ||
| 262 | - case 'Ed25519': | ||
| 263 | - // Fall through | ||
| 264 | - case 'Ed448': | ||
| 265 | - checkUse = 'sig'; | ||
| 266 | - break; | ||
| 267 | - case 'X25519': | ||
| 268 | - // Fall through | ||
| 269 | - case 'X448': | ||
| 270 | - checkUse = 'enc'; | ||
| 271 | - break; | ||
| 272 | - } | ||
| 273 | - if (keyData.use !== checkUse) | ||
| 274 | - throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError'); | ||
| 275 | - } | ||
| 276 | - | ||
| 277 | - validateKeyOps(keyData.key_ops, usagesSet); | ||
| 278 | - | ||
| 279 | - if (keyData.ext !== undefined && | ||
| 280 | - keyData.ext === false && | ||
| 281 | - extractable === true) { | ||
| 282 | - throw lazyDOMException( | ||
| 283 | - 'JWK "ext" Parameter and extractable mismatch', | ||
| 284 | - 'DataError'); | ||
| 285 | - } | ||
| 286 | 222 | ||
| 287 | 223 | if (keyData.alg !== undefined && (name === 'Ed25519' || name === 'Ed448')) { | |
| 288 | - if (keyData.alg !== name && keyData.alg !== 'EdDSA') { | ||
| 224 | + if (keyData.alg !== name && keyData.alg !== 'EdDSA') | ||
| 289 | 225 | throw lazyDOMException( | |
| 290 | - 'JWK "alg" does not match the requested algorithm', | ||
| 291 | - 'DataError'); | ||
| 292 | - } | ||
| 226 | + 'JWK "alg" does not match the requested algorithm', 'DataError'); | ||
| 293 | 227 | } | |
| 294 | 228 | ||
| 295 | - if (!isPublic && typeof keyData.x !== 'string') { | ||
| 296 | - throw lazyDOMException('Invalid JWK', 'DataError'); | ||
| 297 | - } | ||
| 298 | - | ||
| 299 | - verifyAcceptableCfrgKeyUse( | ||
| 300 | - name, | ||
| 301 | - isPublic, | ||
| 302 | - usagesSet); | ||
| 303 | - | ||
| 304 | - try { | ||
| 305 | - const publicKeyObject = createCFRGRawKey( | ||
| 306 | - name, | ||
| 307 | - Buffer.from(keyData.x, 'base64'), | ||
| 308 | - true); | ||
| 309 | - | ||
| 310 | - if (isPublic) { | ||
| 311 | - keyObject = publicKeyObject; | ||
| 312 | - } else { | ||
| 313 | - keyObject = createCFRGRawKey( | ||
| 314 | - name, | ||
| 315 | - Buffer.from(keyData.d, 'base64'), | ||
| 316 | - false); | ||
| 229 | + const isPublic = keyData.d === undefined; | ||
| 230 | + verifyAcceptableCfrgKeyUse(name, isPublic, usagesSet); | ||
| 231 | + keyObject = importJwkKey(isPublic, keyData); | ||
| 317 | 232 | ||
| 318 | - if (!createPublicKey(keyObject).equals(publicKeyObject)) { | ||
| 319 | - throw new ERR_CRYPTO_INVALID_JWK(); | ||
| 320 | - } | ||
| 321 | - } | ||
| 322 | - } catch (err) { | ||
| 323 | - throw lazyDOMException('Invalid keyData', { name: 'DataError', cause: err }); | ||
| 233 | + if (!isPublic) { | ||
| 234 | + const publicKey = Buffer.from(keyData.x, 'base64url'); | ||
| 235 | + if (!Buffer.from(keyObject[kHandle].rawPublicKey()).equals(publicKey)) | ||
| 236 | + throw lazyDOMException('Invalid keyData', 'DataError'); | ||
| 324 | 237 | } | |
| 325 | 238 | break; | |
| 326 | 239 | } | |
| 327 | 240 | case 'raw': { | |
| 328 | 241 | verifyAcceptableCfrgKeyUse(name, true, usagesSet); | |
| 329 | - keyObject = createCFRGRawKey(name, keyData, true); | ||
| 242 | + keyObject = importRawKey(true, keyData, kKeyFormatRawPublic, name); | ||
| 330 | 243 | break; | |
| 331 | 244 | } | |
| 332 | 245 | default: | |
@@ -340,7 +253,7 @@ function cfrgImportKey( | |||
| 340 | 253 | return new InternalCryptoKey( | |
| 341 | 254 | keyObject, | |
| 342 | 255 | { name }, | |
| 343 | - usagesSet, | ||
| 256 | + keyUsages, | ||
| 344 | 257 | extractable); | |
| 345 | 258 | } | |
| 346 | 259 | ||
@@ -358,6 +271,7 @@ async function eddsaSignVerify(key, data, algorithm, signature) { | |||
| 358 | 271 | undefined, | |
| 359 | 272 | undefined, | |
| 360 | 273 | undefined, | |
| 274 | + undefined, | ||
| 361 | 275 | data, | |
| 362 | 276 | undefined, | |
| 363 | 277 | undefined, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments