Buckets:
| 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, JWEInvalid } from '../util/errors.js'; | |
| import crypto, { isCryptoKey } from './webcrypto.js'; | |
| import { checkEncCryptoKey } from '../lib/crypto_key.js'; | |
| import invalidKeyInput from '../lib/invalid_key_input.js'; | |
| import { types } from './is_key_like.js'; | |
| async function cbcDecrypt(enc, cek, ciphertext, iv, tag, aad) { | |
| if (!(cek instanceof Uint8Array)) { | |
| throw new TypeError(invalidKeyInput(cek, 'Uint8Array')); | |
| } | |
| const keySize = parseInt(enc.slice(1, 4), 10); | |
| const encKey = await crypto.subtle.importKey('raw', cek.subarray(keySize >> 3), 'AES-CBC', false, ['decrypt']); | |
| const macKey = await crypto.subtle.importKey('raw', cek.subarray(0, keySize >> 3), { | |
| hash: `SHA-${keySize << 1}`, | |
| name: 'HMAC', | |
| }, false, ['sign']); | |
| const macData = concat(aad, iv, ciphertext, uint64be(aad.length << 3)); | |
| const expectedTag = new Uint8Array((await crypto.subtle.sign('HMAC', macKey, macData)).slice(0, keySize >> 3)); | |
| let macCheckPassed; | |
| try { | |
| macCheckPassed = timingSafeEqual(tag, expectedTag); | |
| } | |
| catch { | |
| } | |
| if (!macCheckPassed) { | |
| throw new JWEDecryptionFailed(); | |
| } | |
| let plaintext; | |
| try { | |
| plaintext = new Uint8Array(await crypto.subtle.decrypt({ iv, name: 'AES-CBC' }, encKey, ciphertext)); | |
| } | |
| catch { | |
| } | |
| if (!plaintext) { | |
| throw new JWEDecryptionFailed(); | |
| } | |
| return plaintext; | |
| } | |
| 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 { | |
| checkEncCryptoKey(cek, enc, 'decrypt'); | |
| encKey = cek; | |
| } | |
| try { | |
| return new Uint8Array(await crypto.subtle.decrypt({ | |
| additionalData: aad, | |
| iv, | |
| name: 'AES-GCM', | |
| tagLength: 128, | |
| }, encKey, concat(ciphertext, tag))); | |
| } | |
| catch { | |
| throw new JWEDecryptionFailed(); | |
| } | |
| } | |
| const decrypt = async (enc, cek, ciphertext, iv, tag, aad) => { | |
| if (!isCryptoKey(cek) && !(cek instanceof Uint8Array)) { | |
| throw new TypeError(invalidKeyInput(cek, ...types, 'Uint8Array')); | |
| } | |
| if (!iv) { | |
| throw new JWEInvalid('JWE Initialization Vector missing'); | |
| } | |
| if (!tag) { | |
| throw new JWEInvalid('JWE Authentication Tag missing'); | |
| } | |
| checkIvLength(enc, iv); | |
| switch (enc) { | |
| case 'A128CBC-HS256': | |
| case 'A192CBC-HS384': | |
| case 'A256CBC-HS512': | |
| if (cek instanceof Uint8Array) | |
| checkCekLength(cek, parseInt(enc.slice(-3), 10)); | |
| return cbcDecrypt(enc, cek, ciphertext, iv, tag, aad); | |
| case 'A128GCM': | |
| case 'A192GCM': | |
| case 'A256GCM': | |
| if (cek instanceof Uint8Array) | |
| checkCekLength(cek, parseInt(enc.slice(1, 4), 10)); | |
| return gcmDecrypt(enc, cek, ciphertext, iv, tag, aad); | |
| default: | |
| throw new JOSENotSupported('Unsupported JWE Content Encryption Algorithm'); | |
| } | |
| }; | |
| export default decrypt; | |
Xet Storage Details
- Size:
- 3.35 kB
- Xet hash:
- 37a76875c16267a25702383add5a9f1b302a3d5b490180422bc9576f398a1d2c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.