jose-browser-runtime
Advanced tools
Comparing version 4.0.2 to 4.0.3
import bogusWebCrypto from './bogus.js'; | ||
import crypto, { isCryptoKey } from './webcrypto.js'; | ||
import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js'; | ||
import invalidKeyInput from './invalid_key_input.js'; | ||
@@ -9,4 +9,5 @@ function checkKeySize(key, alg) { | ||
} | ||
function getCryptoKey(key, usage) { | ||
function getCryptoKey(key, alg, usage) { | ||
if (isCryptoKey(key)) { | ||
checkCryptoKey(key, alg, usage); | ||
return key; | ||
@@ -20,3 +21,3 @@ } | ||
export const wrap = async (alg, key, cek) => { | ||
const cryptoKey = await getCryptoKey(key, 'wrapKey'); | ||
const cryptoKey = await getCryptoKey(key, alg, 'wrapKey'); | ||
checkKeySize(cryptoKey, alg); | ||
@@ -27,3 +28,3 @@ const cryptoKeyCek = await crypto.subtle.importKey('raw', cek, ...bogusWebCrypto); | ||
export const unwrap = async (alg, key, encryptedKey) => { | ||
const cryptoKey = await getCryptoKey(key, 'unwrapKey'); | ||
const cryptoKey = await getCryptoKey(key, alg, 'unwrapKey'); | ||
checkKeySize(cryptoKey, alg); | ||
@@ -30,0 +31,0 @@ const cryptoKeyCek = await crypto.subtle.unwrapKey('raw', encryptedKey, cryptoKey, 'AES-KW', ...bogusWebCrypto); |
import { concat, uint64be } from '../lib/buffer_utils.js'; | ||
import checkIvLength from '../lib/check_iv_length.js'; | ||
import checkCekLength from './check_cek_length.js'; | ||
import timingSafeEqual from './timing_safe_equal.js'; | ||
import { JOSENotSupported, JWEDecryptionFailed } from '../util/errors.js'; | ||
import crypto, { isCryptoKey } from './webcrypto.js'; | ||
import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js'; | ||
import invalidKeyInput from './invalid_key_input.js'; | ||
async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { | ||
if (!(cek instanceof Uint8Array)) { | ||
throw new TypeError(invalidKeyInput(cek, 'Uint8Array')); | ||
} | ||
const keySize = parseInt(enc.substr(1, 3), 10); | ||
@@ -37,6 +39,11 @@ const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['decrypt']); | ||
} | ||
async function gcmDecrypt(cek, ciphertext, iv, tag, aad) { | ||
const encKey = cek instanceof Uint8Array | ||
? await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']) | ||
: cek; | ||
async function gcmDecrypt(enc, cek, ciphertext, iv, tag, aad) { | ||
let encKey; | ||
if (cek instanceof Uint8Array) { | ||
encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['decrypt']); | ||
} | ||
else { | ||
checkCryptoKey(cek, enc, 'decrypt'); | ||
encKey = cek; | ||
} | ||
try { | ||
@@ -58,3 +65,2 @@ return new Uint8Array(await crypto.subtle.decrypt({ | ||
} | ||
checkCekLength(enc, cek); | ||
checkIvLength(enc, iv); | ||
@@ -69,3 +75,3 @@ switch (enc) { | ||
case 'A256GCM': | ||
return gcmDecrypt(cek, ciphertext, iv, tag, aad); | ||
return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); | ||
default: | ||
@@ -72,0 +78,0 @@ throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); |
import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../lib/buffer_utils.js'; | ||
import crypto, { isCryptoKey } from './webcrypto.js'; | ||
import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js'; | ||
import digest from './digest.js'; | ||
@@ -9,5 +9,7 @@ import invalidKeyInput from './invalid_key_input.js'; | ||
} | ||
checkCryptoKey(publicKey, 'ECDH-ES'); | ||
if (!isCryptoKey(privateKey)) { | ||
throw new TypeError(invalidKeyInput(privateKey, 'CryptoKey')); | ||
} | ||
checkCryptoKey(privateKey, 'ECDH-ES', 'deriveBits', 'deriveKey'); | ||
const value = concat(lengthAndInput(encoder.encode(algorithm)), lengthAndInput(apu), lengthAndInput(apv), uint32be(keyLength)); | ||
@@ -14,0 +16,0 @@ if (!privateKey.usages.includes('deriveBits')) { |
import { concat, uint64be } from '../lib/buffer_utils.js'; | ||
import checkIvLength from '../lib/check_iv_length.js'; | ||
import checkCekLength from './check_cek_length.js'; | ||
import crypto, { isCryptoKey } from './webcrypto.js'; | ||
import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js'; | ||
import invalidKeyInput from './invalid_key_input.js'; | ||
import { JOSENotSupported } from '../util/errors.js'; | ||
async function cbcEncrypt(enc, plaintext, cek, iv, aad) { | ||
if (!(cek instanceof Uint8Array)) { | ||
throw new TypeError(invalidKeyInput(cek, 'Uint8Array')); | ||
} | ||
const keySize = parseInt(enc.substr(1, 3), 10); | ||
@@ -22,6 +24,11 @@ const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['encrypt']); | ||
} | ||
async function gcmEncrypt(plaintext, cek, iv, aad) { | ||
const encKey = cek instanceof Uint8Array | ||
? await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']) | ||
: cek; | ||
async function gcmEncrypt(enc, plaintext, cek, iv, aad) { | ||
let encKey; | ||
if (cek instanceof Uint8Array) { | ||
encKey = await crypto.subtle.importKey('raw', cek, 'AES-GCM', false, ['encrypt']); | ||
} | ||
else { | ||
checkCryptoKey(cek, enc, 'encrypt'); | ||
encKey = cek; | ||
} | ||
const encrypted = new Uint8Array(await crypto.subtle.encrypt({ | ||
@@ -41,3 +48,2 @@ additionalData: aad, | ||
} | ||
checkCekLength(enc, cek); | ||
checkIvLength(enc, iv); | ||
@@ -52,3 +58,3 @@ switch (enc) { | ||
case 'A256GCM': | ||
return gcmEncrypt(plaintext, cek, iv, aad); | ||
return gcmEncrypt(enc, plaintext, cek, iv, aad); | ||
default: | ||
@@ -55,0 +61,0 @@ throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); |
@@ -1,5 +0,6 @@ | ||
import crypto, { isCryptoKey } from './webcrypto.js'; | ||
import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js'; | ||
import invalidKeyInput from './invalid_key_input.js'; | ||
export default function getCryptoKey(alg, key, usage) { | ||
if (isCryptoKey(key)) { | ||
checkCryptoKey(key, alg, usage); | ||
return key; | ||
@@ -6,0 +7,0 @@ } |
@@ -6,5 +6,5 @@ import random from './random.js'; | ||
import checkP2s from '../lib/check_p2s.js'; | ||
import crypto, { isCryptoKey } from './webcrypto.js'; | ||
import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js'; | ||
import invalidKeyInput from './invalid_key_input.js'; | ||
function getCryptoKey(key) { | ||
function getCryptoKey(key, alg) { | ||
if (key instanceof Uint8Array) { | ||
@@ -14,2 +14,3 @@ return crypto.subtle.importKey('raw', key, 'PBKDF2', false, ['deriveBits']); | ||
if (isCryptoKey(key)) { | ||
checkCryptoKey(key, alg, 'deriveBits', 'deriveKey'); | ||
return key; | ||
@@ -33,3 +34,3 @@ } | ||
}; | ||
const cryptoKey = await getCryptoKey(key); | ||
const cryptoKey = await getCryptoKey(key, alg); | ||
let derived; | ||
@@ -62,3 +63,3 @@ if (cryptoKey.usages.includes('deriveBits')) { | ||
}; | ||
const cryptoKey = await getCryptoKey(key); | ||
const cryptoKey = await getCryptoKey(key, alg); | ||
let derived; | ||
@@ -65,0 +66,0 @@ if (cryptoKey.usages.includes('deriveBits')) { |
import subtleAlgorithm from './subtle_rsaes.js'; | ||
import bogusWebCrypto from './bogus.js'; | ||
import crypto, { isCryptoKey } from './webcrypto.js'; | ||
import crypto, { checkCryptoKey, isCryptoKey } from './webcrypto.js'; | ||
import checkKeyLength from './check_key_length.js'; | ||
@@ -10,2 +10,3 @@ import invalidKeyInput from './invalid_key_input.js'; | ||
} | ||
checkCryptoKey(key, alg, 'encrypt', 'wrapKey'); | ||
checkKeyLength(alg, key); | ||
@@ -25,2 +26,3 @@ if (key.usages.includes('encrypt')) { | ||
} | ||
checkCryptoKey(key, alg, 'decrypt', 'unwrapKey'); | ||
checkKeyLength(alg, key); | ||
@@ -27,0 +29,0 @@ if (key.usages.includes('decrypt')) { |
@@ -9,1 +9,146 @@ import globalThis from './global.js'; | ||
} | ||
function getHashLength(hash) { | ||
return parseInt(hash === null || hash === void 0 ? void 0 : hash.name.substr(4), 10); | ||
} | ||
function getNamedCurve(alg) { | ||
switch (alg) { | ||
case 'ES256': | ||
return 'P-256'; | ||
case 'ES384': | ||
return 'P-384'; | ||
case 'ES512': | ||
return 'P-521'; | ||
} | ||
} | ||
export function checkCryptoKey(key, alg, ...usages) { | ||
switch (alg) { | ||
case undefined: | ||
break; | ||
case 'HS256': | ||
case 'HS384': | ||
case 'HS512': { | ||
if (key.algorithm.name !== 'HMAC') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be HMAC.`); | ||
} | ||
const expected = parseInt(alg.substr(2), 10); | ||
const actual = getHashLength(key.algorithm.hash); | ||
if (actual !== expected) { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.hash must be SHA-${expected}.`); | ||
} | ||
break; | ||
} | ||
case 'RS256': | ||
case 'RS384': | ||
case 'RS512': { | ||
if (key.algorithm.name !== 'RSASSA-PKCS1-v1_5') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be RSASSA-PKCS1-v1_5.`); | ||
} | ||
const expected = parseInt(alg.substr(2), 10); | ||
const actual = getHashLength(key.algorithm.hash); | ||
if (actual !== expected) { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.hash must be SHA-${expected}.`); | ||
} | ||
break; | ||
} | ||
case 'PS256': | ||
case 'PS384': | ||
case 'PS512': { | ||
if (key.algorithm.name !== 'RSA-PSS') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be RSA-PSS.`); | ||
} | ||
const expected = parseInt(alg.substr(2), 10); | ||
const actual = getHashLength(key.algorithm.hash); | ||
if (actual !== expected) { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.hash must be SHA-${expected}.`); | ||
} | ||
break; | ||
} | ||
case 'EdDSA': { | ||
if (key.algorithm.name !== 'NODE-ED25519' && key.algorithm.name !== 'NODE-ED448') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be NODE-ED25519 or NODE-ED448.`); | ||
} | ||
break; | ||
} | ||
case 'ES256': | ||
case 'ES384': | ||
case 'ES512': { | ||
if (key.algorithm.name !== 'ECDSA') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be ECDSA.`); | ||
} | ||
const expected = getNamedCurve(alg); | ||
const actual = key.algorithm.namedCurve; | ||
if (actual !== expected) { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.namedCurve must be ${expected}.`); | ||
} | ||
break; | ||
} | ||
case 'A128GCM': | ||
case 'A192GCM': | ||
case 'A256GCM': { | ||
if (key.algorithm.name !== 'AES-GCM') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be AES-GCM.`); | ||
} | ||
const expected = parseInt(alg.substr(1, 3), 10); | ||
const actual = key.algorithm.length; | ||
if (actual !== expected) { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.length must be ${expected}.`); | ||
} | ||
break; | ||
} | ||
case 'A128KW': | ||
case 'A192KW': | ||
case 'A256KW': { | ||
if (key.algorithm.name !== 'AES-KW') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be AES-KW.`); | ||
} | ||
const expected = parseInt(alg.substr(1, 3), 10); | ||
const actual = key.algorithm.length; | ||
if (actual !== expected) { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.length must be ${expected}.`); | ||
} | ||
break; | ||
} | ||
case 'ECDH-ES': | ||
if (key.algorithm.name !== 'ECDH') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be ECDH.`); | ||
} | ||
break; | ||
case 'PBES2-HS256+A128KW': | ||
case 'PBES2-HS384+A192KW': | ||
case 'PBES2-HS512+A256KW': | ||
if (key.algorithm.name !== 'PBKDF2') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be PBKDF2.`); | ||
} | ||
break; | ||
case 'RSA-OAEP': | ||
case 'RSA-OAEP-256': | ||
case 'RSA-OAEP-384': | ||
case 'RSA-OAEP-512': { | ||
if (key.algorithm.name !== 'RSA-OAEP') { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.name must be RSA-OAEP.`); | ||
} | ||
const expected = parseInt(alg.substr(9), 10) || 1; | ||
const actual = getHashLength(key.algorithm.hash); | ||
if (actual !== expected) { | ||
throw new TypeError(`CryptoKey does not support this operation, its algorithm.hash must be SHA-${expected}.`); | ||
} | ||
break; | ||
} | ||
default: | ||
throw new TypeError('CryptoKey does not support this operation'); | ||
} | ||
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); | ||
} | ||
} |
{ | ||
"name": "jose-browser-runtime", | ||
"version": "4.0.2", | ||
"version": "4.0.3", | ||
"description": "(Browser Runtime) 'JSON Web Almost Everything' - JWA, JWS, JWE, JWT, JWK, JWKS with no dependencies using runtime's native crypto", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
153539
3783
104