jose 4.3.4 → 4.3.8
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/dist/browser/jwks/remote.js +1 -1
- package/dist/browser/lib/aesgcmkw.js +2 -2
- package/dist/browser/lib/crypto_key.js +7 -7
- package/dist/browser/lib/decrypt_key_management.js +2 -2
- package/dist/browser/lib/encrypt_key_management.js +3 -3
- package/dist/browser/runtime/aeskw.js +1 -1
- package/dist/browser/runtime/asn1.js +21 -20
- package/dist/browser/runtime/decrypt.js +3 -3
- package/dist/browser/runtime/digest.js +1 -1
- package/dist/browser/runtime/ecdhes.js +8 -9
- package/dist/browser/runtime/encrypt.js +3 -3
- package/dist/browser/runtime/generate.js +7 -7
- package/dist/browser/runtime/get_sign_verify_key.js +1 -1
- package/dist/browser/runtime/jwk_to_key.js +4 -4
- package/dist/browser/runtime/pbes2kw.js +4 -4
- package/dist/browser/runtime/sign.js +1 -1
- package/dist/browser/runtime/subtle_dsa.js +7 -6
- package/dist/browser/runtime/verify.js +1 -1
- package/dist/node/cjs/jwks/remote.js +1 -1
- package/dist/node/cjs/lib/aesgcmkw.js +2 -2
- package/dist/node/cjs/lib/crypto_key.js +7 -7
- package/dist/node/cjs/lib/decrypt_key_management.js +2 -2
- package/dist/node/cjs/lib/encrypt_key_management.js +3 -3
- package/dist/node/cjs/runtime/aeskw.js +4 -5
- package/dist/node/cjs/runtime/check_cek_length.js +2 -2
- package/dist/node/cjs/runtime/decrypt.js +3 -3
- package/dist/node/cjs/runtime/ecdhes.js +7 -7
- package/dist/node/cjs/runtime/encrypt.js +3 -3
- package/dist/node/cjs/runtime/generate.js +2 -2
- package/dist/node/cjs/runtime/get_named_curve.js +2 -2
- package/dist/node/cjs/runtime/get_sign_verify_key.js +1 -2
- package/dist/node/cjs/runtime/jwk_to_key.js +1 -1
- package/dist/node/cjs/runtime/key_to_jwk.js +1 -1
- package/dist/node/cjs/runtime/node_key.js +4 -3
- package/dist/node/cjs/runtime/pbes2kw.js +6 -6
- package/dist/node/cjs/runtime/verify.js +1 -1
- package/dist/node/esm/jwks/remote.js +1 -1
- package/dist/node/esm/lib/aesgcmkw.js +2 -2
- package/dist/node/esm/lib/crypto_key.js +7 -7
- package/dist/node/esm/lib/decrypt_key_management.js +2 -2
- package/dist/node/esm/lib/encrypt_key_management.js +3 -3
- package/dist/node/esm/runtime/aeskw.js +5 -6
- package/dist/node/esm/runtime/check_cek_length.js +2 -2
- package/dist/node/esm/runtime/decrypt.js +3 -3
- package/dist/node/esm/runtime/ecdhes.js +7 -7
- package/dist/node/esm/runtime/encrypt.js +3 -3
- package/dist/node/esm/runtime/generate.js +2 -2
- package/dist/node/esm/runtime/get_named_curve.js +2 -2
- package/dist/node/esm/runtime/get_sign_verify_key.js +2 -3
- package/dist/node/esm/runtime/jwk_to_key.js +1 -1
- package/dist/node/esm/runtime/key_to_jwk.js +1 -1
- package/dist/node/esm/runtime/node_key.js +4 -3
- package/dist/node/esm/runtime/pbes2kw.js +6 -6
- package/dist/node/esm/runtime/verify.js +1 -1
- package/dist/types/types.d.ts +1 -1
- package/package.json +1 -1
- package/dist/node/cjs/runtime/secret_key.js +0 -14
- package/dist/node/esm/runtime/secret_key.js +0 -11
|
@@ -3,7 +3,7 @@ import { importJWK } from '../key/import.js';
|
|
|
3
3
|
import { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';
|
|
4
4
|
import isObject from '../lib/is_object.js';
|
|
5
5
|
function getKtyFromAlg(alg) {
|
|
6
|
-
switch (typeof alg === 'string' && alg.
|
|
6
|
+
switch (typeof alg === 'string' && alg.slice(0, 2)) {
|
|
7
7
|
case 'RS':
|
|
8
8
|
case 'PS':
|
|
9
9
|
return 'RSA';
|
|
@@ -3,12 +3,12 @@ import decrypt from '../runtime/decrypt.js';
|
|
|
3
3
|
import generateIv from './iv.js';
|
|
4
4
|
import { encode as base64url } from '../runtime/base64url.js';
|
|
5
5
|
export async function wrap(alg, key, cek, iv) {
|
|
6
|
-
const jweAlgorithm = alg.
|
|
6
|
+
const jweAlgorithm = alg.slice(0, 7);
|
|
7
7
|
iv || (iv = generateIv(jweAlgorithm));
|
|
8
8
|
const { ciphertext: encryptedKey, tag } = await encrypt(jweAlgorithm, cek, key, iv, new Uint8Array(0));
|
|
9
9
|
return { encryptedKey, iv: base64url(iv), tag: base64url(tag) };
|
|
10
10
|
}
|
|
11
11
|
export async function unwrap(alg, key, encryptedKey, iv, tag) {
|
|
12
|
-
const jweAlgorithm = alg.
|
|
12
|
+
const jweAlgorithm = alg.slice(0, 7);
|
|
13
13
|
return decrypt(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
|
|
14
14
|
}
|
|
@@ -6,7 +6,7 @@ function isAlgorithm(algorithm, name) {
|
|
|
6
6
|
return algorithm.name === name;
|
|
7
7
|
}
|
|
8
8
|
function getHashLength(hash) {
|
|
9
|
-
return parseInt(hash.name.
|
|
9
|
+
return parseInt(hash.name.slice(4), 10);
|
|
10
10
|
}
|
|
11
11
|
function getNamedCurve(alg) {
|
|
12
12
|
switch (alg) {
|
|
@@ -43,7 +43,7 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
43
43
|
case 'HS512': {
|
|
44
44
|
if (!isAlgorithm(key.algorithm, 'HMAC'))
|
|
45
45
|
throw unusable('HMAC');
|
|
46
|
-
const expected = parseInt(alg.
|
|
46
|
+
const expected = parseInt(alg.slice(2), 10);
|
|
47
47
|
const actual = getHashLength(key.algorithm.hash);
|
|
48
48
|
if (actual !== expected)
|
|
49
49
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -54,7 +54,7 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
54
54
|
case 'RS512': {
|
|
55
55
|
if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))
|
|
56
56
|
throw unusable('RSASSA-PKCS1-v1_5');
|
|
57
|
-
const expected = parseInt(alg.
|
|
57
|
+
const expected = parseInt(alg.slice(2), 10);
|
|
58
58
|
const actual = getHashLength(key.algorithm.hash);
|
|
59
59
|
if (actual !== expected)
|
|
60
60
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -65,7 +65,7 @@ export function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
65
65
|
case 'PS512': {
|
|
66
66
|
if (!isAlgorithm(key.algorithm, 'RSA-PSS'))
|
|
67
67
|
throw unusable('RSA-PSS');
|
|
68
|
-
const expected = parseInt(alg.
|
|
68
|
+
const expected = parseInt(alg.slice(2), 10);
|
|
69
69
|
const actual = getHashLength(key.algorithm.hash);
|
|
70
70
|
if (actual !== expected)
|
|
71
71
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -104,7 +104,7 @@ export function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
104
104
|
case 'A256GCM': {
|
|
105
105
|
if (!isAlgorithm(key.algorithm, 'AES-GCM'))
|
|
106
106
|
throw unusable('AES-GCM');
|
|
107
|
-
const expected = parseInt(alg.
|
|
107
|
+
const expected = parseInt(alg.slice(1, 4), 10);
|
|
108
108
|
const actual = key.algorithm.length;
|
|
109
109
|
if (actual !== expected)
|
|
110
110
|
throw unusable(expected, 'algorithm.length');
|
|
@@ -115,7 +115,7 @@ export function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
115
115
|
case 'A256KW': {
|
|
116
116
|
if (!isAlgorithm(key.algorithm, 'AES-KW'))
|
|
117
117
|
throw unusable('AES-KW');
|
|
118
|
-
const expected = parseInt(alg.
|
|
118
|
+
const expected = parseInt(alg.slice(1, 4), 10);
|
|
119
119
|
const actual = key.algorithm.length;
|
|
120
120
|
if (actual !== expected)
|
|
121
121
|
throw unusable(expected, 'algorithm.length');
|
|
@@ -137,7 +137,7 @@ export function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
137
137
|
case 'RSA-OAEP-512': {
|
|
138
138
|
if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))
|
|
139
139
|
throw unusable('RSA-OAEP');
|
|
140
|
-
const expected = parseInt(alg.
|
|
140
|
+
const expected = parseInt(alg.slice(9), 10) || 1;
|
|
141
141
|
const actual = getHashLength(key.algorithm.hash);
|
|
142
142
|
if (actual !== expected)
|
|
143
143
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -40,12 +40,12 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
|
40
40
|
throw new JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
41
41
|
partyVInfo = base64url(joseHeader.apv);
|
|
42
42
|
}
|
|
43
|
-
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? cekLength(joseHeader.enc) : parseInt(alg.
|
|
43
|
+
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);
|
|
44
44
|
if (alg === 'ECDH-ES')
|
|
45
45
|
return sharedSecret;
|
|
46
46
|
if (encryptedKey === undefined)
|
|
47
47
|
throw new JWEInvalid('JWE Encrypted Key missing');
|
|
48
|
-
return aesKw(alg.
|
|
48
|
+
return aesKw(alg.slice(-6), sharedSecret, encryptedKey);
|
|
49
49
|
}
|
|
50
50
|
case 'RSA1_5':
|
|
51
51
|
case 'RSA-OAEP':
|
|
@@ -27,9 +27,9 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
27
27
|
}
|
|
28
28
|
const { apu, apv } = providedParameters;
|
|
29
29
|
let { epk: ephemeralKey } = providedParameters;
|
|
30
|
-
ephemeralKey || (ephemeralKey = await ECDH.generateEpk(key));
|
|
30
|
+
ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey);
|
|
31
31
|
const { x, y, crv, kty } = await exportJWK(ephemeralKey);
|
|
32
|
-
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.
|
|
32
|
+
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);
|
|
33
33
|
parameters = { epk: { x, y, crv, kty } };
|
|
34
34
|
if (apu)
|
|
35
35
|
parameters.apu = base64url(apu);
|
|
@@ -40,7 +40,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
40
40
|
break;
|
|
41
41
|
}
|
|
42
42
|
cek = providedCek || generateCek(enc);
|
|
43
|
-
const kwAlg = alg.
|
|
43
|
+
const kwAlg = alg.slice(-6);
|
|
44
44
|
encryptedKey = await aesKw(kwAlg, sharedSecret, cek);
|
|
45
45
|
break;
|
|
46
46
|
}
|
|
@@ -4,7 +4,7 @@ import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
|
4
4
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
5
5
|
import { types } from './is_key_like.js';
|
|
6
6
|
function checkKeySize(key, alg) {
|
|
7
|
-
if (key.algorithm.length !== parseInt(alg.
|
|
7
|
+
if (key.algorithm.length !== parseInt(alg.slice(1, 4), 10)) {
|
|
8
8
|
throw new TypeError(`Invalid key size for alg: ${alg}`);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -23,29 +23,30 @@ export const toSPKI = (key) => {
|
|
|
23
23
|
export const toPKCS8 = (key) => {
|
|
24
24
|
return genericExport('private', 'pkcs8', key);
|
|
25
25
|
};
|
|
26
|
+
const findOid = (keyData, oid, from = 0) => {
|
|
27
|
+
if (from === 0) {
|
|
28
|
+
oid.unshift(oid.length);
|
|
29
|
+
oid.unshift(0x06);
|
|
30
|
+
}
|
|
31
|
+
let i = keyData.indexOf(oid[0], from);
|
|
32
|
+
if (i === -1)
|
|
33
|
+
return false;
|
|
34
|
+
const sub = keyData.subarray(i, i + oid.length);
|
|
35
|
+
if (sub.length !== oid.length)
|
|
36
|
+
return false;
|
|
37
|
+
return sub.every((value, index) => value === oid[index]) || findOid(keyData, oid, i + 1);
|
|
38
|
+
};
|
|
26
39
|
const getNamedCurve = (keyData) => {
|
|
27
|
-
const keyDataStr = keyData.toString();
|
|
28
40
|
switch (true) {
|
|
29
|
-
case
|
|
30
|
-
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
|
|
31
|
-
0x3d, 0x03, 0x01, 0x07,
|
|
32
|
-
]).toString()):
|
|
41
|
+
case findOid(keyData, [0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]):
|
|
33
42
|
return 'P-256';
|
|
34
|
-
case
|
|
35
|
-
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
|
|
36
|
-
0x22,
|
|
37
|
-
]).toString()):
|
|
43
|
+
case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x22]):
|
|
38
44
|
return 'P-384';
|
|
39
|
-
case
|
|
40
|
-
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
|
|
41
|
-
0x23,
|
|
42
|
-
]).toString()):
|
|
45
|
+
case findOid(keyData, [0x2b, 0x81, 0x04, 0x00, 0x23]):
|
|
43
46
|
return 'P-521';
|
|
44
|
-
case (isCloudflareWorkers() || isNodeJs()) &&
|
|
45
|
-
keyDataStr.includes(new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x70]).toString()):
|
|
47
|
+
case (isCloudflareWorkers() || isNodeJs()) && findOid(keyData, [0x2b, 0x65, 0x70]):
|
|
46
48
|
return 'Ed25519';
|
|
47
|
-
case isNodeJs() &&
|
|
48
|
-
keyDataStr.includes(new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x71]).toString()):
|
|
49
|
+
case isNodeJs() && findOid(keyData, [0x2b, 0x65, 0x71]):
|
|
49
50
|
return 'Ed448';
|
|
50
51
|
default:
|
|
51
52
|
throw new JOSENotSupported('Invalid or unsupported EC Key Curve or OKP Key Sub Type');
|
|
@@ -63,13 +64,13 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
|
63
64
|
case 'PS256':
|
|
64
65
|
case 'PS384':
|
|
65
66
|
case 'PS512':
|
|
66
|
-
algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.
|
|
67
|
+
algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` };
|
|
67
68
|
keyUsages = isPublic ? ['verify'] : ['sign'];
|
|
68
69
|
break;
|
|
69
70
|
case 'RS256':
|
|
70
71
|
case 'RS384':
|
|
71
72
|
case 'RS512':
|
|
72
|
-
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.
|
|
73
|
+
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` };
|
|
73
74
|
keyUsages = isPublic ? ['verify'] : ['sign'];
|
|
74
75
|
break;
|
|
75
76
|
case 'RSA-OAEP':
|
|
@@ -78,7 +79,7 @@ const genericImport = async (replace, keyFormat, pem, alg, options) => {
|
|
|
78
79
|
case 'RSA-OAEP-512':
|
|
79
80
|
algorithm = {
|
|
80
81
|
name: 'RSA-OAEP',
|
|
81
|
-
hash: `SHA-${parseInt(alg.
|
|
82
|
+
hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`,
|
|
82
83
|
};
|
|
83
84
|
keyUsages = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey'];
|
|
84
85
|
break;
|
|
@@ -11,7 +11,7 @@ async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) {
|
|
|
11
11
|
if (!(cek instanceof Uint8Array)) {
|
|
12
12
|
throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
|
|
13
13
|
}
|
|
14
|
-
const keySize = parseInt(enc.
|
|
14
|
+
const keySize = parseInt(enc.slice(1, 4), 10);
|
|
15
15
|
const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['decrypt']);
|
|
16
16
|
const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {
|
|
17
17
|
hash: `SHA-${keySize << 1}`,
|
|
@@ -70,13 +70,13 @@ const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => {
|
|
|
70
70
|
case 'A192CBC-HS384':
|
|
71
71
|
case 'A256CBC-HS512':
|
|
72
72
|
if (cek instanceof Uint8Array)
|
|
73
|
-
checkCekLength(cek, parseInt(enc.
|
|
73
|
+
checkCekLength(cek, parseInt(enc.slice(-3), 10));
|
|
74
74
|
return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad);
|
|
75
75
|
case 'A128GCM':
|
|
76
76
|
case 'A192GCM':
|
|
77
77
|
case 'A256GCM':
|
|
78
78
|
if (cek instanceof Uint8Array)
|
|
79
|
-
checkCekLength(cek, parseInt(enc.
|
|
79
|
+
checkCekLength(cek, parseInt(enc.slice(1, 4), 10));
|
|
80
80
|
return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad);
|
|
81
81
|
default:
|
|
82
82
|
throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from './webcrypto.js';
|
|
2
2
|
const digest = async (algorithm, data) => {
|
|
3
|
-
const subtleDigest = `SHA-${algorithm.
|
|
3
|
+
const subtleDigest = `SHA-${algorithm.slice(-3)}`;
|
|
4
4
|
return new Uint8Array(await crypto.subtle.digest(subtleDigest, data));
|
|
5
5
|
};
|
|
6
6
|
export default digest;
|
|
@@ -4,7 +4,7 @@ import { checkEncCryptoKey } from '../lib/crypto_key.js';
|
|
|
4
4
|
import digest from './digest.js';
|
|
5
5
|
import invalidKeyInput from '../lib/invalid_key_input.js';
|
|
6
6
|
import { types } from './is_key_like.js';
|
|
7
|
-
export
|
|
7
|
+
export async function deriveKey(publicKey, privateKey, algorithm, keyLength, apu = new Uint8Array(0), apv = new Uint8Array(0)) {
|
|
8
8
|
if (!isCryptoKey(publicKey)) {
|
|
9
9
|
throw new TypeError(invalidKeyInput(publicKey, ...types));
|
|
10
10
|
}
|
|
@@ -20,19 +20,18 @@ export const deriveKey = async (publicKey, privateKey, algorithm, keyLength, apu
|
|
|
20
20
|
const sharedSecret = new Uint8Array(await crypto.subtle.deriveBits({
|
|
21
21
|
name: 'ECDH',
|
|
22
22
|
public: publicKey,
|
|
23
|
-
}, privateKey, Math.ceil(parseInt(privateKey.algorithm.namedCurve.
|
|
24
|
-
3));
|
|
23
|
+
}, privateKey, Math.ceil(parseInt(privateKey.algorithm.namedCurve.slice(-3), 10) / 8) << 3));
|
|
25
24
|
return concatKdf(digest, sharedSecret, keyLength, value);
|
|
26
|
-
}
|
|
27
|
-
export
|
|
25
|
+
}
|
|
26
|
+
export async function generateEpk(key) {
|
|
28
27
|
if (!isCryptoKey(key)) {
|
|
29
28
|
throw new TypeError(invalidKeyInput(key, ...types));
|
|
30
29
|
}
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
export
|
|
30
|
+
return crypto.subtle.generateKey(key.algorithm, true, ['deriveBits']);
|
|
31
|
+
}
|
|
32
|
+
export function ecdhAllowed(key) {
|
|
34
33
|
if (!isCryptoKey(key)) {
|
|
35
34
|
throw new TypeError(invalidKeyInput(key, ...types));
|
|
36
35
|
}
|
|
37
36
|
return ['P-256', 'P-384', 'P-521'].includes(key.algorithm.namedCurve);
|
|
38
|
-
}
|
|
37
|
+
}
|
|
@@ -10,7 +10,7 @@ async function cbcEncrypt(enc, plaintext, cek, iv, aad) {
|
|
|
10
10
|
if (!(cek instanceof Uint8Array)) {
|
|
11
11
|
throw new TypeError(invalidKeyInput(cek, 'Uint8Array'));
|
|
12
12
|
}
|
|
13
|
-
const keySize = parseInt(enc.
|
|
13
|
+
const keySize = parseInt(enc.slice(1, 4), 10);
|
|
14
14
|
const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['encrypt']);
|
|
15
15
|
const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), {
|
|
16
16
|
hash: `SHA-${keySize << 1}`,
|
|
@@ -53,13 +53,13 @@ const encrypt = async (enc, plaintext, cek, iv, aad) => {
|
|
|
53
53
|
case 'A192CBC-HS384':
|
|
54
54
|
case 'A256CBC-HS512':
|
|
55
55
|
if (cek instanceof Uint8Array)
|
|
56
|
-
checkCekLength(cek, parseInt(enc.
|
|
56
|
+
checkCekLength(cek, parseInt(enc.slice(-3), 10));
|
|
57
57
|
return cbcEncrypt(enc, plaintext, cek, iv, aad);
|
|
58
58
|
case 'A128GCM':
|
|
59
59
|
case 'A192GCM':
|
|
60
60
|
case 'A256GCM':
|
|
61
61
|
if (cek instanceof Uint8Array)
|
|
62
|
-
checkCekLength(cek, parseInt(enc.
|
|
62
|
+
checkCekLength(cek, parseInt(enc.slice(1, 4), 10));
|
|
63
63
|
return gcmEncrypt(enc, plaintext, cek, iv, aad);
|
|
64
64
|
default:
|
|
65
65
|
throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm');
|
|
@@ -11,19 +11,19 @@ export async function generateSecret(alg, options) {
|
|
|
11
11
|
case 'HS256':
|
|
12
12
|
case 'HS384':
|
|
13
13
|
case 'HS512':
|
|
14
|
-
length = parseInt(alg.
|
|
14
|
+
length = parseInt(alg.slice(-3), 10);
|
|
15
15
|
algorithm = { name: 'HMAC', hash: `SHA-${length}`, length };
|
|
16
16
|
keyUsages = ['sign', 'verify'];
|
|
17
17
|
break;
|
|
18
18
|
case 'A128CBC-HS256':
|
|
19
19
|
case 'A192CBC-HS384':
|
|
20
20
|
case 'A256CBC-HS512':
|
|
21
|
-
length = parseInt(alg.
|
|
21
|
+
length = parseInt(alg.slice(-3), 10);
|
|
22
22
|
return random(new Uint8Array(length >> 3));
|
|
23
23
|
case 'A128KW':
|
|
24
24
|
case 'A192KW':
|
|
25
25
|
case 'A256KW':
|
|
26
|
-
length = parseInt(alg.
|
|
26
|
+
length = parseInt(alg.slice(1, 4), 10);
|
|
27
27
|
algorithm = { name: 'AES-KW', length };
|
|
28
28
|
keyUsages = ['wrapKey', 'unwrapKey'];
|
|
29
29
|
break;
|
|
@@ -33,7 +33,7 @@ export async function generateSecret(alg, options) {
|
|
|
33
33
|
case 'A128GCM':
|
|
34
34
|
case 'A192GCM':
|
|
35
35
|
case 'A256GCM':
|
|
36
|
-
length = parseInt(alg.
|
|
36
|
+
length = parseInt(alg.slice(1, 4), 10);
|
|
37
37
|
algorithm = { name: 'AES-GCM', length };
|
|
38
38
|
keyUsages = ['encrypt', 'decrypt'];
|
|
39
39
|
break;
|
|
@@ -60,7 +60,7 @@ export async function generateKeyPair(alg, options) {
|
|
|
60
60
|
case 'PS512':
|
|
61
61
|
algorithm = {
|
|
62
62
|
name: 'RSA-PSS',
|
|
63
|
-
hash: `SHA-${alg.
|
|
63
|
+
hash: `SHA-${alg.slice(-3)}`,
|
|
64
64
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
65
65
|
modulusLength: getModulusLengthOption(options),
|
|
66
66
|
};
|
|
@@ -71,7 +71,7 @@ export async function generateKeyPair(alg, options) {
|
|
|
71
71
|
case 'RS512':
|
|
72
72
|
algorithm = {
|
|
73
73
|
name: 'RSASSA-PKCS1-v1_5',
|
|
74
|
-
hash: `SHA-${alg.
|
|
74
|
+
hash: `SHA-${alg.slice(-3)}`,
|
|
75
75
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
76
76
|
modulusLength: getModulusLengthOption(options),
|
|
77
77
|
};
|
|
@@ -83,7 +83,7 @@ export async function generateKeyPair(alg, options) {
|
|
|
83
83
|
case 'RSA-OAEP-512':
|
|
84
84
|
algorithm = {
|
|
85
85
|
name: 'RSA-OAEP',
|
|
86
|
-
hash: `SHA-${parseInt(alg.
|
|
86
|
+
hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`,
|
|
87
87
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
88
88
|
modulusLength: getModulusLengthOption(options),
|
|
89
89
|
};
|
|
@@ -11,7 +11,7 @@ export default function getCryptoKey(alg, key, usage) {
|
|
|
11
11
|
if (!alg.startsWith('HS')) {
|
|
12
12
|
throw new TypeError(invalidKeyInput(key, ...types));
|
|
13
13
|
}
|
|
14
|
-
return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.
|
|
14
|
+
return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, false, [usage]);
|
|
15
15
|
}
|
|
16
16
|
throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array'));
|
|
17
17
|
}
|
|
@@ -11,7 +11,7 @@ function subtleMapping(jwk) {
|
|
|
11
11
|
case 'HS256':
|
|
12
12
|
case 'HS384':
|
|
13
13
|
case 'HS512':
|
|
14
|
-
algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.
|
|
14
|
+
algorithm = { name: 'HMAC', hash: `SHA-${jwk.alg.slice(-3)}` };
|
|
15
15
|
keyUsages = ['sign', 'verify'];
|
|
16
16
|
break;
|
|
17
17
|
case 'A128CBC-HS256':
|
|
@@ -49,13 +49,13 @@ function subtleMapping(jwk) {
|
|
|
49
49
|
case 'PS256':
|
|
50
50
|
case 'PS384':
|
|
51
51
|
case 'PS512':
|
|
52
|
-
algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.
|
|
52
|
+
algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` };
|
|
53
53
|
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
54
54
|
break;
|
|
55
55
|
case 'RS256':
|
|
56
56
|
case 'RS384':
|
|
57
57
|
case 'RS512':
|
|
58
|
-
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.
|
|
58
|
+
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` };
|
|
59
59
|
keyUsages = jwk.d ? ['sign'] : ['verify'];
|
|
60
60
|
break;
|
|
61
61
|
case 'RSA-OAEP':
|
|
@@ -64,7 +64,7 @@ function subtleMapping(jwk) {
|
|
|
64
64
|
case 'RSA-OAEP-512':
|
|
65
65
|
algorithm = {
|
|
66
66
|
name: 'RSA-OAEP',
|
|
67
|
-
hash: `SHA-${parseInt(jwk.alg.
|
|
67
|
+
hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`,
|
|
68
68
|
};
|
|
69
69
|
keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];
|
|
70
70
|
break;
|
|
@@ -20,9 +20,9 @@ function getCryptoKey(key, alg) {
|
|
|
20
20
|
async function deriveKey(p2s, alg, p2c, key) {
|
|
21
21
|
checkP2s(p2s);
|
|
22
22
|
const salt = concatSalt(alg, p2s);
|
|
23
|
-
const keylen = parseInt(alg.
|
|
23
|
+
const keylen = parseInt(alg.slice(13, 16), 10);
|
|
24
24
|
const subtleAlg = {
|
|
25
|
-
hash: `SHA-${alg.
|
|
25
|
+
hash: `SHA-${alg.slice(8, 11)}`,
|
|
26
26
|
iterations: p2c,
|
|
27
27
|
name: 'PBKDF2',
|
|
28
28
|
salt,
|
|
@@ -42,10 +42,10 @@ async function deriveKey(p2s, alg, p2c, key) {
|
|
|
42
42
|
}
|
|
43
43
|
export const encrypt = async (alg, key, cek, p2c = Math.floor(Math.random() * 2049) + 2048, p2s = random(new Uint8Array(16))) => {
|
|
44
44
|
const derived = await deriveKey(p2s, alg, p2c, key);
|
|
45
|
-
const encryptedKey = await wrap(alg.
|
|
45
|
+
const encryptedKey = await wrap(alg.slice(-6), derived, cek);
|
|
46
46
|
return { encryptedKey, p2c, p2s: base64url(p2s) };
|
|
47
47
|
};
|
|
48
48
|
export const decrypt = async (alg, key, encryptedKey, p2c, p2s) => {
|
|
49
49
|
const derived = await deriveKey(p2s, alg, p2c, key);
|
|
50
|
-
return unwrap(alg.
|
|
50
|
+
return unwrap(alg.slice(-6), derived, encryptedKey);
|
|
51
51
|
};
|
|
@@ -5,7 +5,7 @@ import getSignKey from './get_sign_verify_key.js';
|
|
|
5
5
|
const sign = async (alg, key, data) => {
|
|
6
6
|
const cryptoKey = await getSignKey(alg, key, 'sign');
|
|
7
7
|
checkKeyLength(alg, cryptoKey);
|
|
8
|
-
const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm
|
|
8
|
+
const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data);
|
|
9
9
|
return new Uint8Array(signature);
|
|
10
10
|
};
|
|
11
11
|
export default sign;
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { isCloudflareWorkers, isNodeJs } from './env.js';
|
|
2
2
|
import { JOSENotSupported } from '../util/errors.js';
|
|
3
|
-
export default function subtleDsa(alg,
|
|
4
|
-
const
|
|
3
|
+
export default function subtleDsa(alg, algorithm) {
|
|
4
|
+
const hash = `SHA-${alg.slice(-3)}`;
|
|
5
5
|
switch (alg) {
|
|
6
6
|
case 'HS256':
|
|
7
7
|
case 'HS384':
|
|
8
8
|
case 'HS512':
|
|
9
|
-
return { hash
|
|
9
|
+
return { hash, name: 'HMAC' };
|
|
10
10
|
case 'PS256':
|
|
11
11
|
case 'PS384':
|
|
12
12
|
case 'PS512':
|
|
13
|
-
return { hash
|
|
13
|
+
return { hash, name: 'RSA-PSS', saltLength: alg.slice(-3) >> 3 };
|
|
14
14
|
case 'RS256':
|
|
15
15
|
case 'RS384':
|
|
16
16
|
case 'RS512':
|
|
17
|
-
return { hash
|
|
17
|
+
return { hash, name: 'RSASSA-PKCS1-v1_5' };
|
|
18
18
|
case 'ES256':
|
|
19
19
|
case 'ES384':
|
|
20
20
|
case 'ES512':
|
|
21
|
-
return { hash
|
|
21
|
+
return { hash, name: 'ECDSA', namedCurve: algorithm.namedCurve };
|
|
22
22
|
case (isCloudflareWorkers() || isNodeJs()) && 'EdDSA':
|
|
23
|
+
const { namedCurve } = algorithm;
|
|
23
24
|
return { name: namedCurve, namedCurve };
|
|
24
25
|
default:
|
|
25
26
|
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
|
|
@@ -5,7 +5,7 @@ import getVerifyKey from './get_sign_verify_key.js';
|
|
|
5
5
|
const verify = async (alg, key, signature, data) => {
|
|
6
6
|
const cryptoKey = await getVerifyKey(alg, key, 'verify');
|
|
7
7
|
checkKeyLength(alg, cryptoKey);
|
|
8
|
-
const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm
|
|
8
|
+
const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm);
|
|
9
9
|
try {
|
|
10
10
|
return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
|
|
11
11
|
}
|
|
@@ -6,7 +6,7 @@ const import_js_1 = require("../key/import.js");
|
|
|
6
6
|
const errors_js_1 = require("../util/errors.js");
|
|
7
7
|
const is_object_js_1 = require("../lib/is_object.js");
|
|
8
8
|
function getKtyFromAlg(alg) {
|
|
9
|
-
switch (typeof alg === 'string' && alg.
|
|
9
|
+
switch (typeof alg === 'string' && alg.slice(0, 2)) {
|
|
10
10
|
case 'RS':
|
|
11
11
|
case 'PS':
|
|
12
12
|
return 'RSA';
|
|
@@ -6,14 +6,14 @@ const decrypt_js_1 = require("../runtime/decrypt.js");
|
|
|
6
6
|
const iv_js_1 = require("./iv.js");
|
|
7
7
|
const base64url_js_1 = require("../runtime/base64url.js");
|
|
8
8
|
async function wrap(alg, key, cek, iv) {
|
|
9
|
-
const jweAlgorithm = alg.
|
|
9
|
+
const jweAlgorithm = alg.slice(0, 7);
|
|
10
10
|
iv || (iv = (0, iv_js_1.default)(jweAlgorithm));
|
|
11
11
|
const { ciphertext: encryptedKey, tag } = await (0, encrypt_js_1.default)(jweAlgorithm, cek, key, iv, new Uint8Array(0));
|
|
12
12
|
return { encryptedKey, iv: (0, base64url_js_1.encode)(iv), tag: (0, base64url_js_1.encode)(tag) };
|
|
13
13
|
}
|
|
14
14
|
exports.wrap = wrap;
|
|
15
15
|
async function unwrap(alg, key, encryptedKey, iv, tag) {
|
|
16
|
-
const jweAlgorithm = alg.
|
|
16
|
+
const jweAlgorithm = alg.slice(0, 7);
|
|
17
17
|
return (0, decrypt_js_1.default)(jweAlgorithm, key, encryptedKey, iv, tag, new Uint8Array(0));
|
|
18
18
|
}
|
|
19
19
|
exports.unwrap = unwrap;
|
|
@@ -9,7 +9,7 @@ function isAlgorithm(algorithm, name) {
|
|
|
9
9
|
return algorithm.name === name;
|
|
10
10
|
}
|
|
11
11
|
function getHashLength(hash) {
|
|
12
|
-
return parseInt(hash.name.
|
|
12
|
+
return parseInt(hash.name.slice(4), 10);
|
|
13
13
|
}
|
|
14
14
|
function getNamedCurve(alg) {
|
|
15
15
|
switch (alg) {
|
|
@@ -46,7 +46,7 @@ function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
46
46
|
case 'HS512': {
|
|
47
47
|
if (!isAlgorithm(key.algorithm, 'HMAC'))
|
|
48
48
|
throw unusable('HMAC');
|
|
49
|
-
const expected = parseInt(alg.
|
|
49
|
+
const expected = parseInt(alg.slice(2), 10);
|
|
50
50
|
const actual = getHashLength(key.algorithm.hash);
|
|
51
51
|
if (actual !== expected)
|
|
52
52
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -57,7 +57,7 @@ function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
57
57
|
case 'RS512': {
|
|
58
58
|
if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))
|
|
59
59
|
throw unusable('RSASSA-PKCS1-v1_5');
|
|
60
|
-
const expected = parseInt(alg.
|
|
60
|
+
const expected = parseInt(alg.slice(2), 10);
|
|
61
61
|
const actual = getHashLength(key.algorithm.hash);
|
|
62
62
|
if (actual !== expected)
|
|
63
63
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -68,7 +68,7 @@ function checkSigCryptoKey(key, alg, ...usages) {
|
|
|
68
68
|
case 'PS512': {
|
|
69
69
|
if (!isAlgorithm(key.algorithm, 'RSA-PSS'))
|
|
70
70
|
throw unusable('RSA-PSS');
|
|
71
|
-
const expected = parseInt(alg.
|
|
71
|
+
const expected = parseInt(alg.slice(2), 10);
|
|
72
72
|
const actual = getHashLength(key.algorithm.hash);
|
|
73
73
|
if (actual !== expected)
|
|
74
74
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -108,7 +108,7 @@ function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
108
108
|
case 'A256GCM': {
|
|
109
109
|
if (!isAlgorithm(key.algorithm, 'AES-GCM'))
|
|
110
110
|
throw unusable('AES-GCM');
|
|
111
|
-
const expected = parseInt(alg.
|
|
111
|
+
const expected = parseInt(alg.slice(1, 4), 10);
|
|
112
112
|
const actual = key.algorithm.length;
|
|
113
113
|
if (actual !== expected)
|
|
114
114
|
throw unusable(expected, 'algorithm.length');
|
|
@@ -119,7 +119,7 @@ function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
119
119
|
case 'A256KW': {
|
|
120
120
|
if (!isAlgorithm(key.algorithm, 'AES-KW'))
|
|
121
121
|
throw unusable('AES-KW');
|
|
122
|
-
const expected = parseInt(alg.
|
|
122
|
+
const expected = parseInt(alg.slice(1, 4), 10);
|
|
123
123
|
const actual = key.algorithm.length;
|
|
124
124
|
if (actual !== expected)
|
|
125
125
|
throw unusable(expected, 'algorithm.length');
|
|
@@ -141,7 +141,7 @@ function checkEncCryptoKey(key, alg, ...usages) {
|
|
|
141
141
|
case 'RSA-OAEP-512': {
|
|
142
142
|
if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))
|
|
143
143
|
throw unusable('RSA-OAEP');
|
|
144
|
-
const expected = parseInt(alg.
|
|
144
|
+
const expected = parseInt(alg.slice(9), 10) || 1;
|
|
145
145
|
const actual = getHashLength(key.algorithm.hash);
|
|
146
146
|
if (actual !== expected)
|
|
147
147
|
throw unusable(`SHA-${expected}`, 'algorithm.hash');
|
|
@@ -42,12 +42,12 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader) {
|
|
|
42
42
|
throw new errors_js_1.JWEInvalid(`JOSE Header "apv" (Agreement PartyVInfo) invalid`);
|
|
43
43
|
partyVInfo = (0, base64url_js_1.decode)(joseHeader.apv);
|
|
44
44
|
}
|
|
45
|
-
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(joseHeader.enc) : parseInt(alg.
|
|
45
|
+
const sharedSecret = await ECDH.deriveKey(epk, key, alg === 'ECDH-ES' ? joseHeader.enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(joseHeader.enc) : parseInt(alg.slice(-5, -2), 10), partyUInfo, partyVInfo);
|
|
46
46
|
if (alg === 'ECDH-ES')
|
|
47
47
|
return sharedSecret;
|
|
48
48
|
if (encryptedKey === undefined)
|
|
49
49
|
throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
|
|
50
|
-
return (0, aeskw_js_1.unwrap)(alg.
|
|
50
|
+
return (0, aeskw_js_1.unwrap)(alg.slice(-6), sharedSecret, encryptedKey);
|
|
51
51
|
}
|
|
52
52
|
case 'RSA1_5':
|
|
53
53
|
case 'RSA-OAEP':
|
|
@@ -29,9 +29,9 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
29
29
|
}
|
|
30
30
|
const { apu, apv } = providedParameters;
|
|
31
31
|
let { epk: ephemeralKey } = providedParameters;
|
|
32
|
-
ephemeralKey || (ephemeralKey = await ECDH.generateEpk(key));
|
|
32
|
+
ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey);
|
|
33
33
|
const { x, y, crv, kty } = await (0, export_js_1.exportJWK)(ephemeralKey);
|
|
34
|
-
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(enc) : parseInt(alg.
|
|
34
|
+
const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? (0, cek_js_1.bitLength)(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv);
|
|
35
35
|
parameters = { epk: { x, y, crv, kty } };
|
|
36
36
|
if (apu)
|
|
37
37
|
parameters.apu = (0, base64url_js_1.encode)(apu);
|
|
@@ -42,7 +42,7 @@ async function encryptKeyManagement(alg, enc, key, providedCek, providedParamete
|
|
|
42
42
|
break;
|
|
43
43
|
}
|
|
44
44
|
cek = providedCek || (0, cek_js_1.default)(enc);
|
|
45
|
-
const kwAlg = alg.
|
|
45
|
+
const kwAlg = alg.slice(-6);
|
|
46
46
|
encryptedKey = await (0, aeskw_js_1.wrap)(kwAlg, sharedSecret, cek);
|
|
47
47
|
break;
|
|
48
48
|
}
|