conductor-oss 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@conductor-oss/plugin-agent-amp/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-ccr/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-claude-code/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-codex/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-cursor-cli/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-droid/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-gemini/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-github-copilot/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-opencode/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-qwen-code/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-mcp-server/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-notifier-desktop/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-notifier-discord/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-runtime-tmux/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-scm-github/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-terminal-web/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-tracker-github/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-workspace-worktree/package.json +1 -1
- package/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +11 -36
- package/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +10 -22
- package/node_modules/jose/dist/webapi/jwe/general/decrypt.js +1 -1
- package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +8 -16
- package/node_modules/jose/dist/webapi/jwk/embedded.js +1 -1
- package/node_modules/jose/dist/webapi/jwk/thumbprint.js +2 -2
- package/node_modules/jose/dist/webapi/jwks/local.js +1 -1
- package/node_modules/jose/dist/webapi/jwks/remote.js +2 -2
- package/node_modules/jose/dist/webapi/jws/flattened/sign.js +5 -8
- package/node_modules/jose/dist/webapi/jws/flattened/verify.js +6 -16
- package/node_modules/jose/dist/webapi/jws/general/sign.js +3 -6
- package/node_modules/jose/dist/webapi/jws/general/verify.js +1 -1
- package/node_modules/jose/dist/webapi/jwt/encrypt.js +5 -12
- package/node_modules/jose/dist/webapi/key/import.js +1 -1
- package/node_modules/jose/dist/webapi/lib/aesgcmkw.js +1 -2
- package/node_modules/jose/dist/webapi/lib/check_key_type.js +1 -1
- package/node_modules/jose/dist/webapi/lib/content_encryption.js +217 -0
- package/node_modules/jose/dist/webapi/lib/crypto_key.js +9 -16
- package/node_modules/jose/dist/webapi/lib/ecdhes.js +1 -1
- package/node_modules/jose/dist/webapi/lib/helpers.js +19 -0
- package/node_modules/jose/dist/webapi/lib/jwk_to_key.js +9 -11
- package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +1 -1
- package/node_modules/jose/dist/webapi/lib/key_management.js +186 -0
- package/node_modules/jose/dist/webapi/lib/normalize_key.js +10 -20
- package/node_modules/jose/dist/webapi/lib/rsaes.js +1 -1
- package/node_modules/jose/dist/webapi/lib/signing.js +68 -0
- package/node_modules/jose/dist/webapi/lib/type_checks.js +40 -0
- package/node_modules/jose/dist/webapi/util/decode_jwt.js +1 -1
- package/node_modules/jose/dist/webapi/util/decode_protected_header.js +1 -1
- package/node_modules/jose/package.json +1 -1
- package/package.json +23 -23
- package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/packages/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__000b8c99._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__29d8d063._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__4168e031._.js → [root-of-the-server]__a004344a._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_1f2460d5._.js → _23584339._.js} +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b6d31783._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_2d57befe._.js +3 -0
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{node_modules_@clerk_nextjs_dist_esm_app-router_0a811c5a._.js → node_modules_@clerk_nextjs_dist_esm_app-router_c4893a23._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +8 -8
- package/web/.next/standalone/packages/web/.next/static/chunks/{2e2e8fd2ceca47dc.js → 5887c6e7b41bfd4b.js} +2 -2
- package/web/.next/standalone/packages/web/.next/static/chunks/d60c73bb353f26d3.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/e6e3c4fe9248dbee.js +1 -0
- package/web/.next/static/chunks/{2e2e8fd2ceca47dc.js → 5887c6e7b41bfd4b.js} +2 -2
- package/web/.next/static/chunks/d60c73bb353f26d3.js +1 -0
- package/web/.next/static/chunks/e6e3c4fe9248dbee.js +1 -0
- package/node_modules/jose/dist/webapi/lib/cek.js +0 -19
- package/node_modules/jose/dist/webapi/lib/check_cek_length.js +0 -7
- package/node_modules/jose/dist/webapi/lib/check_iv_length.js +0 -7
- package/node_modules/jose/dist/webapi/lib/check_key_length.js +0 -8
- package/node_modules/jose/dist/webapi/lib/decrypt.js +0 -106
- package/node_modules/jose/dist/webapi/lib/decrypt_key_management.js +0 -127
- package/node_modules/jose/dist/webapi/lib/digest.js +0 -4
- package/node_modules/jose/dist/webapi/lib/encrypt.js +0 -74
- package/node_modules/jose/dist/webapi/lib/encrypt_key_management.js +0 -92
- package/node_modules/jose/dist/webapi/lib/get_sign_verify_key.js +0 -12
- package/node_modules/jose/dist/webapi/lib/is_disjoint.js +0 -21
- package/node_modules/jose/dist/webapi/lib/is_jwk.js +0 -6
- package/node_modules/jose/dist/webapi/lib/is_object.js +0 -14
- package/node_modules/jose/dist/webapi/lib/iv.js +0 -19
- package/node_modules/jose/dist/webapi/lib/private_symbols.js +0 -1
- package/node_modules/jose/dist/webapi/lib/sign.js +0 -9
- package/node_modules/jose/dist/webapi/lib/subtle_dsa.js +0 -31
- package/node_modules/jose/dist/webapi/lib/verify.js +0 -14
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_2c78c2f3._.js +0 -3
- package/web/.next/standalone/packages/web/.next/static/chunks/7fd2a83e9e74f215.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/91e9e111a2536f92.js +0 -1
- package/web/.next/static/chunks/7fd2a83e9e74f215.js +0 -1
- package/web/.next/static/chunks/91e9e111a2536f92.js +0 -1
- /package/web/.next/standalone/packages/web/.next/static/{E4-NvSai1Ps20r9dtdpps → s8P8PtiSDD1N4unj4vBuY}/_buildManifest.js +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{E4-NvSai1Ps20r9dtdpps → s8P8PtiSDD1N4unj4vBuY}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{E4-NvSai1Ps20r9dtdpps → s8P8PtiSDD1N4unj4vBuY}/_ssgManifest.js +0 -0
- /package/web/.next/static/{E4-NvSai1Ps20r9dtdpps → s8P8PtiSDD1N4unj4vBuY}/_buildManifest.js +0 -0
- /package/web/.next/static/{E4-NvSai1Ps20r9dtdpps → s8P8PtiSDD1N4unj4vBuY}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{E4-NvSai1Ps20r9dtdpps → s8P8PtiSDD1N4unj4vBuY}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { concat, uint64be } from './buffer_utils.js';
|
|
2
|
+
import { checkEncCryptoKey } from './crypto_key.js';
|
|
3
|
+
import { invalidKeyInput } from './invalid_key_input.js';
|
|
4
|
+
import { JOSENotSupported, JWEDecryptionFailed, JWEInvalid } from '../util/errors.js';
|
|
5
|
+
import { isCryptoKey } from './is_key_like.js';
|
|
6
|
+
export function cekLength(alg) {
|
|
7
|
+
switch (alg) {
|
|
8
|
+
case 'A128GCM':
|
|
9
|
+
return 128;
|
|
10
|
+
case 'A192GCM':
|
|
11
|
+
return 192;
|
|
12
|
+
case 'A256GCM':
|
|
13
|
+
case 'A128CBC-HS256':
|
|
14
|
+
return 256;
|
|
15
|
+
case 'A192CBC-HS384':
|
|
16
|
+
return 384;
|
|
17
|
+
case 'A256CBC-HS512':
|
|
18
|
+
return 512;
|
|
19
|
+
default:
|
|
20
|
+
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export const generateCek = (alg) => crypto.getRandomValues(new Uint8Array(cekLength(alg) >> 3));
|
|
24
|
+
function checkCekLength(cek, expected) {
|
|
25
|
+
const actual = cek.byteLength << 3;
|
|
26
|
+
if (actual !== expected) {
|
|
27
|
+
throw new JWEInvalid(`Invalid Content Encryption Key length. Expected ${expected} bits, got ${actual} bits`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function ivBitLength(alg) {
|
|
31
|
+
switch (alg) {
|
|
32
|
+
case 'A128GCM':
|
|
33
|
+
case 'A128GCMKW':
|
|
34
|
+
case 'A192GCM':
|
|
35
|
+
case 'A192GCMKW':
|
|
36
|
+
case 'A256GCM':
|
|
37
|
+
case 'A256GCMKW':
|
|
38
|
+
return 96;
|
|
39
|
+
case 'A128CBC-HS256':
|
|
40
|
+
case 'A192CBC-HS384':
|
|
41
|
+
case 'A256CBC-HS512':
|
|
42
|
+
return 128;
|
|
43
|
+
default:
|
|
44
|
+
throw new JOSENotSupported(`Unsupported JWE Algorithm: ${alg}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export const generateIv = (alg) => crypto.getRandomValues(new Uint8Array(ivBitLength(alg) >> 3));
|
|
48
|
+
export function checkIvLength(enc, iv) {
|
|
49
|
+
if (iv.length << 3 !== ivBitLength(enc)) {
|
|
50
|
+
throw new JWEInvalid('Invalid Initialization Vector length');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function cbcKeySetup(enc, cek, usage) {
|
|
54
|
+
if (!(cek instanceof Uint8Array)) {
|
|
55
|
+
throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
|
|
56
|
+
}
|
|
57
|
+
const keySize = parseInt(enc.slice(1, 4), 10);
|
|
58
|
+
const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, [usage]);
|
|
59
|
+
const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {
|
|
60
|
+
hash: `SHA-${keySize << 1}`,
|
|
61
|
+
name: 'HMAC',
|
|
62
|
+
}, false, ['sign']);
|
|
63
|
+
return { encKey, macKey, keySize };
|
|
64
|
+
}
|
|
65
|
+
async function cbcHmacTag(macKey, macData, keySize) {
|
|
66
|
+
return new Uint8Array((await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3));
|
|
67
|
+
}
|
|
68
|
+
async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
69
|
+
const { encKey, macKey, keySize } = await cbcKeySetup(enc, cek, 'encrypt');
|
|
70
|
+
const ciphertext = new Uint8Array(await crypto.subtle.encrypt({
|
|
71
|
+
iv: iv,
|
|
72
|
+
name: 'AES-CBC',
|
|
73
|
+
}, encKey, plaintext));
|
|
74
|
+
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
|
|
75
|
+
const tag = await cbcHmacTag(macKey, macData, keySize);
|
|
76
|
+
return { ciphertext, tag, iv };
|
|
77
|
+
}
|
|
78
|
+
async function timingSafeEqual(a, b) {
|
|
79
|
+
if (!(a instanceof Uint8Array)) {
|
|
80
|
+
throw new TypeError('First argument must be a buffer');
|
|
81
|
+
}
|
|
82
|
+
if (!(b instanceof Uint8Array)) {
|
|
83
|
+
throw new TypeError('Second argument must be a buffer');
|
|
84
|
+
}
|
|
85
|
+
const algorithm = { name: 'HMAC', hash: 'SHA-256' };
|
|
86
|
+
const key = (await crypto.subtle.generateKey(algorithm, false, ['sign']));
|
|
87
|
+
const aHmac = new Uint8Array(await crypto.subtle.sign(algorithm, key, a));
|
|
88
|
+
const bHmac = new Uint8Array(await crypto.subtle.sign(algorithm, key, b));
|
|
89
|
+
let out = 0;
|
|
90
|
+
let i = -1;
|
|
91
|
+
while (++i < 32) {
|
|
92
|
+
out |= aHmac[i] ^ bHmac[i];
|
|
93
|
+
}
|
|
94
|
+
return out === 0;
|
|
95
|
+
}
|
|
96
|
+
async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
97
|
+
const { encKey, macKey, keySize } = await cbcKeySetup(enc, cek, 'decrypt');
|
|
98
|
+
const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3));
|
|
99
|
+
const expectedTag = await cbcHmacTag(macKey, macData, keySize);
|
|
100
|
+
let macCheckPassed;
|
|
101
|
+
try {
|
|
102
|
+
macCheckPassed = await timingSafeEqual(tag, expectedTag);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
}
|
|
106
|
+
if (!macCheckPassed) {
|
|
107
|
+
throw new JWEDecryptionFailed();
|
|
108
|
+
}
|
|
109
|
+
let plaintext;
|
|
110
|
+
try {
|
|
111
|
+
plaintext = new Uint8Array(await crypto.subtle.decrypt({ iv: iv, name: 'AES-CBC' }, encKey, ciphertext));
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
}
|
|
115
|
+
if (!plaintext) {
|
|
116
|
+
throw new JWEDecryptionFailed();
|
|
117
|
+
}
|
|
118
|
+
return plaintext;
|
|
119
|
+
}
|
|
120
|
+
async function gcmEncrypt(enc, plaintext, cek, iv, aad) {
|
|
121
|
+
let encKey;
|
|
122
|
+
if (cek instanceof Uint8Array) {
|
|
123
|
+
encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
checkEncCryptoKey(cek, enc, 'encrypt');
|
|
127
|
+
encKey = cek;
|
|
128
|
+
}
|
|
129
|
+
const encrypted = new Uint8Array(await crypto.subtle.encrypt({
|
|
130
|
+
additionalData: aad,
|
|
131
|
+
iv: iv,
|
|
132
|
+
name: 'AES-GCM',
|
|
133
|
+
tagLength: 128,
|
|
134
|
+
}, encKey, plaintext));
|
|
135
|
+
const tag = encrypted.slice(-16);
|
|
136
|
+
const ciphertext = encrypted.slice(0, -16);
|
|
137
|
+
return { ciphertext, tag, iv };
|
|
138
|
+
}
|
|
139
|
+
async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
140
|
+
let encKey;
|
|
141
|
+
if (cek instanceof Uint8Array) {
|
|
142
|
+
encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
checkEncCryptoKey(cek, enc, 'decrypt');
|
|
146
|
+
encKey = cek;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
return new Uint8Array(await crypto.subtle.decrypt({
|
|
150
|
+
additionalData: aad,
|
|
151
|
+
iv: iv,
|
|
152
|
+
name: 'AES-GCM',
|
|
153
|
+
tagLength: 128,
|
|
154
|
+
}, encKey, concat(ciphertext, tag)));
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
throw new JWEDecryptionFailed();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const unsupportedEnc = 'Unsupported JWE Content Encryption Algorithm';
|
|
161
|
+
export async function encrypt(enc, plaintext, cek, iv, aad) {
|
|
162
|
+
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
163
|
+
throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'KeyObject', 'Uint8Array', 'JSON Web Key'));
|
|
164
|
+
}
|
|
165
|
+
if (iv) {
|
|
166
|
+
checkIvLength(enc, iv);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
iv = generateIv(enc);
|
|
170
|
+
}
|
|
171
|
+
switch (enc) {
|
|
172
|
+
case 'A128CBC-HS256':
|
|
173
|
+
case 'A192CBC-HS384':
|
|
174
|
+
case 'A256CBC-HS512':
|
|
175
|
+
if (cek instanceof Uint8Array) {
|
|
176
|
+
checkCekLength(cek, parseInt(enc.slice(-3), 10));
|
|
177
|
+
}
|
|
178
|
+
return cbcEncrypt(enc, plaintext, cek, iv, aad);
|
|
179
|
+
case 'A128GCM':
|
|
180
|
+
case 'A192GCM':
|
|
181
|
+
case 'A256GCM':
|
|
182
|
+
if (cek instanceof Uint8Array) {
|
|
183
|
+
checkCekLength(cek, parseInt(enc.slice(1, 4), 10));
|
|
184
|
+
}
|
|
185
|
+
return gcmEncrypt(enc, plaintext, cek, iv, aad);
|
|
186
|
+
default:
|
|
187
|
+
throw new JOSENotSupported(unsupportedEnc);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
export async function decrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
191
|
+
if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) {
|
|
192
|
+
throw new TypeError(invalidKeyInput(cek, 'CryptoKey', 'KeyObject', 'Uint8Array', 'JSON Web Key'));
|
|
193
|
+
}
|
|
194
|
+
if (!iv) {
|
|
195
|
+
throw new JWEInvalid('JWE Initialization Vector missing');
|
|
196
|
+
}
|
|
197
|
+
if (!tag) {
|
|
198
|
+
throw new JWEInvalid('JWE Authentication Tag missing');
|
|
199
|
+
}
|
|
200
|
+
checkIvLength(enc, iv);
|
|
201
|
+
switch (enc) {
|
|
202
|
+
case 'A128CBC-HS256':
|
|
203
|
+
case 'A192CBC-HS384':
|
|
204
|
+
case 'A256CBC-HS512':
|
|
205
|
+
if (cek instanceof Uint8Array)
|
|
206
|
+
checkCekLength(cek, parseInt(enc.slice(-3), 10));
|
|
207
|
+
return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad);
|
|
208
|
+
case 'A128GCM':
|
|
209
|
+
case 'A192GCM':
|
|
210
|
+
case 'A256GCM':
|
|
211
|
+
if (cek instanceof Uint8Array)
|
|
212
|
+
checkCekLength(cek, parseInt(enc.slice(1, 4), 10));
|
|
213
|
+
return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
|
|
214
|
+
default:
|
|
215
|
+
throw new JOSENotSupported(unsupportedEnc);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -3,6 +3,11 @@ const isAlgorithm = (algorithm, name) => algorithm.name === name;
|
|
|
3
3
|
function getHashLength(hash) {
|
|
4
4
|
return parseInt(hash.name.slice(4), 10);
|
|
5
5
|
}
|
|
6
|
+
function checkHashLength(algorithm, expected) {
|
|
7
|
+
const actual = getHashLength(algorithm.hash);
|
|
8
|
+
if (actual !== expected)
|
|
9
|
+
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
10
|
+
}
|
|
6
11
|
function getNamedCurve(alg) {
|
|
7
12
|
switch (alg) {
|
|
8
13
|
case 'ES256':
|
|
@@ -27,10 +32,7 @@ export function checkSigCryptoKey(key, alg, usage) {
|
|
|
27
32
|
case 'HS512': {
|
|
28
33
|
if (!isAlgorithm(key.algorithm, 'HMAC'))
|
|
29
34
|
throw unusable('HMAC');
|
|
30
|
-
|
|
31
|
-
const actual = getHashLength(key.algorithm.hash);
|
|
32
|
-
if (actual !== expected)
|
|
33
|
-
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
35
|
+
checkHashLength(key.algorithm, parseInt(alg.slice(2), 10));
|
|
34
36
|
break;
|
|
35
37
|
}
|
|
36
38
|
case 'RS256':
|
|
@@ -38,10 +40,7 @@ export function checkSigCryptoKey(key, alg, usage) {
|
|
|
38
40
|
case 'RS512': {
|
|
39
41
|
if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))
|
|
40
42
|
throw unusable('RSASSA-PKCS1-v1_5');
|
|
41
|
-
|
|
42
|
-
const actual = getHashLength(key.algorithm.hash);
|
|
43
|
-
if (actual !== expected)
|
|
44
|
-
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
43
|
+
checkHashLength(key.algorithm, parseInt(alg.slice(2), 10));
|
|
45
44
|
break;
|
|
46
45
|
}
|
|
47
46
|
case 'PS256':
|
|
@@ -49,10 +48,7 @@ export function checkSigCryptoKey(key, alg, usage) {
|
|
|
49
48
|
case 'PS512': {
|
|
50
49
|
if (!isAlgorithm(key.algorithm, 'RSA-PSS'))
|
|
51
50
|
throw unusable('RSA-PSS');
|
|
52
|
-
|
|
53
|
-
const actual = getHashLength(key.algorithm.hash);
|
|
54
|
-
if (actual !== expected)
|
|
55
|
-
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
51
|
+
checkHashLength(key.algorithm, parseInt(alg.slice(2), 10));
|
|
56
52
|
break;
|
|
57
53
|
}
|
|
58
54
|
case 'Ed25519':
|
|
@@ -130,10 +126,7 @@ export function checkEncCryptoKey(key, alg, usage) {
|
|
|
130
126
|
case 'RSA-OAEP-512': {
|
|
131
127
|
if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))
|
|
132
128
|
throw unusable('RSA-OAEP');
|
|
133
|
-
|
|
134
|
-
const actual = getHashLength(key.algorithm.hash);
|
|
135
|
-
if (actual !== expected)
|
|
136
|
-
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
129
|
+
checkHashLength(key.algorithm, parseInt(alg.slice(9), 10) || 1);
|
|
137
130
|
break;
|
|
138
131
|
}
|
|
139
132
|
default:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { encode, concat, uint32be } from './buffer_utils.js';
|
|
2
2
|
import { checkEncCryptoKey } from './crypto_key.js';
|
|
3
|
-
import { digest } from './
|
|
3
|
+
import { digest } from './helpers.js';
|
|
4
4
|
function lengthAndInput(input) {
|
|
5
5
|
return concat(uint32be(input.length), input);
|
|
6
6
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { decode } from '../util/base64url.js';
|
|
2
|
+
export const unprotected = Symbol();
|
|
3
|
+
export function assertNotSet(value, name) {
|
|
4
|
+
if (value) {
|
|
5
|
+
throw new TypeError(`${name} can only be called once`);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export function decodeBase64url(value, label, ErrorClass) {
|
|
9
|
+
try {
|
|
10
|
+
return decode(value);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
throw new ErrorClass(`Failed to base64url decode the ${label}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export async function digest(algorithm, data) {
|
|
17
|
+
const subtleDigest = `SHA-${algorithm.slice(-3)}`;
|
|
18
|
+
return new Uint8Array(await crypto.subtle.digest(subtleDigest, data));
|
|
19
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { JOSENotSupported } from '../util/errors.js';
|
|
2
|
+
const unsupportedAlg = 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value';
|
|
2
3
|
function subtleMapping(jwk) {
|
|
3
4
|
let algorithm;
|
|
4
5
|
let keyUsages;
|
|
@@ -12,7 +13,7 @@ function subtleMapping(jwk) {
|
|
|
12
13
|
keyUsages = jwk.priv ? ['sign'] : ['verify'];
|
|
13
14
|
break;
|
|
14
15
|
default:
|
|
15
|
-
throw new JOSENotSupported(
|
|
16
|
+
throw new JOSENotSupported(unsupportedAlg);
|
|
16
17
|
}
|
|
17
18
|
break;
|
|
18
19
|
}
|
|
@@ -41,22 +42,19 @@ function subtleMapping(jwk) {
|
|
|
41
42
|
keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];
|
|
42
43
|
break;
|
|
43
44
|
default:
|
|
44
|
-
throw new JOSENotSupported(
|
|
45
|
+
throw new JOSENotSupported(unsupportedAlg);
|
|
45
46
|
}
|
|
46
47
|
break;
|
|
47
48
|
}
|
|
48
49
|
case 'EC': {
|
|
49
50
|
switch (jwk.alg) {
|
|
50
51
|
case 'ES256':
|
|
51
|
-
algorithm = { name: 'ECDSA', namedCurve: 'P-256' };
|
|
52
|
-
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
53
|
-
break;
|
|
54
52
|
case 'ES384':
|
|
55
|
-
algorithm = { name: 'ECDSA', namedCurve: 'P-384' };
|
|
56
|
-
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
57
|
-
break;
|
|
58
53
|
case 'ES512':
|
|
59
|
-
algorithm = {
|
|
54
|
+
algorithm = {
|
|
55
|
+
name: 'ECDSA',
|
|
56
|
+
namedCurve: { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' }[jwk.alg],
|
|
57
|
+
};
|
|
60
58
|
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
61
59
|
break;
|
|
62
60
|
case 'ECDH-ES':
|
|
@@ -67,7 +65,7 @@ function subtleMapping(jwk) {
|
|
|
67
65
|
keyUsages = jwk.d ? ['deriveBits'] : [];
|
|
68
66
|
break;
|
|
69
67
|
default:
|
|
70
|
-
throw new JOSENotSupported(
|
|
68
|
+
throw new JOSENotSupported(unsupportedAlg);
|
|
71
69
|
}
|
|
72
70
|
break;
|
|
73
71
|
}
|
|
@@ -86,7 +84,7 @@ function subtleMapping(jwk) {
|
|
|
86
84
|
keyUsages = jwk.d ? ['deriveBits'] : [];
|
|
87
85
|
break;
|
|
88
86
|
default:
|
|
89
|
-
throw new JOSENotSupported(
|
|
87
|
+
throw new JOSENotSupported(unsupportedAlg);
|
|
90
88
|
}
|
|
91
89
|
break;
|
|
92
90
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';
|
|
2
2
|
import { encoder, decoder } from './buffer_utils.js';
|
|
3
|
-
import { isObject } from './
|
|
3
|
+
import { isObject } from './type_checks.js';
|
|
4
4
|
const epoch = (date) => Math.floor(date.getTime() / 1000);
|
|
5
5
|
const minute = 60;
|
|
6
6
|
const hour = minute * 60;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import * as aeskw from './aeskw.js';
|
|
2
|
+
import * as ecdhes from './ecdhes.js';
|
|
3
|
+
import * as pbes2kw from './pbes2kw.js';
|
|
4
|
+
import * as rsaes from './rsaes.js';
|
|
5
|
+
import { encode as b64u } from '../util/base64url.js';
|
|
6
|
+
import { normalizeKey } from './normalize_key.js';
|
|
7
|
+
import { JOSENotSupported, JWEInvalid } from '../util/errors.js';
|
|
8
|
+
import { decodeBase64url } from './helpers.js';
|
|
9
|
+
import { generateCek, cekLength } from './content_encryption.js';
|
|
10
|
+
import { importJWK } from '../key/import.js';
|
|
11
|
+
import { exportJWK } from '../key/export.js';
|
|
12
|
+
import { isObject } from './type_checks.js';
|
|
13
|
+
import { wrap as aesGcmKwWrap, unwrap as aesGcmKwUnwrap } from './aesgcmkw.js';
|
|
14
|
+
import { assertCryptoKey } from './is_key_like.js';
|
|
15
|
+
const unsupportedAlgHeader = 'Invalid or unsupported "alg" (JWE Algorithm) header value';
|
|
16
|
+
function assertEncryptedKey(encryptedKey) {
|
|
17
|
+
if (encryptedKey === undefined)
|
|
18
|
+
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
19
|
+
}
|
|
20
|
+
export async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options) {
|
|
21
|
+
switch (alg) {
|
|
22
|
+
case 'dir': {
|
|
23
|
+
if (encryptedKey !== undefined)
|
|
24
|
+
throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
|
25
|
+
return key;
|
|
26
|
+
}
|
|
27
|
+
case 'ECDH-ES':
|
|
28
|
+
if (encryptedKey !== undefined)
|
|
29
|
+
throw new JWEInvalid('Encountered unexpected JWE Encrypted Key');
|
|
30
|
+
case 'ECDH-ES+A128KW':
|
|
31
|
+
case 'ECDH-ES+A192KW':
|
|
32
|
+
case 'ECDH-ES+A256KW': {
|
|
33
|
+
if (!isObject(joseHeader.epk))
|
|
34
|
+
throw new JWEInvalid(`JOSE Header "epk" (Ephemeral Public Key) missing or invalid`);
|
|
35
|
+
assertCryptoKey(key);
|
|
36
|
+
if (!ecdhes.allowed(key))
|
|
37
|
+
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
38
|
+
const epk = await importJWK(joseHeader.epk, alg);
|
|
39
|
+
assertCryptoKey(epk);
|
|
40
|
+
let partyUInfo;
|
|
41
|
+
let partyVInfo;
|
|
42
|
+
if (joseHeader.apu !== undefined) {
|
|
43
|
+
if (typeof joseHeader.apu !== 'string')
|
|
44
|
+
throw new JWEInvalid(`JOSE Header "apu" (Agreement PartyUInfo) invalid`);
|
|
45
|
+
partyUInfo = decodeBase64url(joseHeader.apu, 'apu', JWEInvalid);
|
|
46
|
+
}
|
|
47
|
+
if (joseHeader.apv !== undefined) {
|
|
48
|
+
if (typeof joseHeader.apv !== 'string')
|
|
49
|
+
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
50
|
+
partyVInfo = decodeBase64url(joseHeader.apv, 'apv', JWEInvalid);
|
|
51
|
+
}
|
|
52
|
+
const sharedSecret = await ecdhes.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo);
|
|
53
|
+
if (alg === 'ECDH-ES')
|
|
54
|
+
return sharedSecret;
|
|
55
|
+
assertEncryptedKey(encryptedKey);
|
|
56
|
+
return aeskw.unwrap(alg.slice(-6), sharedSecret, encryptedKey);
|
|
57
|
+
}
|
|
58
|
+
case 'RSA-OAEP':
|
|
59
|
+
case 'RSA-OAEP-256':
|
|
60
|
+
case 'RSA-OAEP-384':
|
|
61
|
+
case 'RSA-OAEP-512': {
|
|
62
|
+
assertEncryptedKey(encryptedKey);
|
|
63
|
+
assertCryptoKey(key);
|
|
64
|
+
return rsaes.decrypt(alg, key, encryptedKey);
|
|
65
|
+
}
|
|
66
|
+
case 'PBES2-HS256+A128KW':
|
|
67
|
+
case 'PBES2-HS384+A192KW':
|
|
68
|
+
case 'PBES2-HS512+A256KW': {
|
|
69
|
+
assertEncryptedKey(encryptedKey);
|
|
70
|
+
if (typeof joseHeader.p2c !== 'number')
|
|
71
|
+
throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
|
|
72
|
+
const p2cLimit = options?.maxPBES2Count || 10_000;
|
|
73
|
+
if (joseHeader.p2c > p2cLimit)
|
|
74
|
+
throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`);
|
|
75
|
+
if (typeof joseHeader.p2s !== 'string')
|
|
76
|
+
throw new JWEInvalid(`JOSE Header "p2s" (PBES2 Salt) missing or invalid`);
|
|
77
|
+
let p2s;
|
|
78
|
+
p2s = decodeBase64url(joseHeader.p2s, 'p2s', JWEInvalid);
|
|
79
|
+
return pbes2kw.unwrap(alg, key, encryptedKey, joseHeader.p2c, p2s);
|
|
80
|
+
}
|
|
81
|
+
case 'A128KW':
|
|
82
|
+
case 'A192KW':
|
|
83
|
+
case 'A256KW': {
|
|
84
|
+
assertEncryptedKey(encryptedKey);
|
|
85
|
+
return aeskw.unwrap(alg, key, encryptedKey);
|
|
86
|
+
}
|
|
87
|
+
case 'A128GCMKW':
|
|
88
|
+
case 'A192GCMKW':
|
|
89
|
+
case 'A256GCMKW': {
|
|
90
|
+
assertEncryptedKey(encryptedKey);
|
|
91
|
+
if (typeof joseHeader.iv !== 'string')
|
|
92
|
+
throw new JWEInvalid(`JOSE Header "iv" (Initialization Vector) missing or invalid`);
|
|
93
|
+
if (typeof joseHeader.tag !== 'string')
|
|
94
|
+
throw new JWEInvalid(`JOSE Header "tag" (Authentication Tag) missing or invalid`);
|
|
95
|
+
let iv;
|
|
96
|
+
iv = decodeBase64url(joseHeader.iv, 'iv', JWEInvalid);
|
|
97
|
+
let tag;
|
|
98
|
+
tag = decodeBase64url(joseHeader.tag, 'tag', JWEInvalid);
|
|
99
|
+
return aesGcmKwUnwrap(alg, key, encryptedKey, iv, tag);
|
|
100
|
+
}
|
|
101
|
+
default: {
|
|
102
|
+
throw new JOSENotSupported(unsupportedAlgHeader);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {
|
|
107
|
+
let encryptedKey;
|
|
108
|
+
let parameters;
|
|
109
|
+
let cek;
|
|
110
|
+
switch (alg) {
|
|
111
|
+
case 'dir': {
|
|
112
|
+
cek = key;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case 'ECDH-ES':
|
|
116
|
+
case 'ECDH-ES+A128KW':
|
|
117
|
+
case 'ECDH-ES+A192KW':
|
|
118
|
+
case 'ECDH-ES+A256KW': {
|
|
119
|
+
assertCryptoKey(key);
|
|
120
|
+
if (!ecdhes.allowed(key)) {
|
|
121
|
+
throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');
|
|
122
|
+
}
|
|
123
|
+
const { apu, apv } = providedParameters;
|
|
124
|
+
let ephemeralKey;
|
|
125
|
+
if (providedParameters.epk) {
|
|
126
|
+
ephemeralKey = (await normalizeKey(providedParameters.epk, alg));
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
ephemeralKey = (await crypto.subtle.generateKey(key.algorithm, true, ['deriveBits'])).privateKey;
|
|
130
|
+
}
|
|
131
|
+
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
|
|
132
|
+
const sharedSecret = await ecdhes.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv);
|
|
133
|
+
parameters = { epk: { x, crv, kty } };
|
|
134
|
+
if (kty === 'EC')
|
|
135
|
+
parameters.epk.y = y;
|
|
136
|
+
if (apu)
|
|
137
|
+
parameters.apu = b64u(apu);
|
|
138
|
+
if (apv)
|
|
139
|
+
parameters.apv = b64u(apv);
|
|
140
|
+
if (alg === 'ECDH-ES') {
|
|
141
|
+
cek = sharedSecret;
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
cek = providedCek || generateCek(enc);
|
|
145
|
+
const kwAlg = alg.slice(-6);
|
|
146
|
+
encryptedKey = await aeskw.wrap(kwAlg, sharedSecret, cek);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case 'RSA-OAEP':
|
|
150
|
+
case 'RSA-OAEP-256':
|
|
151
|
+
case 'RSA-OAEP-384':
|
|
152
|
+
case 'RSA-OAEP-512': {
|
|
153
|
+
cek = providedCek || generateCek(enc);
|
|
154
|
+
assertCryptoKey(key);
|
|
155
|
+
encryptedKey = await rsaes.encrypt(alg, key, cek);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case 'PBES2-HS256+A128KW':
|
|
159
|
+
case 'PBES2-HS384+A192KW':
|
|
160
|
+
case 'PBES2-HS512+A256KW': {
|
|
161
|
+
cek = providedCek || generateCek(enc);
|
|
162
|
+
const { p2c, p2s } = providedParameters;
|
|
163
|
+
({ encryptedKey, ...parameters } = await pbes2kw.wrap(alg, key, cek, p2c, p2s));
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case 'A128KW':
|
|
167
|
+
case 'A192KW':
|
|
168
|
+
case 'A256KW': {
|
|
169
|
+
cek = providedCek || generateCek(enc);
|
|
170
|
+
encryptedKey = await aeskw.wrap(alg, key, cek);
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 'A128GCMKW':
|
|
174
|
+
case 'A192GCMKW':
|
|
175
|
+
case 'A256GCMKW': {
|
|
176
|
+
cek = providedCek || generateCek(enc);
|
|
177
|
+
const { iv } = providedParameters;
|
|
178
|
+
({ encryptedKey, ...parameters } = await aesGcmKwWrap(alg, key, cek, iv));
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
default: {
|
|
182
|
+
throw new JOSENotSupported(unsupportedAlgHeader);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return { cek, encryptedKey, parameters };
|
|
186
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { isJWK } from './
|
|
1
|
+
import { isJWK } from './type_checks.js';
|
|
2
2
|
import { decode } from '../util/base64url.js';
|
|
3
3
|
import { jwkToKey } from './jwk_to_key.js';
|
|
4
4
|
import { isCryptoKey, isKeyObject } from './is_key_like.js';
|
|
5
|
+
const unusableForAlg = 'given KeyObject instance cannot be used for this algorithm';
|
|
5
6
|
let cache;
|
|
6
7
|
const handleJWK = async (key, jwk, alg, freeze = false) => {
|
|
7
8
|
cache ||= new WeakMap();
|
|
@@ -37,13 +38,13 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
37
38
|
case 'ECDH-ES+A256KW':
|
|
38
39
|
break;
|
|
39
40
|
default:
|
|
40
|
-
throw new TypeError(
|
|
41
|
+
throw new TypeError(unusableForAlg);
|
|
41
42
|
}
|
|
42
43
|
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, isPublic ? [] : ['deriveBits']);
|
|
43
44
|
}
|
|
44
45
|
if (keyObject.asymmetricKeyType === 'ed25519') {
|
|
45
46
|
if (alg !== 'EdDSA' && alg !== 'Ed25519') {
|
|
46
|
-
throw new TypeError(
|
|
47
|
+
throw new TypeError(unusableForAlg);
|
|
47
48
|
}
|
|
48
49
|
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
|
|
49
50
|
isPublic ? 'verify' : 'sign',
|
|
@@ -54,7 +55,7 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
54
55
|
case 'ml-dsa-65':
|
|
55
56
|
case 'ml-dsa-87': {
|
|
56
57
|
if (alg !== keyObject.asymmetricKeyType.toUpperCase()) {
|
|
57
|
-
throw new TypeError(
|
|
58
|
+
throw new TypeError(unusableForAlg);
|
|
58
59
|
}
|
|
59
60
|
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
|
|
60
61
|
isPublic ? 'verify' : 'sign',
|
|
@@ -83,7 +84,7 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
83
84
|
hash = 'SHA-512';
|
|
84
85
|
break;
|
|
85
86
|
default:
|
|
86
|
-
throw new TypeError(
|
|
87
|
+
throw new TypeError(unusableForAlg);
|
|
87
88
|
}
|
|
88
89
|
if (alg.startsWith('RSA-OAEP')) {
|
|
89
90
|
return keyObject.toCryptoKey({
|
|
@@ -104,21 +105,10 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
104
105
|
]);
|
|
105
106
|
const namedCurve = nist.get(keyObject.asymmetricKeyDetails?.namedCurve);
|
|
106
107
|
if (!namedCurve) {
|
|
107
|
-
throw new TypeError(
|
|
108
|
+
throw new TypeError(unusableForAlg);
|
|
108
109
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
name: 'ECDSA',
|
|
112
|
-
namedCurve,
|
|
113
|
-
}, extractable, [isPublic ? 'verify' : 'sign']);
|
|
114
|
-
}
|
|
115
|
-
if (alg === 'ES384' && namedCurve === 'P-384') {
|
|
116
|
-
cryptoKey = keyObject.toCryptoKey({
|
|
117
|
-
name: 'ECDSA',
|
|
118
|
-
namedCurve,
|
|
119
|
-
}, extractable, [isPublic ? 'verify' : 'sign']);
|
|
120
|
-
}
|
|
121
|
-
if (alg === 'ES512' && namedCurve === 'P-521') {
|
|
110
|
+
const expectedCurve = { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' };
|
|
111
|
+
if (expectedCurve[alg] && namedCurve === expectedCurve[alg]) {
|
|
122
112
|
cryptoKey = keyObject.toCryptoKey({
|
|
123
113
|
name: 'ECDSA',
|
|
124
114
|
namedCurve,
|
|
@@ -132,7 +122,7 @@ const handleKeyObject = (keyObject, alg) => {
|
|
|
132
122
|
}
|
|
133
123
|
}
|
|
134
124
|
if (!cryptoKey) {
|
|
135
|
-
throw new TypeError(
|
|
125
|
+
throw new TypeError(unusableForAlg);
|
|
136
126
|
}
|
|
137
127
|
if (!cached) {
|
|
138
128
|
cache.set(keyObject, { [alg]: cryptoKey });
|