@unvision/jose
Version:
Implementation of the RFCs of the JOSE Working Group.
134 lines • 6.54 kB
JavaScript
;
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