@@ -49,5 +49,6 @@ /** | ||
| /** | ||
| * Sets the JWE Key Management parameters to be used when encrypting the Content Encryption Key. | ||
| * You do not need to invoke this method, it is only really intended for test and vector | ||
| * validation purposes. | ||
| * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is | ||
| * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or | ||
| * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed | ||
| * and missing. | ||
| * | ||
@@ -54,0 +55,0 @@ * @param parameters JWE Key Management parameters. |
@@ -24,5 +24,5 @@ /** | ||
| * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is | ||
| * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or | ||
| * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed | ||
| * and missing. | ||
| * really only needed for ECDH based algorithms when utilizing the "apu" (Agreement PartyUInfo) or | ||
| * "apv" (Agreement PartyVInfo) parameters. Other parameters will always be randomly generated | ||
| * when needed and missing. | ||
| * | ||
@@ -29,0 +29,0 @@ * @param parameters JWE Key Management parameters. |
@@ -20,4 +20,5 @@ /** | ||
| * | ||
| * Note: The function's purpose is to resolve public keys used for verifying signatures and will not | ||
| * work for public encryption keys. | ||
| * > [!NOTE]\ | ||
| * > The function's purpose is to resolve public keys used for verifying signatures and will not work | ||
| * > for public encryption keys. | ||
| * | ||
@@ -24,0 +25,0 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well |
@@ -11,2 +11,6 @@ /** | ||
| * | ||
| * > [!NOTE]\ | ||
| * > Known caveat: Expect Type-related issues when passing the inputs through to fetch-like modules, | ||
| * > they hardly ever get their typings inline with actual fetch, you should `@ts-expect-error` them. | ||
| * | ||
| * import ky from 'ky' | ||
@@ -113,5 +117,6 @@ * | ||
| /** | ||
| * DANGER ZONE - This option has security implications that must be understood, assessed for | ||
| * applicability, and accepted before use. It is critical that the JSON Web Key Set cache only be | ||
| * writable by your own code. | ||
| * > [!WARNING]\ | ||
| * > This option has security implications that must be understood, assessed for applicability, and | ||
| * > accepted before use. It is critical that the JSON Web Key Set cache only be writable by your own | ||
| * > code. | ||
| * | ||
@@ -212,4 +217,5 @@ * This option is intended for cloud computing runtimes that cannot keep an in memory cache between | ||
| * | ||
| * Note: The function's purpose is to resolve public keys used for verifying signatures and will not | ||
| * work for public encryption keys. | ||
| * > [!NOTE]\ | ||
| * > The function's purpose is to resolve public keys used for verifying signatures and will not work | ||
| * > for public encryption keys. | ||
| * | ||
@@ -216,0 +222,0 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well |
@@ -38,5 +38,5 @@ /** | ||
| * Sets the JWE Key Management parameters to be used when encrypting. Use of this is method is | ||
| * really only needed for ECDH based algorithms when utilizing the Agreement PartyUInfo or | ||
| * Agreement PartyVInfo parameters. Other parameters will always be randomly generated when needed | ||
| * and missing. | ||
| * really only needed for ECDH based algorithms when utilizing the "apu" (Agreement PartyUInfo) or | ||
| * "apv" (Agreement PartyVInfo) parameters. Other parameters will always be randomly generated | ||
| * when needed and missing. | ||
| * | ||
@@ -43,0 +43,0 @@ * @param parameters JWE Key Management parameters. |
@@ -36,4 +36,5 @@ /** | ||
| * | ||
| * Note: The `privateKey` is generated with `extractable` set to `false` by default. See | ||
| * {@link GenerateKeyPairOptions.extractable} to generate an extractable `privateKey`. | ||
| * > [!NOTE]\ | ||
| * > The `privateKey` is generated with `extractable` set to `false` by default. See | ||
| * > {@link GenerateKeyPairOptions.extractable} to generate an extractable `privateKey`. | ||
| * | ||
@@ -40,0 +41,0 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well |
@@ -12,4 +12,5 @@ /** | ||
| * | ||
| * Note: Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as | ||
| * {@link !CryptoKey} this option has no effect for them. | ||
| * > [!NOTE]\ | ||
| * > Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as | ||
| * > {@link !CryptoKey} this option has no effect for them. | ||
| */ | ||
@@ -21,6 +22,8 @@ extractable?: boolean; | ||
| * | ||
| * Note: The secret key is generated with `extractable` set to `false` by default. | ||
| * > [!NOTE]\ | ||
| * > The secret key is generated with `extractable` set to `false` by default. | ||
| * | ||
| * Note: Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as | ||
| * {@link !CryptoKey} this method yields a {@link !Uint8Array} for them instead. | ||
| * > [!NOTE]\ | ||
| * > Because A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 secrets cannot be represented as | ||
| * > {@link !CryptoKey} this method yields a {@link !Uint8Array} for them instead. | ||
| * | ||
@@ -27,0 +30,0 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well |
@@ -18,5 +18,6 @@ /** | ||
| * | ||
| * Note: The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in | ||
| * {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption | ||
| * (1.2.840.113549.1.1.1) instead for all RSA algorithms. | ||
| * > [!NOTE]\ | ||
| * > The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in | ||
| * > {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption | ||
| * > (1.2.840.113549.1.1.1) instead for all RSA algorithms. | ||
| * | ||
@@ -34,5 +35,6 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well | ||
| * | ||
| * Note: The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in | ||
| * {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption | ||
| * (1.2.840.113549.1.1.1) instead for all RSA algorithms. | ||
| * > [!NOTE]\ | ||
| * > The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in | ||
| * > {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption | ||
| * > (1.2.840.113549.1.1.1) instead for all RSA algorithms. | ||
| * | ||
@@ -50,5 +52,6 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well | ||
| * | ||
| * Note: The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in | ||
| * {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption | ||
| * (1.2.840.113549.1.1.1) instead for all RSA algorithms. | ||
| * > [!NOTE]\ | ||
| * > The OID id-RSASSA-PSS (1.2.840.113549.1.1.10) is not supported in | ||
| * > {@link https://w3c.github.io/webcrypto/ Web Cryptography API}, use the OID rsaEncryption | ||
| * > (1.2.840.113549.1.1.1) instead for all RSA algorithms. | ||
| * | ||
@@ -67,7 +70,9 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well | ||
| * | ||
| * Note: The JSON Web Key parameters "use", "key_ops", and "ext" are also used in the | ||
| * {@link !CryptoKey} import process. | ||
| * > [!NOTE]\ | ||
| * > The JSON Web Key parameters "use", "key_ops", and "ext" are also used in the {@link !CryptoKey} | ||
| * > import process. | ||
| * | ||
| * Note: Symmetric JSON Web Keys (i.e. `kty: "oct"`) yield back an {@link !Uint8Array} instead of a | ||
| * {@link !CryptoKey}. | ||
| * > [!NOTE]\ | ||
| * > Symmetric JSON Web Keys (i.e. `kty: "oct"`) yield back an {@link !Uint8Array} instead of a | ||
| * > {@link !CryptoKey}. | ||
| * | ||
@@ -74,0 +79,0 @@ * This function is exported (as a named export) from the main `'jose'` module entry point as well |
@@ -525,3 +525,4 @@ /** Generic JSON Web Key Parameters. */ | ||
| * | ||
| * Note: Unsecured JWTs (`{ "alg": "none" }`) are never accepted by this API. | ||
| * > [!NOTE]\ | ||
| * > Unsecured JWTs (`{ "alg": "none" }`) are never accepted by this API. | ||
| */ | ||
@@ -528,0 +529,0 @@ algorithms?: string[] |
@@ -12,3 +12,3 @@ import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from '../util/errors.js'; | ||
| const NAME = 'jose'; | ||
| const VERSION = 'v6.0.11'; | ||
| const VERSION = 'v6.0.12'; | ||
| USER_AGENT = `${NAME}/${VERSION}`; | ||
@@ -15,0 +15,0 @@ } |
+74
-118
@@ -33,34 +33,26 @@ import invalidKeyInput from './invalid_key_input.js'; | ||
| }; | ||
| const findOid = (keyData, oid, from = 0) => { | ||
| if (from === 0) { | ||
| oid.unshift(oid.length); | ||
| oid.unshift(0x06); | ||
| } | ||
| const i = keyData.indexOf(oid[0], from); | ||
| if (i === -1) | ||
| return false; | ||
| const sub = keyData.subarray(i, i + oid.length); | ||
| if (sub.length !== oid.length) | ||
| return false; | ||
| return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1); | ||
| }; | ||
| const getNamedCurve = (keyData) => { | ||
| switch (true) { | ||
| case findOid(keyData, [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]): | ||
| return 'P-256'; | ||
| case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x22]): | ||
| return 'P-384'; | ||
| case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]): | ||
| return 'P-521'; | ||
| default: | ||
| return undefined; | ||
| const patterns = Object.entries({ | ||
| 'P-256': [0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07], | ||
| 'P-384': [0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22], | ||
| 'P-521': [0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23], | ||
| }); | ||
| const maxPatternLen = Math.max(...patterns.map(([, bytes]) => bytes.length)); | ||
| for (let i = 0; i <= keyData.byteLength - maxPatternLen; i++) { | ||
| for (const [curve, bytes] of patterns) { | ||
| if (i <= keyData.byteLength - bytes.length) { | ||
| if (keyData.subarray(i, i + bytes.length).every((byte, idx) => byte === bytes[idx])) { | ||
| return curve; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return undefined; | ||
| }; | ||
| const genericImport = async (replace, keyFormat, pem, alg, options) => { | ||
| const genericImport = async (keyFormat, keyData, alg, options) => { | ||
| let algorithm; | ||
| let keyUsages; | ||
| const keyData = new Uint8Array(atob(pem.replace(replace, '')) | ||
| .split('') | ||
| .map((c) => c.charCodeAt(0))); | ||
| const isPublic = keyFormat === 'spki'; | ||
| const getSignatureUsages = () => (isPublic ? ['verify'] : ['sign']); | ||
| const getEncryptionUsages = () => isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey']; | ||
| switch (alg) { | ||
@@ -71,3 +63,3 @@ case 'PS256': | ||
| algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` }; | ||
| keyUsages = isPublic ? ['verify'] : ['sign']; | ||
| keyUsages = getSignatureUsages(); | ||
| break; | ||
@@ -78,3 +70,3 @@ case 'RS256': | ||
| algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` }; | ||
| keyUsages = isPublic ? ['verify'] : ['sign']; | ||
| keyUsages = getSignatureUsages(); | ||
| break; | ||
@@ -89,16 +81,12 @@ case 'RSA-OAEP': | ||
| }; | ||
| keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey']; | ||
| keyUsages = getEncryptionUsages(); | ||
| break; | ||
| case 'ES256': | ||
| algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; | ||
| keyUsages = isPublic ? ['verify'] : ['sign']; | ||
| break; | ||
| case 'ES384': | ||
| algorithm = { name: 'ECDSA', namedCurve: 'P-384' }; | ||
| keyUsages = isPublic ? ['verify'] : ['sign']; | ||
| case 'ES512': { | ||
| const curveMap = { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' }; | ||
| algorithm = { name: 'ECDSA', namedCurve: curveMap[alg] }; | ||
| keyUsages = getSignatureUsages(); | ||
| break; | ||
| case 'ES512': | ||
| algorithm = { name: 'ECDSA', namedCurve: 'P-521' }; | ||
| keyUsages = isPublic ? ['verify'] : ['sign']; | ||
| break; | ||
| } | ||
| case 'ECDH-ES': | ||
@@ -109,3 +97,3 @@ case 'ECDH-ES+A128KW': | ||
| const namedCurve = getNamedCurve(keyData); | ||
| algorithm = namedCurve?.startsWith('P-') ? { name: 'ECDH', namedCurve } : { name: 'X25519' }; | ||
| algorithm = namedCurve ? { name: 'ECDH', namedCurve } : { name: 'X25519' }; | ||
| keyUsages = isPublic ? [] : ['deriveBits']; | ||
@@ -117,3 +105,3 @@ break; | ||
| algorithm = { name: 'Ed25519' }; | ||
| keyUsages = isPublic ? ['verify'] : ['sign']; | ||
| keyUsages = getSignatureUsages(); | ||
| break; | ||
@@ -126,92 +114,60 @@ default: | ||
| export const fromPKCS8 = (pem, alg, options) => { | ||
| return genericImport(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, 'pkcs8', pem, alg, options); | ||
| const keyData = decodeBase64(pem.replace(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, '')); | ||
| return genericImport('pkcs8', keyData, alg, options); | ||
| }; | ||
| export const fromSPKI = (pem, alg, options) => { | ||
| return genericImport(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, 'spki', pem, alg, options); | ||
| const keyData = decodeBase64(pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, '')); | ||
| return genericImport('spki', keyData, alg, options); | ||
| }; | ||
| function getElement(seq) { | ||
| const result = []; | ||
| let next = 0; | ||
| while (next < seq.length) { | ||
| const nextPart = parseElement(seq.subarray(next)); | ||
| result.push(nextPart); | ||
| next += nextPart.byteLength; | ||
| } | ||
| return result; | ||
| } | ||
| function parseElement(bytes) { | ||
| let position = 0; | ||
| let tag = bytes[0] & 0x1f; | ||
| position++; | ||
| if (tag === 0x1f) { | ||
| tag = 0; | ||
| while (bytes[position] >= 0x80) { | ||
| tag = tag * 128 + bytes[position] - 0x80; | ||
| position++; | ||
| } | ||
| tag = tag * 128 + bytes[position] - 0x80; | ||
| position++; | ||
| } | ||
| let length = 0; | ||
| if (bytes[position] < 0x80) { | ||
| length = bytes[position]; | ||
| position++; | ||
| } | ||
| else 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'); | ||
| function spkiFromX509(buf) { | ||
| let pos = 0; | ||
| const parseLength = () => { | ||
| const first = buf[pos++]; | ||
| if (first & 0x80) { | ||
| const lengthOfLength = first & 0x7f; | ||
| let length = 0; | ||
| for (let i = 0; i < lengthOfLength; i++) { | ||
| length = (length << 8) | buf[pos++]; | ||
| } | ||
| length++; | ||
| return length; | ||
| } | ||
| const byteLength = position + length + 2; | ||
| return { | ||
| byteLength, | ||
| contents: bytes.subarray(position, position + length), | ||
| raw: bytes.subarray(0, byteLength), | ||
| }; | ||
| return first; | ||
| }; | ||
| const skipElement = (count = 1) => { | ||
| if (count <= 0) | ||
| return; | ||
| pos++; | ||
| const length = parseLength(); | ||
| pos += length; | ||
| if (count > 1) { | ||
| skipElement(count - 1); | ||
| } | ||
| }; | ||
| if (buf[pos++] !== 0x30) | ||
| throw new Error('Invalid certificate structure'); | ||
| parseLength(); | ||
| if (buf[pos++] !== 0x30) | ||
| throw new Error('Invalid tbsCertificate structure'); | ||
| parseLength(); | ||
| if (buf[pos] === 0xa0) { | ||
| skipElement(6); | ||
| } | ||
| else { | ||
| const numberOfDigits = bytes[position] & 0x7f; | ||
| position++; | ||
| length = 0; | ||
| for (let i = 0; i < numberOfDigits; i++) { | ||
| length = length * 256 + bytes[position]; | ||
| position++; | ||
| } | ||
| skipElement(5); | ||
| } | ||
| const byteLength = position + length; | ||
| return { | ||
| byteLength, | ||
| contents: bytes.subarray(position, byteLength), | ||
| raw: bytes.subarray(0, byteLength), | ||
| }; | ||
| const spkiStart = pos; | ||
| if (buf[pos++] !== 0x30) | ||
| throw new Error('Invalid SPKI structure'); | ||
| const spkiContentLength = parseLength(); | ||
| return buf.subarray(spkiStart, spkiStart + spkiContentLength + (pos - spkiStart)); | ||
| } | ||
| function spkiFromX509(buf) { | ||
| const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents); | ||
| return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 0xa0 ? 6 : 5].raw); | ||
| function extractX509SPKI(x509) { | ||
| const base64Content = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ''); | ||
| const derBytes = decodeBase64(base64Content); | ||
| return spkiFromX509(derBytes); | ||
| } | ||
| let createPublicKey; | ||
| function getSPKI(x509) { | ||
| try { | ||
| createPublicKey ??= globalThis.process?.getBuiltinModule?.('node:crypto')?.createPublicKey; | ||
| } | ||
| catch { | ||
| createPublicKey = 0; | ||
| } | ||
| if (createPublicKey) { | ||
| try { | ||
| return new createPublicKey(x509).export({ format: 'pem', type: 'spki' }); | ||
| } | ||
| catch { } | ||
| } | ||
| const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, ''); | ||
| const raw = decodeBase64(pem); | ||
| return formatPEM(spkiFromX509(raw), 'PUBLIC KEY'); | ||
| } | ||
| export const fromX509 = (pem, alg, options) => { | ||
| let spki; | ||
| try { | ||
| spki = getSPKI(pem); | ||
| spki = extractX509SPKI(pem); | ||
| } | ||
@@ -221,3 +177,3 @@ catch (cause) { | ||
| } | ||
| return fromSPKI(spki, alg, options); | ||
| return genericImport('spki', spki, alg, options); | ||
| }; |
+1
-1
| { | ||
| "name": "jose", | ||
| "version": "6.0.11", | ||
| "version": "6.0.12", | ||
| "description": "JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
250232
-0.28%6142
-0.42%11
22.22%