@guarani/jose
Version:
Implementation of the RFCs of the JOSE Working Group.
96 lines (95 loc) • 4.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.A256GCMKW = exports.A192GCMKW = exports.A128GCMKW = void 0;
const crypto_1 = require("crypto");
const util_1 = require("util");
const invalid_json_web_key_exception_1 = require("../../../exceptions/invalid-json-web-key.exception");
const jsonwebencryption_keywrap_algorithm_1 = require("./jsonwebencryption-keywrap.algorithm");
const randomBytesAsync = (0, util_1.promisify)(crypto_1.randomBytes);
/**
* Implementation of the AES-GCM JSON Web Encryption Key Wrap Algorithm.
*/
class AESGCMKeyWrapAlgorithm extends jsonwebencryption_keywrap_algorithm_1.JsonWebEncryptionKeyWrapAlgorithm {
/**
* Instantiates a new JSON Web Encryption AES-GCM Key Wrap Algorithm to Wrap and Unwrap Content Encryption Keys.
*
* @param algorithm Name of the JSON Web Encryption Key Wrap Algorithm.
*/
constructor(algorithm) {
super(algorithm, 'oct');
/**
* Size of the Initialization Vector in bits.
*/
this.ivSize = 96;
/**
* Size of the Authentication Tag in bytes.
*/
this.authTagLength = 16;
this.keySize = Number.parseInt(this.algorithm.substring(1, 4));
this.cipherAlgorithm = `aes${this.keySize}-gcm`;
}
/**
* Wraps the provided Content Encryption Key using the provide JSON Web Key.
*
* @param enc JSON Web Encryption Content Encryption Algorithm.
* @param key JSON Web Key used to Wrap the provided Content Encryption Key.
* @returns Wrapped Content Encryption Key and optional additional JSON Web Encryption Header Parameters.
*/
async wrap(enc, key) {
this.validateJsonWebKey(key);
const iv = await randomBytesAsync(this.ivSize / 8);
const cryptoKey = Reflect.get(key, 'cryptoKey');
const cipher = (0, crypto_1.createCipheriv)(this.cipherAlgorithm, cryptoKey, iv, { authTagLength: this.authTagLength });
cipher.setAAD(Buffer.alloc(0));
const cek = await enc.generateContentEncryptionKey();
const ek = Buffer.concat([cipher.update(cek), cipher.final()]);
const tag = cipher.getAuthTag();
return { cek, ek, additionalHeaderParams: { iv: iv.toString('base64url'), tag: tag.toString('base64url') } };
}
/**
* Unwraps the provided Encrypted Key using the provided JSON Web Key.
*
* @param enc JSON Web Encryption Content Encryption Algorithm.
* @param key JSON Web Key used to Unwrap the Wrapped Content Encryption Key.
* @param ek Wrapped Content Encryption Key.
* @param header JSON Web Encryption Header containing the additional Parameters.
* @returns Unwrapped Content Encryption Key.
*/
async unwrap(enc, key, ek, header) {
this.validateJsonWebKey(key);
const iv = Buffer.from(header.iv, 'base64url');
const tag = Buffer.from(header.tag, 'base64url');
const cryptoKey = Reflect.get(key, 'cryptoKey');
const decipher = (0, crypto_1.createDecipheriv)(this.cipherAlgorithm, cryptoKey, iv, { authTagLength: this.authTagLength });
decipher.setAAD(Buffer.alloc(0));
decipher.setAuthTag(tag);
const cek = Buffer.concat([decipher.update(ek), decipher.final()]);
enc.validateContentEncryptionKey(cek);
return cek;
}
/**
* Checks if the provided JSON Web Key can be used by the requesting JSON Web Encryption AES-GCM Key Wrap Algorithm.
*
* @param key JSON Web Key to be checked.
* @throws {InvalidJsonWebKeyException} The provided JSON Web Key is invalid.
*/
validateJsonWebKey(key) {
super.validateJsonWebKey(key);
const exportedKey = key.export({ encoding: 'buffer' });
if (exportedKey.length * 8 !== this.keySize) {
throw new invalid_json_web_key_exception_1.InvalidJsonWebKeyException('Invalid JSON Web Key Secret Size.');
}
}
}
/**
* Key wrapping with AES GCM using 128-bit key.
*/
exports.A128GCMKW = new AESGCMKeyWrapAlgorithm('A128GCMKW');
/**
* Key wrapping with AES GCM using 192-bit key.
*/
exports.A192GCMKW = new AESGCMKeyWrapAlgorithm('A192GCMKW');
/**
* Key wrapping with AES GCM using 256-bit key.
*/
exports.A256GCMKW = new AESGCMKeyWrapAlgorithm('A256GCMKW');