UNPKG

@unvision/jose

Version:

Implementation of the RFCs of the JOSE Working Group.

134 lines 6.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsonWebEncryption = void 0; const invalid_jsonwebencryption_exception_1 = require("../exceptions/invalid-jsonwebencryption.exception"); const invalid_jsonwebkey_exception_1 = require("../exceptions/invalid-jsonwebkey.exception"); const jose_exception_1 = require("../exceptions/jose.exception"); const jsonwebkey_1 = require("../jwk/jsonwebkey"); const jsonwebencryption_header_1 = require("./jsonwebencryption.header"); /** * Implementation of a JSON Web Encryption. * * @see https://www.rfc-editor.org/rfc/rfc7516.html */ class JsonWebEncryption { /** * Instantiates a new JSON Web Encryption based on the provided JSON Web Encryption Header and Plaintext. * * @param header JSON Web Encryption Header. * @param plaintext Buffer to be used as the Plaintext. */ constructor(header, plaintext) { if (plaintext !== undefined && !Buffer.isBuffer(plaintext)) { throw new TypeError('Invalid JSON Web Encryption Plaintext.'); } this.header = new jsonwebencryption_header_1.JsonWebEncryptionHeader(header); this.plaintext = Buffer.isBuffer(plaintext) ? plaintext : Buffer.alloc(0); } /** * Decodes the provided JSON Web Encryption Token and returns its parsed Parameters. * * @example * * const [header, ek, iv, ciphertext, tag, aad] = JsonWebEncryption.decode('eyJhbGciOiJBMTI4...'); * * @param token JSON Web Encryption Token to be Decoded. * @returns Parsed Parameters of the JSON Web Encryption Token. */ static decode(token) { if (typeof token !== 'string') { throw new invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException(); } const splitToken = token.split('.'); if (splitToken.length !== 5) { throw new invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException(); } try { const [b64Header, b64Ek, b64Iv, b64Ciphertext, b64Tag] = splitToken; const headerParameters = JSON.parse(Buffer.from(b64Header, 'base64url').toString('utf8')); const header = new jsonwebencryption_header_1.JsonWebEncryptionHeader(headerParameters); const ek = Buffer.from(b64Ek, 'base64url'); const iv = Buffer.from(b64Iv, 'base64url'); const ciphertext = Buffer.from(b64Ciphertext, 'base64url'); const tag = Buffer.from(b64Tag, 'base64url'); const aad = Buffer.from(b64Header, 'ascii'); return [header, ek, iv, ciphertext, tag, aad]; } catch (exc) { if (exc instanceof invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException) { throw exc; } throw exc instanceof jose_exception_1.JoseException ? new invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException(exc) : new invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException(null, exc); } } /** * Deserializes a JSON Web Encryption Compact Token. * * @param token JSON Web Encryption Compact Token to be Deserialized. * @param keyOrKeyLoader JSON Web Key used to Deserialize the JSON Web Encryption Compact Token. * @returns JSON Web Encryption containing the Deserialized JSON Web Encryption Header and Plaintext. */ static async decrypt(token, keyOrKeyLoader) { if (!(keyOrKeyLoader instanceof jsonwebkey_1.JsonWebKey) && typeof keyOrKeyLoader !== 'function') { throw new invalid_jsonwebkey_exception_1.InvalidJsonWebKeyException(); } const [header, ek, iv, ciphertext, tag, aad] = this.decode(token); const key = typeof keyOrKeyLoader === 'function' ? await keyOrKeyLoader(header) : keyOrKeyLoader; try { const alg = header.keyWrapAlgorithm; const enc = header.contentEncryptionAlgorithm; const zip = header.compressionAlgorithm; const cek = await alg.unwrap(enc, key, ek, header); let plaintext = await enc.decrypt(ciphertext, aad, iv, tag, cek); if (zip !== null) { plaintext = await zip.decompress(plaintext); } return new JsonWebEncryption(header, plaintext); } catch (exc) { if (exc instanceof invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException) { throw exc; } throw exc instanceof jose_exception_1.JoseException ? new invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException(exc) : new invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException(null, exc); } } /** * Serializes the JSON Web Encryption into a Compact Token. * * @param key JSON Web Key used to Serialize the JSON Web Encryption. * @returns JSON Web Encryption Compact Token. */ async encrypt(key) { try { let { header, plaintext } = this; const alg = header.keyWrapAlgorithm; const enc = header.contentEncryptionAlgorithm; const zip = header.compressionAlgorithm; const iv = await enc.generateInitializationVector(); const [cek, ek, additionalHeaderParams] = await alg.wrap(enc, key); if (additionalHeaderParams !== undefined) { Object.assign(header, additionalHeaderParams); } const b64Header = Buffer.from(JSON.stringify(header), 'utf8').toString('base64url'); const aad = Buffer.from(b64Header, 'ascii'); if (zip !== null) { plaintext = await zip.compress(plaintext); } const [ciphertext, tag] = await enc.encrypt(plaintext, aad, iv, cek); const b64Ek = ek.toString('base64url'); const b64Iv = iv.toString('base64url'); const b64Ciphertext = ciphertext.toString('base64url'); const b64Tag = tag.toString('base64url'); return `${b64Header}.${b64Ek}.${b64Iv}.${b64Ciphertext}.${b64Tag}`; } catch (exc) { throw exc instanceof jose_exception_1.JoseException ? exc : new invalid_jsonwebencryption_exception_1.InvalidJsonWebEncryptionException(null, exc); } } } exports.JsonWebEncryption = JsonWebEncryption; //# sourceMappingURL=jsonwebencryption.js.map