Comparing version 4.9.3 to 4.10.0
@@ -36,14 +36,8 @@ import { decode as decodeBase64URL, encodeBase64, decodeBase64 } from '../runtime/base64url.js'; | ||
} | ||
else { | ||
let numberOfDigits = bytes[position] & 0x7f; | ||
position++; | ||
else if (length === 0x80) { | ||
length = 0; | ||
for (let i = 0; i < numberOfDigits; i++) { | ||
length = length * 256 + bytes[position]; | ||
position++; | ||
} | ||
} | ||
if (length === 0x80) { | ||
length = 0; | ||
while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { | ||
if (length > bytes.byteLength) { | ||
throw new TypeError('invalid indefinite form length'); | ||
} | ||
length++; | ||
@@ -58,2 +52,11 @@ } | ||
} | ||
else { | ||
let numberOfDigits = bytes[position] & 0x7f; | ||
position++; | ||
length = 0; | ||
for (let i = 0; i < numberOfDigits; i++) { | ||
length = length * 256 + bytes[position]; | ||
position++; | ||
} | ||
} | ||
const byteLength = position + length; | ||
@@ -85,3 +88,9 @@ return { | ||
} | ||
const spki = getSPKI(x509); | ||
let spki; | ||
try { | ||
spki = getSPKI(x509); | ||
} | ||
catch (cause) { | ||
throw new TypeError('failed to parse the X.509 certificate', { cause }); | ||
} | ||
return importPublic(spki, alg, options); | ||
@@ -88,0 +97,0 @@ } |
@@ -79,2 +79,8 @@ import { isCloudflareWorkers } from '../runtime/env.js'; | ||
} | ||
case 'EdDSA': { | ||
if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { | ||
throw unusable('Ed25519 or Ed448'); | ||
} | ||
break; | ||
} | ||
case 'ES256': | ||
@@ -120,6 +126,13 @@ case 'ES384': | ||
} | ||
case 'ECDH': | ||
if (!isAlgorithm(key.algorithm, 'ECDH')) | ||
throw unusable('ECDH'); | ||
case 'ECDH': { | ||
switch (key.algorithm.name) { | ||
case 'ECDH': | ||
case 'X25519': | ||
case 'X448': | ||
break; | ||
default: | ||
throw unusable('ECDH, X25519, or X448'); | ||
} | ||
break; | ||
} | ||
case 'PBES2-HS256+A128KW': | ||
@@ -126,0 +139,0 @@ case 'PBES2-HS384+A192KW': |
@@ -47,4 +47,10 @@ import { isCloudflareWorkers } from './env.js'; | ||
return 'P-521'; | ||
case isCloudflareWorkers() && findOid(keyData, [0x2b, 0x65, 0x70]): | ||
case findOid(keyData, [0x2b, 0x65, 0x6e]): | ||
return 'X25519'; | ||
case findOid(keyData, [0x2b, 0x65, 0x6f]): | ||
return 'X448'; | ||
case findOid(keyData, [0x2b, 0x65, 0x70]): | ||
return 'Ed25519'; | ||
case findOid(keyData, [0x2b, 0x65, 0x71]): | ||
return 'Ed448'; | ||
default: | ||
@@ -100,7 +106,9 @@ throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type'); | ||
case 'ECDH-ES+A192KW': | ||
case 'ECDH-ES+A256KW': | ||
algorithm = { name: 'ECDH', namedCurve: getNamedCurve(keyData) }; | ||
case 'ECDH-ES+A256KW': { | ||
const namedCurve = getNamedCurve(keyData); | ||
algorithm = namedCurve.startsWith('P-') ? { name: 'ECDH', namedCurve } : { name: namedCurve }; | ||
keyUsages = isPublic ? [] : ['deriveBits']; | ||
break; | ||
case isCloudflareWorkers() && 'EdDSA': | ||
} | ||
case isCloudflareWorkers() && 'EdDSA': { | ||
const namedCurve = getNamedCurve(keyData).toUpperCase(); | ||
@@ -110,2 +118,7 @@ algorithm = { name: `NODE-${namedCurve}`, namedCurve: `NODE-${namedCurve}` }; | ||
break; | ||
} | ||
case 'EdDSA': | ||
algorithm = { name: getNamedCurve(keyData) }; | ||
keyUsages = isPublic ? ['verify'] : ['sign']; | ||
break; | ||
default: | ||
@@ -112,0 +125,0 @@ throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value'); |
@@ -16,6 +16,17 @@ import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.js'; | ||
const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); | ||
let length; | ||
if (publicKey.algorithm.name === 'X25519') { | ||
length = 256; | ||
} | ||
else if (publicKey.algorithm.name === 'X448') { | ||
length = 448; | ||
} | ||
else { | ||
length = | ||
Math.ceil(parseInt(publicKey.algorithm.namedCurve.substr(-3), 10) / 8) << 3; | ||
} | ||
const sharedSecret = new Uint8Array(await crypto.subtle.deriveBits({ | ||
name: 'ECDH', | ||
name: publicKey.algorithm.name, | ||
public: publicKey, | ||
}, privateKey, Math.ceil(parseInt(privateKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3)); | ||
}, privateKey, length)); | ||
return concatKdf(sharedSecret, keyLength, value); | ||
@@ -33,3 +44,5 @@ } | ||
} | ||
return ['P-256', 'P-384', 'P-521'].includes(key.algorithm.namedCurve); | ||
return (['P-256', 'P-384', 'P-521'].includes(key.algorithm.namedCurve) || | ||
key.algorithm.name === 'X25519' || | ||
key.algorithm.name === 'X448'); | ||
} |
export function isCloudflareWorkers() { | ||
return typeof WebSocketPair === 'function'; | ||
return (typeof WebSocketPair !== 'undefined' || | ||
(typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') || | ||
(typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel')); | ||
} |
@@ -54,3 +54,3 @@ import { isCloudflareWorkers } from './env.js'; | ||
export async function generateKeyPair(alg, options) { | ||
var _a, _b; | ||
var _a, _b, _c; | ||
let algorithm; | ||
@@ -116,13 +116,40 @@ let keyUsages; | ||
break; | ||
case 'EdDSA': | ||
keyUsages = ['sign', 'verify']; | ||
const crv = (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : 'Ed25519'; | ||
switch (crv) { | ||
case 'Ed25519': | ||
case 'Ed448': | ||
algorithm = { name: crv }; | ||
break; | ||
default: | ||
throw new JOSENotSupported('Invalid or unsupported crv option provided'); | ||
} | ||
break; | ||
case 'ECDH-ES': | ||
case 'ECDH-ES+A128KW': | ||
case 'ECDH-ES+A192KW': | ||
case 'ECDH-ES+A256KW': | ||
algorithm = { name: 'ECDH', namedCurve: (_a = options === null || options === void 0 ? void 0 : options.crv) !== null && _a !== void 0 ? _a : 'P-256' }; | ||
case 'ECDH-ES+A256KW': { | ||
keyUsages = ['deriveKey', 'deriveBits']; | ||
const crv = (_b = options === null || options === void 0 ? void 0 : options.crv) !== null && _b !== void 0 ? _b : 'P-256'; | ||
switch (crv) { | ||
case 'P-256': | ||
case 'P-384': | ||
case 'P-521': { | ||
algorithm = { name: 'ECDH', namedCurve: crv }; | ||
break; | ||
} | ||
case 'X25519': | ||
case 'X448': | ||
algorithm = { name: crv }; | ||
break; | ||
default: | ||
throw new JOSENotSupported('Invalid or unsupported crv option provided, supported values are P-256, P-384, P-521, X25519, and X448'); | ||
} | ||
break; | ||
} | ||
default: | ||
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); | ||
} | ||
return (crypto.subtle.generateKey(algorithm, (_b = options === null || options === void 0 ? void 0 : options.extractable) !== null && _b !== void 0 ? _b : false, keyUsages)); | ||
return (crypto.subtle.generateKey(algorithm, (_c = options === null || options === void 0 ? void 0 : options.extractable) !== null && _c !== void 0 ? _c : false, keyUsages)); | ||
} |
@@ -112,5 +112,23 @@ import { isCloudflareWorkers } from './env.js'; | ||
default: | ||
throw new JOSENotSupported('Invalid or unsupported JWK "crv" (Subtype of Key Pair) Parameter value'); | ||
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); | ||
} | ||
break; | ||
case 'OKP': { | ||
switch (jwk.alg) { | ||
case 'EdDSA': | ||
algorithm = { name: jwk.crv }; | ||
keyUsages = jwk.d ? ['sign'] : ['verify']; | ||
break; | ||
case 'ECDH-ES': | ||
case 'ECDH-ES+A128KW': | ||
case 'ECDH-ES+A192KW': | ||
case 'ECDH-ES+A256KW': | ||
algorithm = { name: jwk.crv }; | ||
keyUsages = jwk.d ? ['deriveBits'] : []; | ||
break; | ||
default: | ||
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); | ||
} | ||
break; | ||
} | ||
default: | ||
@@ -117,0 +135,0 @@ throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); |
@@ -25,2 +25,4 @@ import { isCloudflareWorkers } from './env.js'; | ||
return { name: namedCurve, namedCurve }; | ||
case 'EdDSA': | ||
return { name: algorithm.name }; | ||
default: | ||
@@ -27,0 +29,0 @@ throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); |
@@ -39,14 +39,8 @@ "use strict"; | ||
} | ||
else { | ||
let numberOfDigits = bytes[position] & 0x7f; | ||
position++; | ||
else if (length === 0x80) { | ||
length = 0; | ||
for (let i = 0; i < numberOfDigits; i++) { | ||
length = length * 256 + bytes[position]; | ||
position++; | ||
} | ||
} | ||
if (length === 0x80) { | ||
length = 0; | ||
while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { | ||
if (length > bytes.byteLength) { | ||
throw new TypeError('invalid indefinite form length'); | ||
} | ||
length++; | ||
@@ -61,2 +55,11 @@ } | ||
} | ||
else { | ||
let numberOfDigits = bytes[position] & 0x7f; | ||
position++; | ||
length = 0; | ||
for (let i = 0; i < numberOfDigits; i++) { | ||
length = length * 256 + bytes[position]; | ||
position++; | ||
} | ||
} | ||
const byteLength = position + length; | ||
@@ -89,3 +92,9 @@ return { | ||
} | ||
const spki = getSPKI(x509); | ||
let spki; | ||
try { | ||
spki = getSPKI(x509); | ||
} | ||
catch (cause) { | ||
throw new TypeError('failed to parse the X.509 certificate', { cause }); | ||
} | ||
return (0, asn1_js_1.fromSPKI)(spki, alg, options); | ||
@@ -92,0 +101,0 @@ } |
@@ -82,2 +82,8 @@ "use strict"; | ||
} | ||
case 'EdDSA': { | ||
if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { | ||
throw unusable('Ed25519 or Ed448'); | ||
} | ||
break; | ||
} | ||
case 'ES256': | ||
@@ -124,6 +130,13 @@ case 'ES384': | ||
} | ||
case 'ECDH': | ||
if (!isAlgorithm(key.algorithm, 'ECDH')) | ||
throw unusable('ECDH'); | ||
case 'ECDH': { | ||
switch (key.algorithm.name) { | ||
case 'ECDH': | ||
case 'X25519': | ||
case 'X448': | ||
break; | ||
default: | ||
throw unusable('ECDH, X25519, or X448'); | ||
} | ||
break; | ||
} | ||
case 'PBES2-HS256+A128KW': | ||
@@ -130,0 +143,0 @@ case 'PBES2-HS384+A192KW': |
@@ -36,14 +36,8 @@ import { decode as decodeBase64URL, encodeBase64, decodeBase64 } from '../runtime/base64url.js'; | ||
} | ||
else { | ||
let numberOfDigits = bytes[position] & 0x7f; | ||
position++; | ||
else if (length === 0x80) { | ||
length = 0; | ||
for (let i = 0; i < numberOfDigits; i++) { | ||
length = length * 256 + bytes[position]; | ||
position++; | ||
} | ||
} | ||
if (length === 0x80) { | ||
length = 0; | ||
while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { | ||
if (length > bytes.byteLength) { | ||
throw new TypeError('invalid indefinite form length'); | ||
} | ||
length++; | ||
@@ -58,2 +52,11 @@ } | ||
} | ||
else { | ||
let numberOfDigits = bytes[position] & 0x7f; | ||
position++; | ||
length = 0; | ||
for (let i = 0; i < numberOfDigits; i++) { | ||
length = length * 256 + bytes[position]; | ||
position++; | ||
} | ||
} | ||
const byteLength = position + length; | ||
@@ -85,3 +88,9 @@ return { | ||
} | ||
const spki = getSPKI(x509); | ||
let spki; | ||
try { | ||
spki = getSPKI(x509); | ||
} | ||
catch (cause) { | ||
throw new TypeError('failed to parse the X.509 certificate', { cause }); | ||
} | ||
return importPublic(spki, alg, options); | ||
@@ -88,0 +97,0 @@ } |
@@ -79,2 +79,8 @@ import { isCloudflareWorkers } from '../runtime/env.js'; | ||
} | ||
case 'EdDSA': { | ||
if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') { | ||
throw unusable('Ed25519 or Ed448'); | ||
} | ||
break; | ||
} | ||
case 'ES256': | ||
@@ -120,6 +126,13 @@ case 'ES384': | ||
} | ||
case 'ECDH': | ||
if (!isAlgorithm(key.algorithm, 'ECDH')) | ||
throw unusable('ECDH'); | ||
case 'ECDH': { | ||
switch (key.algorithm.name) { | ||
case 'ECDH': | ||
case 'X25519': | ||
case 'X448': | ||
break; | ||
default: | ||
throw unusable('ECDH, X25519, or X448'); | ||
} | ||
break; | ||
} | ||
case 'PBES2-HS256+A128KW': | ||
@@ -126,0 +139,0 @@ case 'PBES2-HS384+A192KW': |
{ | ||
"name": "jose", | ||
"version": "4.9.3", | ||
"description": "'JSON Web Almost Everything' - JWA, JWS, JWE, JWT, JWK, JWKS with no dependencies using runtime's native crypto", | ||
"version": "4.10.0", | ||
"description": "'JSON Web Almost Everything' - JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, and other Web-interoperable runtimes", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "browser", |
# jose | ||
> "JSON Web Almost Everything" - JWA, JWS, JWE, JWT, JWK, JWKS with no dependencies using runtime's native crypto in Node.js, Browser, Cloudflare Workers, Electron, and Deno. | ||
> "JSON Web Almost Everything" - JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, and other Web-interoperable runtimes. | ||
@@ -25,2 +25,4 @@ ## Implemented specs & features | ||
## Dependencies: 0 | ||
## Documentation | ||
@@ -104,3 +106,3 @@ | ||
- it supports Browser, Cloudflare Workers, and Deno runtimes | ||
- it supports Browser, Deno, Cloudflare Workers, and other Web-interoperable runtimes | ||
- it supports encrypted JWTs (i.e. in JWE format) | ||
@@ -107,0 +109,0 @@ - supports secp256k1, Ed25519, Ed448, X25519, and X448 |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
556288
13750
162