UNPKG

@guarani/jose

Version:

Implementation of the RFCs of the JOSE Working Group.

102 lines (101 loc) 4.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.A256CBC_HS512 = exports.A192CBC_HS384 = exports.A128CBC_HS256 = void 0; const crypto_1 = require("crypto"); const invalid_json_web_encryption_exception_1 = require("../../../exceptions/invalid-json-web-encryption.exception"); const jsonwebencryption_contentencryption_algorithm_1 = require("./jsonwebencryption-contentencryption.algorithm"); /** * Implementation of the AES-CBC JSON Web Encryption Content Encryption Algorithm. */ class CBCHS2ContentEncryptionAlgorithm extends jsonwebencryption_contentencryption_algorithm_1.JsonWebEncryptionContentEncryptionAlgorithm { /** * Instantiates a new AES-CBC JSON Web Encryption Content Encryption to Encrypt and Decrypt a Plaintext. * * @param algorithm Name of the JSON Web Encryption Content Encryption Algorithm. */ constructor(algorithm) { const regex = /^A([0-9]{3})CBC-HS([0-9]{3})$/; const [keySize, hashSize] = regex .exec(algorithm) .slice(1) .map((value) => Number.parseInt(value)); super(keySize * 2, 128, algorithm); this.keySize = keySize; this.hashAlgorithm = `SHA${hashSize}`; this.cipherAlgorithm = `aes-${keySize}-cbc`; } /** * Encrypts the provided Plaintext. * * @param plaintext Plaintext to be Cncrypted. * @param aad Additional Authenticated Data. * @param iv Initialization Vector. * @param key Content Encryption Key used to Encrypt the provided Plaintext. * @returns Resulting Ciphertext and Authentication Tag. */ async encrypt(plaintext, aad, iv, key) { this.validateInitializationVector(iv); this.validateContentEncryptionKey(key); const macKey = key.subarray(0, this.keySize >> 3); const encKey = key.subarray(this.keySize >> 3); const cipher = (0, crypto_1.createCipheriv)(this.cipherAlgorithm, encKey, iv); const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]); const tag = this.getAuthTag(ciphertext, iv, aad, macKey); return { ciphertext, tag }; } /** * Decrypts the provided Ciphertext back to its original Plaintext. * * @param ciphertext Ciphertext to be Decrypted. * @param aad Additional Authenticated Data. * @param iv Initialization Vector. * @param tag Authentication Tag. * @param key Content Encryption Key used to Decrypt the provided Ciphertext. * @returns Resulting Plaintext. */ async decrypt(ciphertext, aad, iv, tag, key) { this.validateInitializationVector(iv); this.validateContentEncryptionKey(key); const macKey = key.subarray(0, this.keySize >> 3); const encKey = key.subarray(this.keySize >> 3); const expectedTag = this.getAuthTag(ciphertext, iv, aad, macKey); if (!(0, crypto_1.timingSafeEqual)(tag, expectedTag)) { throw new invalid_json_web_encryption_exception_1.InvalidJsonWebEncryptionException(); } const decipher = (0, crypto_1.createDecipheriv)(this.cipherAlgorithm, encKey, iv); const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]); return plaintext; } /** * Generates the Authentication Tag of the provided Ciphertext. * * @param ciphertext Ciphertext to be Decrypted. * @param iv Initialization Vector. * @param aad Additional Authenticated Data. * @param key Content Encryption Key. * @returns Authentication Tag. */ getAuthTag(ciphertext, iv, aad, key) { const len = aad.length << 3; const buf = Buffer.alloc(8); buf.writeUInt32BE(Math.floor(len / 2 ** 32), 0); buf.writeUInt32BE(len % 2 ** 32, 4); const data = Buffer.concat([aad, iv, ciphertext, buf]); return (0, crypto_1.createHmac)(this.hashAlgorithm, key) .update(data) .digest() .slice(0, this.keySize >> 3); } } /** * AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm. */ exports.A128CBC_HS256 = new CBCHS2ContentEncryptionAlgorithm('A128CBC-HS256'); /** * AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm. */ exports.A192CBC_HS384 = new CBCHS2ContentEncryptionAlgorithm('A192CBC-HS384'); /** * AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm. */ exports.A256CBC_HS512 = new CBCHS2ContentEncryptionAlgorithm('A256CBC-HS512');