initial commit
This commit is contained in:
14
server/node_modules/jose/dist/node/esm/lib/aesgcmkw.js
generated
vendored
Normal file
14
server/node_modules/jose/dist/node/esm/lib/aesgcmkw.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import encrypt from '../runtime/encrypt.js';
|
||||
import decrypt from '../runtime/decrypt.js';
|
||||
import generateIv from './iv.js';
|
||||
import { encode as base64url } from '../runtime/base64url.js';
|
||||
export async function wrap(alg, key, cek, iv) {
|
||||
const jweAlgorithm = alg.slice(0, 7);
|
||||
iv || (iv = generateIv(jweAlgorithm));
|
||||
const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
|
||||
return { encryptedKey, iv: base64url(iv), tag: base64url(tag) };
|
||||
}
|
||||
export async function unwrap(alg, key, encryptedKey, iv, tag) {
|
||||
const jweAlgorithm = alg.slice(0, 7);
|
||||
return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
|
||||
}
|
||||
51
server/node_modules/jose/dist/node/esm/lib/buffer_utils.js
generated
vendored
Normal file
51
server/node_modules/jose/dist/node/esm/lib/buffer_utils.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
import digest from '../runtime/digest.js';
|
||||
export const encoder = new TextEncoder();
|
||||
export const decoder = new TextDecoder();
|
||||
const MAX_INT32 = 2 ** 32;
|
||||
export function concat(...buffers) {
|
||||
const size = buffers.reduce((acc, { length }) => acc + length, 0);
|
||||
const buf = new Uint8Array(size);
|
||||
let i = 0;
|
||||
buffers.forEach((buffer) => {
|
||||
buf.set(buffer, i);
|
||||
i += buffer.length;
|
||||
});
|
||||
return buf;
|
||||
}
|
||||
export function p2s(alg, p2sInput) {
|
||||
return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput);
|
||||
}
|
||||
function writeUInt32BE(buf, value, offset) {
|
||||
if (value < 0 || value >= MAX_INT32) {
|
||||
throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);
|
||||
}
|
||||
buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset);
|
||||
}
|
||||
export function uint64be(value) {
|
||||
const high = Math.floor(value / MAX_INT32);
|
||||
const low = value % MAX_INT32;
|
||||
const buf = new Uint8Array(8);
|
||||
writeUInt32BE(buf, high, 0);
|
||||
writeUInt32BE(buf, low, 4);
|
||||
return buf;
|
||||
}
|
||||
export function uint32be(value) {
|
||||
const buf = new Uint8Array(4);
|
||||
writeUInt32BE(buf, value);
|
||||
return buf;
|
||||
}
|
||||
export function lengthAndInput(input) {
|
||||
return concat(uint32be(input.length), input);
|
||||
}
|
||||
export async function concatKdf(secret, bits, value) {
|
||||
const iterations = Math.ceil((bits >> 3) / 32);
|
||||
const res = new Uint8Array(iterations * 32);
|
||||
for (let iter = 0; iter < iterations; iter++) {
|
||||
const buf = new Uint8Array(4 + secret.length + value.length);
|
||||
buf.set(uint32be(iter + 1));
|
||||
buf.set(secret, 4);
|
||||
buf.set(value, 4 + secret.length);
|
||||
res.set(await digest('sha256', buf), iter * 32);
|
||||
}
|
||||
return res.slice(0, bits >> 3);
|
||||
}
|
||||
20
server/node_modules/jose/dist/node/esm/lib/cek.js
generated
vendored
Normal file
20
server/node_modules/jose/dist/node/esm/lib/cek.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { JOSENotSupported } from '../util/errors.js';
|
||||
import random from '../runtime/random.js';
|
||||
export function bitLength(alg) {
|
||||
switch (alg) {
|
||||
case 'A128GCM':
|
||||
return 128;
|
||||
case 'A192GCM':
|
||||
return 192;
|
||||
case 'A256GCM':
|
||||
case 'A128CBC-HS256':
|
||||
return 256;
|
||||
case 'A192CBC-HS384':
|
||||
return 384;
|
||||
case 'A256CBC-HS512':
|
||||
return 512;
|
||||
default:
|
||||
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
||||
}
|
||||
}
|
||||
export default (alg) => random(new Uint8Array(bitLength(alg) >> 3));
|
||||
8
server/node_modules/jose/dist/node/esm/lib/check_iv_length.js
generated
vendored
Normal file
8
server/node_modules/jose/dist/node/esm/lib/check_iv_length.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { JWEInvalid } from '../util/errors.js';
|
||||
import { bitLength } from './iv.js';
|
||||
const checkIvLength = (enc, iv) => {
|
||||
if (iv.length << 3 !== bitLength(enc)) {
|
||||
throw new JWEInvalid('Invalid Initialization Vector length');
|
||||
}
|
||||
};
|
||||
export default checkIvLength;
|
||||
45
server/node_modules/jose/dist/node/esm/lib/check_key_type.js
generated
vendored
Normal file
45
server/node_modules/jose/dist/node/esm/lib/check_key_type.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import { withAlg as invalidKeyInput } from './invalid_key_input.js';
|
||||
import isKeyLike, { types } from '../runtime/is_key_like.js';
|
||||
const symmetricTypeCheck = (alg, key) => {
|
||||
if (key instanceof Uint8Array)
|
||||
return;
|
||||
if (!isKeyLike(key)) {
|
||||
throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array'));
|
||||
}
|
||||
if (key.type !== 'secret') {
|
||||
throw new TypeError(`${types.join(' or ')} instances for symmetric algorithms must be of type "secret"`);
|
||||
}
|
||||
};
|
||||
const asymmetricTypeCheck = (alg, key, usage) => {
|
||||
if (!isKeyLike(key)) {
|
||||
throw new TypeError(invalidKeyInput(alg, key, ...types));
|
||||
}
|
||||
if (key.type === 'secret') {
|
||||
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithms must not be of type "secret"`);
|
||||
}
|
||||
if (usage === 'sign' && key.type === 'public') {
|
||||
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm signing must be of type "private"`);
|
||||
}
|
||||
if (usage === 'decrypt' && key.type === 'public') {
|
||||
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm decryption must be of type "private"`);
|
||||
}
|
||||
if (key.algorithm && usage === 'verify' && key.type === 'private') {
|
||||
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm verifying must be of type "public"`);
|
||||
}
|
||||
if (key.algorithm && usage === 'encrypt' && key.type === 'private') {
|
||||
throw new TypeError(`${types.join(' or ')} instances for asymmetric algorithm encryption must be of type "public"`);
|
||||
}
|
||||
};
|
||||
const checkKeyType = (alg, key, usage) => {
|
||||
const symmetric = alg.startsWith('HS') ||
|
||||
alg === 'dir' ||
|
||||
alg.startsWith('PBES2') ||
|
||||
/^A\d{3}(?:GCM)?KW$/.test(alg);
|
||||
if (symmetric) {
|
||||
symmetricTypeCheck(alg, key);
|
||||
}
|
||||
else {
|
||||
asymmetricTypeCheck(alg, key, usage);
|
||||
}
|
||||
};
|
||||
export default checkKeyType;
|
||||
6
server/node_modules/jose/dist/node/esm/lib/check_p2s.js
generated
vendored
Normal file
6
server/node_modules/jose/dist/node/esm/lib/check_p2s.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { JWEInvalid } from '../util/errors.js';
|
||||
export default function checkP2s(p2s) {
|
||||
if (!(p2s instanceof Uint8Array) || p2s.length < 8) {
|
||||
throw new JWEInvalid('PBES2 Salt Input must be 8 or more octets');
|
||||
}
|
||||
}
|
||||
152
server/node_modules/jose/dist/node/esm/lib/crypto_key.js
generated
vendored
Normal file
152
server/node_modules/jose/dist/node/esm/lib/crypto_key.js
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
function unusable(name, prop = 'algorithm.name') {
|
||||
return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
||||
}
|
||||
function isAlgorithm(algorithm, name) {
|
||||
return algorithm.name === name;
|
||||
}
|
||||
function getHashLength(hash) {
|
||||
return parseInt(hash.name.slice(4), 10);
|
||||
}
|
||||
function getNamedCurve(alg) {
|
||||
switch (alg) {
|
||||
case 'ES256':
|
||||
return 'P-256';
|
||||
case 'ES384':
|
||||
return 'P-384';
|
||||
case 'ES512':
|
||||
return 'P-521';
|
||||
default:
|
||||
throw new Error('unreachable');
|
||||
}
|
||||
}
|
||||
function checkUsage(key, usages) {
|
||||
if (usages.length && !usages.some((expected) => key.usages.includes(expected))) {
|
||||
let msg = 'CryptoKey does not support this operation, its usages must include ';
|
||||
if (usages.length > 2) {
|
||||
const last = usages.pop();
|
||||
msg += `one of ${usages.join(', ')}, or ${last}.`;
|
||||
}
|
||||
else if (usages.length === 2) {
|
||||
msg += `one of ${usages[0]} or ${usages[1]}.`;
|
||||
}
|
||||
else {
|
||||
msg += `${usages[0]}.`;
|
||||
}
|
||||
throw new TypeError(msg);
|
||||
}
|
||||
}
|
||||
export function checkSigCryptoKey(key, alg, ...usages) {
|
||||
switch (alg) {
|
||||
case 'HS256':
|
||||
case 'HS384':
|
||||
case 'HS512': {
|
||||
if (!isAlgorithm(key.algorithm, 'HMAC'))
|
||||
throw unusable('HMAC');
|
||||
const expected = parseInt(alg.slice(2), 10);
|
||||
const actual = getHashLength(key.algorithm.hash);
|
||||
if (actual !== expected)
|
||||
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
||||
break;
|
||||
}
|
||||
case 'RS256':
|
||||
case 'RS384':
|
||||
case 'RS512': {
|
||||
if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))
|
||||
throw unusable('RSASSA-PKCS1-v1_5');
|
||||
const expected = parseInt(alg.slice(2), 10);
|
||||
const actual = getHashLength(key.algorithm.hash);
|
||||
if (actual !== expected)
|
||||
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
||||
break;
|
||||
}
|
||||
case 'PS256':
|
||||
case 'PS384':
|
||||
case 'PS512': {
|
||||
if (!isAlgorithm(key.algorithm, 'RSA-PSS'))
|
||||
throw unusable('RSA-PSS');
|
||||
const expected = parseInt(alg.slice(2), 10);
|
||||
const actual = getHashLength(key.algorithm.hash);
|
||||
if (actual !== expected)
|
||||
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
||||
break;
|
||||
}
|
||||
case 'EdDSA': {
|
||||
if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') {
|
||||
throw unusable('Ed25519 or Ed448');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'ES256':
|
||||
case 'ES384':
|
||||
case 'ES512': {
|
||||
if (!isAlgorithm(key.algorithm, 'ECDSA'))
|
||||
throw unusable('ECDSA');
|
||||
const expected = getNamedCurve(alg);
|
||||
const actual = key.algorithm.namedCurve;
|
||||
if (actual !== expected)
|
||||
throw unusable(expected, 'algorithm.namedCurve');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new TypeError('CryptoKey does not support this operation');
|
||||
}
|
||||
checkUsage(key, usages);
|
||||
}
|
||||
export function checkEncCryptoKey(key, alg, ...usages) {
|
||||
switch (alg) {
|
||||
case 'A128GCM':
|
||||
case 'A192GCM':
|
||||
case 'A256GCM': {
|
||||
if (!isAlgorithm(key.algorithm, 'AES-GCM'))
|
||||
throw unusable('AES-GCM');
|
||||
const expected = parseInt(alg.slice(1, 4), 10);
|
||||
const actual = key.algorithm.length;
|
||||
if (actual !== expected)
|
||||
throw unusable(expected, 'algorithm.length');
|
||||
break;
|
||||
}
|
||||
case 'A128KW':
|
||||
case 'A192KW':
|
||||
case 'A256KW': {
|
||||
if (!isAlgorithm(key.algorithm, 'AES-KW'))
|
||||
throw unusable('AES-KW');
|
||||
const expected = parseInt(alg.slice(1, 4), 10);
|
||||
const actual = key.algorithm.length;
|
||||
if (actual !== expected)
|
||||
throw unusable(expected, 'algorithm.length');
|
||||
break;
|
||||
}
|
||||
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':
|
||||
case 'PBES2-HS384+A192KW':
|
||||
case 'PBES2-HS512+A256KW':
|
||||
if (!isAlgorithm(key.algorithm, 'PBKDF2'))
|
||||
throw unusable('PBKDF2');
|
||||
break;
|
||||
case 'RSA-OAEP':
|
||||
case 'RSA-OAEP-256':
|
||||
case 'RSA-OAEP-384':
|
||||
case 'RSA-OAEP-512': {
|
||||
if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))
|
||||
throw unusable('RSA-OAEP');
|
||||
const expected = parseInt(alg.slice(9), 10) || 1;
|
||||
const actual = getHashLength(key.algorithm.hash);
|
||||
if (actual !== expected)
|
||||
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new TypeError('CryptoKey does not support this operation');
|
||||
}
|
||||
checkUsage(key, usages);
|
||||
}
|
||||
127
server/node_modules/jose/dist/node/esm/lib/decrypt_key_management.js
generated
vendored
Normal file
127
server/node_modules/jose/dist/node/esm/lib/decrypt_key_management.js
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
import { unwrap as aesKw } from '../runtime/aeskw.js';
|
||||
import * as ECDH from '../runtime/ecdhes.js';
|
||||
import { decrypt as pbes2Kw } from '../runtime/pbes2kw.js';
|
||||
import { decrypt as rsaEs } from '../runtime/rsaes.js';
|
||||
import { decode as base64url } from '../runtime/base64url.js';
|
||||
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
|
||||
import { bitLength as cekLength } from '../lib/cek.js';
|
||||
import { importJWK } from '../key/import.js';
|
||||
import checkKeyType from './check_key_type.js';
|
||||
import isObject from './is_object.js';
|
||||
import { unwrap as aesGcmKw } from './aesgcmkw.js';
|
||||
async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) {
|
||||
checkKeyType(alg, key, 'decrypt');
|
||||
switch (alg) {
|
||||
case 'dir': {
|
||||
if (encryptedKey !== undefined)
|
||||
throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
||||
return key;
|
||||
}
|
||||
case 'ECDH-ES':
|
||||
if (encryptedKey !== undefined)
|
||||
throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
||||
case 'ECDH-ES+A128KW':
|
||||
case 'ECDH-ES+A192KW':
|
||||
case 'ECDH-ES+A256KW': {
|
||||
if (!isObject(joseHeader.epk))
|
||||
throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
||||
if (!ECDH.ecdhAllowed(key))
|
||||
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
||||
const epk = await importJWK(joseHeader.epk, alg);
|
||||
let partyUInfo;
|
||||
let partyVInfo;
|
||||
if (joseHeader.apu !== undefined) {
|
||||
if (typeof joseHeader.apu !== 'string')
|
||||
throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`);
|
||||
try {
|
||||
partyUInfo = base64url(joseHeader.apu);
|
||||
}
|
||||
catch {
|
||||
throw new JWEInvalid('Failed to base64url decode the apu');
|
||||
}
|
||||
}
|
||||
if (joseHeader.apv !== undefined) {
|
||||
if (typeof joseHeader.apv !== 'string')
|
||||
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
||||
try {
|
||||
partyVInfo = base64url(joseHeader.apv);
|
||||
}
|
||||
catch {
|
||||
throw new JWEInvalid('Failed to base64url decode the apv');
|
||||
}
|
||||
}
|
||||
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo);
|
||||
if (alg === 'ECDH-ES')
|
||||
return sharedSecret;
|
||||
if (encryptedKey === undefined)
|
||||
throw new JWEInvalid('JWE Encrypted Key missing');
|
||||
return aesKw(alg.slice(-6), sharedSecret, encryptedKey);
|
||||
}
|
||||
case 'RSA1_5':
|
||||
case 'RSA-OAEP':
|
||||
case 'RSA-OAEP-256':
|
||||
case 'RSA-OAEP-384':
|
||||
case 'RSA-OAEP-512': {
|
||||
if (encryptedKey === undefined)
|
||||
throw new JWEInvalid('JWE Encrypted Key missing');
|
||||
return rsaEs(alg, key, encryptedKey);
|
||||
}
|
||||
case 'PBES2-HS256+A128KW':
|
||||
case 'PBES2-HS384+A192KW':
|
||||
case 'PBES2-HS512+A256KW': {
|
||||
if (encryptedKey === undefined)
|
||||
throw new JWEInvalid('JWE Encrypted Key missing');
|
||||
if (typeof joseHeader.p2c !== 'number')
|
||||
throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
|
||||
const p2cLimit = (options === null || options === void 0 ? void 0 : options.maxPBES2Count) || 10000;
|
||||
if (joseHeader.p2c > p2cLimit)
|
||||
throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`);
|
||||
if (typeof joseHeader.p2s !== 'string')
|
||||
throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
|
||||
let p2s;
|
||||
try {
|
||||
p2s = base64url(joseHeader.p2s);
|
||||
}
|
||||
catch {
|
||||
throw new JWEInvalid('Failed to base64url decode the p2s');
|
||||
}
|
||||
return pbes2Kw(alg, key, encryptedKey, joseHeader.p2c, p2s);
|
||||
}
|
||||
case 'A128KW':
|
||||
case 'A192KW':
|
||||
case 'A256KW': {
|
||||
if (encryptedKey === undefined)
|
||||
throw new JWEInvalid('JWE Encrypted Key missing');
|
||||
return aesKw(alg, key, encryptedKey);
|
||||
}
|
||||
case 'A128GCMKW':
|
||||
case 'A192GCMKW':
|
||||
case 'A256GCMKW': {
|
||||
if (encryptedKey === undefined)
|
||||
throw new JWEInvalid('JWE Encrypted Key missing');
|
||||
if (typeof joseHeader.iv !== 'string')
|
||||
throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`);
|
||||
if (typeof joseHeader.tag !== 'string')
|
||||
throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`);
|
||||
let iv;
|
||||
try {
|
||||
iv = base64url(joseHeader.iv);
|
||||
}
|
||||
catch {
|
||||
throw new JWEInvalid('Failed to base64url decode the iv');
|
||||
}
|
||||
let tag;
|
||||
try {
|
||||
tag = base64url(joseHeader.tag);
|
||||
}
|
||||
catch {
|
||||
throw new JWEInvalid('Failed to base64url decode the tag');
|
||||
}
|
||||
return aesGcmKw(alg, key, encryptedKey, iv, tag);
|
||||
}
|
||||
default: {
|
||||
throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
|
||||
}
|
||||
}
|
||||
}
|
||||
export default decryptKeyManagement;
|
||||
87
server/node_modules/jose/dist/node/esm/lib/encrypt_key_management.js
generated
vendored
Normal file
87
server/node_modules/jose/dist/node/esm/lib/encrypt_key_management.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
import { wrap as aesKw } from '../runtime/aeskw.js';
|
||||
import * as ECDH from '../runtime/ecdhes.js';
|
||||
import { encrypt as pbes2Kw } from '../runtime/pbes2kw.js';
|
||||
import { encrypt as rsaEs } from '../runtime/rsaes.js';
|
||||
import { encode as base64url } from '../runtime/base64url.js';
|
||||
import generateCek, { bitLength as cekLength } from '../lib/cek.js';
|
||||
import { JOSENotSupported } from '../util/errors.js';
|
||||
import { exportJWK } from '../key/export.js';
|
||||
import checkKeyType from './check_key_type.js';
|
||||
import { wrap as aesGcmKw } from './aesgcmkw.js';
|
||||
async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
|
||||
let encryptedKey;
|
||||
let parameters;
|
||||
let cek;
|
||||
checkKeyType(alg, key, 'encrypt');
|
||||
switch (alg) {
|
||||
case 'dir': {
|
||||
cek = key;
|
||||
break;
|
||||
}
|
||||
case 'ECDH-ES':
|
||||
case 'ECDH-ES+A128KW':
|
||||
case 'ECDH-ES+A192KW':
|
||||
case 'ECDH-ES+A256KW': {
|
||||
if (!ECDH.ecdhAllowed(key)) {
|
||||
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
||||
}
|
||||
const { apu, apv } = providedParameters;
|
||||
let { epk: ephemeralKey } = providedParameters;
|
||||
ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey);
|
||||
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
|
||||
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv);
|
||||
parameters = { epk: { x, crv, kty } };
|
||||
if (kty === 'EC')
|
||||
parameters.epk.y = y;
|
||||
if (apu)
|
||||
parameters.apu = base64url(apu);
|
||||
if (apv)
|
||||
parameters.apv = base64url(apv);
|
||||
if (alg === 'ECDH-ES') {
|
||||
cek = sharedSecret;
|
||||
break;
|
||||
}
|
||||
cek = providedCek || generateCek(enc);
|
||||
const kwAlg = alg.slice(-6);
|
||||
encryptedKey = await aesKw(kwAlg, sharedSecret, cek);
|
||||
break;
|
||||
}
|
||||
case 'RSA1_5':
|
||||
case 'RSA-OAEP':
|
||||
case 'RSA-OAEP-256':
|
||||
case 'RSA-OAEP-384':
|
||||
case 'RSA-OAEP-512': {
|
||||
cek = providedCek || generateCek(enc);
|
||||
encryptedKey = await rsaEs(alg, key, cek);
|
||||
break;
|
||||
}
|
||||
case 'PBES2-HS256+A128KW':
|
||||
case 'PBES2-HS384+A192KW':
|
||||
case 'PBES2-HS512+A256KW': {
|
||||
cek = providedCek || generateCek(enc);
|
||||
const { p2c, p2s } = providedParameters;
|
||||
({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s));
|
||||
break;
|
||||
}
|
||||
case 'A128KW':
|
||||
case 'A192KW':
|
||||
case 'A256KW': {
|
||||
cek = providedCek || generateCek(enc);
|
||||
encryptedKey = await aesKw(alg, key, cek);
|
||||
break;
|
||||
}
|
||||
case 'A128GCMKW':
|
||||
case 'A192GCMKW':
|
||||
case 'A256GCMKW': {
|
||||
cek = providedCek || generateCek(enc);
|
||||
const { iv } = providedParameters;
|
||||
({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');
|
||||
}
|
||||
}
|
||||
return { cek, encryptedKey, parameters };
|
||||
}
|
||||
export default encryptKeyManagement;
|
||||
1
server/node_modules/jose/dist/node/esm/lib/epoch.js
generated
vendored
Normal file
1
server/node_modules/jose/dist/node/esm/lib/epoch.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (date) => Math.floor(date.getTime() / 1000);
|
||||
30
server/node_modules/jose/dist/node/esm/lib/invalid_key_input.js
generated
vendored
Normal file
30
server/node_modules/jose/dist/node/esm/lib/invalid_key_input.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
function message(msg, actual, ...types) {
|
||||
if (types.length > 2) {
|
||||
const last = types.pop();
|
||||
msg += `one of type ${types.join(', ')}, or ${last}.`;
|
||||
}
|
||||
else if (types.length === 2) {
|
||||
msg += `one of type ${types[0]} or ${types[1]}.`;
|
||||
}
|
||||
else {
|
||||
msg += `of type ${types[0]}.`;
|
||||
}
|
||||
if (actual == null) {
|
||||
msg += ` Received ${actual}`;
|
||||
}
|
||||
else if (typeof actual === 'function' && actual.name) {
|
||||
msg += ` Received function ${actual.name}`;
|
||||
}
|
||||
else if (typeof actual === 'object' && actual != null) {
|
||||
if (actual.constructor && actual.constructor.name) {
|
||||
msg += ` Received an instance of ${actual.constructor.name}`;
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
export default (actual, ...types) => {
|
||||
return message('Key must be ', actual, ...types);
|
||||
};
|
||||
export function withAlg(alg, actual, ...types) {
|
||||
return message(`Key for the ${alg} algorithm must be `, actual, ...types);
|
||||
}
|
||||
22
server/node_modules/jose/dist/node/esm/lib/is_disjoint.js
generated
vendored
Normal file
22
server/node_modules/jose/dist/node/esm/lib/is_disjoint.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
const isDisjoint = (...headers) => {
|
||||
const sources = headers.filter(Boolean);
|
||||
if (sources.length === 0 || sources.length === 1) {
|
||||
return true;
|
||||
}
|
||||
let acc;
|
||||
for (const header of sources) {
|
||||
const parameters = Object.keys(header);
|
||||
if (!acc || acc.size === 0) {
|
||||
acc = new Set(parameters);
|
||||
continue;
|
||||
}
|
||||
for (const parameter of parameters) {
|
||||
if (acc.has(parameter)) {
|
||||
return false;
|
||||
}
|
||||
acc.add(parameter);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
export default isDisjoint;
|
||||
16
server/node_modules/jose/dist/node/esm/lib/is_object.js
generated
vendored
Normal file
16
server/node_modules/jose/dist/node/esm/lib/is_object.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
function isObjectLike(value) {
|
||||
return typeof value === 'object' && value !== null;
|
||||
}
|
||||
export default function isObject(input) {
|
||||
if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {
|
||||
return false;
|
||||
}
|
||||
if (Object.getPrototypeOf(input) === null) {
|
||||
return true;
|
||||
}
|
||||
let proto = input;
|
||||
while (Object.getPrototypeOf(proto) !== null) {
|
||||
proto = Object.getPrototypeOf(proto);
|
||||
}
|
||||
return Object.getPrototypeOf(input) === proto;
|
||||
}
|
||||
20
server/node_modules/jose/dist/node/esm/lib/iv.js
generated
vendored
Normal file
20
server/node_modules/jose/dist/node/esm/lib/iv.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { JOSENotSupported } from '../util/errors.js';
|
||||
import random from '../runtime/random.js';
|
||||
export function bitLength(alg) {
|
||||
switch (alg) {
|
||||
case 'A128GCM':
|
||||
case 'A128GCMKW':
|
||||
case 'A192GCM':
|
||||
case 'A192GCMKW':
|
||||
case 'A256GCM':
|
||||
case 'A256GCMKW':
|
||||
return 96;
|
||||
case 'A128CBC-HS256':
|
||||
case 'A192CBC-HS384':
|
||||
case 'A256CBC-HS512':
|
||||
return 128;
|
||||
default:
|
||||
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
||||
}
|
||||
}
|
||||
export default (alg) => random(new Uint8Array(bitLength(alg) >> 3));
|
||||
102
server/node_modules/jose/dist/node/esm/lib/jwt_claims_set.js
generated
vendored
Normal file
102
server/node_modules/jose/dist/node/esm/lib/jwt_claims_set.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';
|
||||
import { decoder } from './buffer_utils.js';
|
||||
import epoch from './epoch.js';
|
||||
import secs from './secs.js';
|
||||
import isObject from './is_object.js';
|
||||
const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, '');
|
||||
const checkAudiencePresence = (audPayload, audOption) => {
|
||||
if (typeof audPayload === 'string') {
|
||||
return audOption.includes(audPayload);
|
||||
}
|
||||
if (Array.isArray(audPayload)) {
|
||||
return audOption.some(Set.prototype.has.bind(new Set(audPayload)));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
export default (protectedHeader, encodedPayload, options = {}) => {
|
||||
const { typ } = options;
|
||||
if (typ &&
|
||||
(typeof protectedHeader.typ !== 'string' ||
|
||||
normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {
|
||||
throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', 'typ', 'check_failed');
|
||||
}
|
||||
let payload;
|
||||
try {
|
||||
payload = JSON.parse(decoder.decode(encodedPayload));
|
||||
}
|
||||
catch {
|
||||
}
|
||||
if (!isObject(payload)) {
|
||||
throw new JWTInvalid('JWT Claims Set must be a top-level JSON object');
|
||||
}
|
||||
const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;
|
||||
if (maxTokenAge !== undefined)
|
||||
requiredClaims.push('iat');
|
||||
if (audience !== undefined)
|
||||
requiredClaims.push('aud');
|
||||
if (subject !== undefined)
|
||||
requiredClaims.push('sub');
|
||||
if (issuer !== undefined)
|
||||
requiredClaims.push('iss');
|
||||
for (const claim of new Set(requiredClaims.reverse())) {
|
||||
if (!(claim in payload)) {
|
||||
throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, claim, 'missing');
|
||||
}
|
||||
}
|
||||
if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {
|
||||
throw new JWTClaimValidationFailed('unexpected "iss" claim value', 'iss', 'check_failed');
|
||||
}
|
||||
if (subject && payload.sub !== subject) {
|
||||
throw new JWTClaimValidationFailed('unexpected "sub" claim value', 'sub', 'check_failed');
|
||||
}
|
||||
if (audience &&
|
||||
!checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) {
|
||||
throw new JWTClaimValidationFailed('unexpected "aud" claim value', 'aud', 'check_failed');
|
||||
}
|
||||
let tolerance;
|
||||
switch (typeof options.clockTolerance) {
|
||||
case 'string':
|
||||
tolerance = secs(options.clockTolerance);
|
||||
break;
|
||||
case 'number':
|
||||
tolerance = options.clockTolerance;
|
||||
break;
|
||||
case 'undefined':
|
||||
tolerance = 0;
|
||||
break;
|
||||
default:
|
||||
throw new TypeError('Invalid clockTolerance option type');
|
||||
}
|
||||
const { currentDate } = options;
|
||||
const now = epoch(currentDate || new Date());
|
||||
if ((payload.iat !== undefined || maxTokenAge) && typeof payload.iat !== 'number') {
|
||||
throw new JWTClaimValidationFailed('"iat" claim must be a number', 'iat', 'invalid');
|
||||
}
|
||||
if (payload.nbf !== undefined) {
|
||||
if (typeof payload.nbf !== 'number') {
|
||||
throw new JWTClaimValidationFailed('"nbf" claim must be a number', 'nbf', 'invalid');
|
||||
}
|
||||
if (payload.nbf > now + tolerance) {
|
||||
throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', 'nbf', 'check_failed');
|
||||
}
|
||||
}
|
||||
if (payload.exp !== undefined) {
|
||||
if (typeof payload.exp !== 'number') {
|
||||
throw new JWTClaimValidationFailed('"exp" claim must be a number', 'exp', 'invalid');
|
||||
}
|
||||
if (payload.exp <= now - tolerance) {
|
||||
throw new JWTExpired('"exp" claim timestamp check failed', 'exp', 'check_failed');
|
||||
}
|
||||
}
|
||||
if (maxTokenAge) {
|
||||
const age = now - payload.iat;
|
||||
const max = typeof maxTokenAge === 'number' ? maxTokenAge : secs(maxTokenAge);
|
||||
if (age - tolerance > max) {
|
||||
throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', 'iat', 'check_failed');
|
||||
}
|
||||
if (age < 0 - tolerance) {
|
||||
throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', 'iat', 'check_failed');
|
||||
}
|
||||
}
|
||||
return payload;
|
||||
};
|
||||
44
server/node_modules/jose/dist/node/esm/lib/secs.js
generated
vendored
Normal file
44
server/node_modules/jose/dist/node/esm/lib/secs.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
const minute = 60;
|
||||
const hour = minute * 60;
|
||||
const day = hour * 24;
|
||||
const week = day * 7;
|
||||
const year = day * 365.25;
|
||||
const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i;
|
||||
export default (str) => {
|
||||
const matched = REGEX.exec(str);
|
||||
if (!matched) {
|
||||
throw new TypeError('Invalid time period format');
|
||||
}
|
||||
const value = parseFloat(matched[1]);
|
||||
const unit = matched[2].toLowerCase();
|
||||
switch (unit) {
|
||||
case 'sec':
|
||||
case 'secs':
|
||||
case 'second':
|
||||
case 'seconds':
|
||||
case 's':
|
||||
return Math.round(value);
|
||||
case 'minute':
|
||||
case 'minutes':
|
||||
case 'min':
|
||||
case 'mins':
|
||||
case 'm':
|
||||
return Math.round(value * minute);
|
||||
case 'hour':
|
||||
case 'hours':
|
||||
case 'hr':
|
||||
case 'hrs':
|
||||
case 'h':
|
||||
return Math.round(value * hour);
|
||||
case 'day':
|
||||
case 'days':
|
||||
case 'd':
|
||||
return Math.round(value * day);
|
||||
case 'week':
|
||||
case 'weeks':
|
||||
case 'w':
|
||||
return Math.round(value * week);
|
||||
default:
|
||||
return Math.round(value * year);
|
||||
}
|
||||
};
|
||||
11
server/node_modules/jose/dist/node/esm/lib/validate_algorithms.js
generated
vendored
Normal file
11
server/node_modules/jose/dist/node/esm/lib/validate_algorithms.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
const validateAlgorithms = (option, algorithms) => {
|
||||
if (algorithms !== undefined &&
|
||||
(!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {
|
||||
throw new TypeError(`"${option}" option must be an array of strings`);
|
||||
}
|
||||
if (!algorithms) {
|
||||
return undefined;
|
||||
}
|
||||
return new Set(algorithms);
|
||||
};
|
||||
export default validateAlgorithms;
|
||||
34
server/node_modules/jose/dist/node/esm/lib/validate_crit.js
generated
vendored
Normal file
34
server/node_modules/jose/dist/node/esm/lib/validate_crit.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import { JOSENotSupported } from '../util/errors.js';
|
||||
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
|
||||
if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) {
|
||||
throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
|
||||
}
|
||||
if (!protectedHeader || protectedHeader.crit === undefined) {
|
||||
return new Set();
|
||||
}
|
||||
if (!Array.isArray(protectedHeader.crit) ||
|
||||
protectedHeader.crit.length === 0 ||
|
||||
protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {
|
||||
throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
|
||||
}
|
||||
let recognized;
|
||||
if (recognizedOption !== undefined) {
|
||||
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);
|
||||
}
|
||||
else {
|
||||
recognized = recognizedDefault;
|
||||
}
|
||||
for (const parameter of protectedHeader.crit) {
|
||||
if (!recognized.has(parameter)) {
|
||||
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
|
||||
}
|
||||
if (joseHeader[parameter] === undefined) {
|
||||
throw new Err(`Extension Header Parameter "${parameter}" is missing`);
|
||||
}
|
||||
else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {
|
||||
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
|
||||
}
|
||||
}
|
||||
return new Set(protectedHeader.crit);
|
||||
}
|
||||
export default validateCrit;
|
||||
Reference in New Issue
Block a user