tedious
Version:
A TDS driver, for connecting to MS SQLServer databases.
112 lines (88 loc) • 17.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.algorithmName = exports.AeadAes256CbcHmac256Algorithm = void 0;
var _types = require("./types");
var _crypto = require("crypto");
var _aeadAes256CbcHmacEncryptionKey = require("./aead-aes-256-cbc-hmac-encryption-key");
// This code is based on the `mssql-jdbc` library published under the conditions of MIT license.
// Copyright (c) 2019 Microsoft Corporation
const algorithmName = 'AEAD_AES_256_CBC_HMAC_SHA256';
exports.algorithmName = algorithmName;
const algorithmVersion = 0x1;
const blockSizeInBytes = 16;
class AeadAes256CbcHmac256Algorithm {
constructor(columnEncryptionKey, encryptionType) {
this.columnEncryptionkey = void 0;
this.isDeterministic = void 0;
this.keySizeInBytes = void 0;
this.version = void 0;
this.versionSize = void 0;
this.minimumCipherTextLengthInBytesNoAuthenticationTag = void 0;
this.minimumCipherTextLengthInBytesWithAuthenticationTag = void 0;
this.keySizeInBytes = _aeadAes256CbcHmacEncryptionKey.keySize / 8;
this.version = Buffer.from([algorithmVersion]);
this.versionSize = Buffer.from([1]);
this.minimumCipherTextLengthInBytesNoAuthenticationTag = 1 + blockSizeInBytes + blockSizeInBytes;
this.minimumCipherTextLengthInBytesWithAuthenticationTag = this.minimumCipherTextLengthInBytesNoAuthenticationTag + this.keySizeInBytes;
this.columnEncryptionkey = columnEncryptionKey;
this.isDeterministic = encryptionType === _types.SQLServerEncryptionType.Deterministic;
}
encryptData(plaintText) {
let iv;
if (this.isDeterministic === true) {
const hmacIv = (0, _crypto.createHmac)('sha256', this.columnEncryptionkey.getIvKey());
hmacIv.update(plaintText);
iv = hmacIv.digest().slice(0, blockSizeInBytes);
} else {
iv = (0, _crypto.randomBytes)(blockSizeInBytes);
}
const encryptCipher = (0, _crypto.createCipheriv)('aes-256-cbc', this.columnEncryptionkey.getEncryptionKey(), iv);
const encryptedBuffer = Buffer.concat([encryptCipher.update(plaintText), encryptCipher.final()]);
const authenticationTag = this._prepareAuthenticationTag(iv, encryptedBuffer, 0, encryptedBuffer.length);
return Buffer.concat([Buffer.from([algorithmVersion]), authenticationTag, iv, encryptedBuffer]);
}
decryptData(cipherText) {
const iv = Buffer.alloc(blockSizeInBytes);
const minimumCiperTextLength = this.minimumCipherTextLengthInBytesWithAuthenticationTag;
if (cipherText.length < minimumCiperTextLength) {
throw new Error(`Specified ciphertext has an invalid size of ${cipherText.length} bytes, which is below the minimum ${minimumCiperTextLength} bytes required for decryption.`);
}
let startIndex = 0;
if (cipherText[0] !== algorithmVersion) {
throw new Error(`The specified ciphertext's encryption algorithm version ${Buffer.from([cipherText[0]]).toString('hex')} does not match the expected encryption algorithm version ${algorithmVersion}.`);
}
startIndex += 1;
let authenticationTagOffset = 0;
authenticationTagOffset = startIndex;
startIndex += this.keySizeInBytes;
cipherText.copy(iv, 0, startIndex, startIndex + iv.length);
startIndex += iv.length;
const cipherTextOffset = startIndex;
const cipherTextCount = cipherText.length - startIndex;
const authenticationTag = this._prepareAuthenticationTag(iv, cipherText, cipherTextOffset, cipherTextCount);
if (0 !== authenticationTag.compare(cipherText, authenticationTagOffset, Math.min(authenticationTagOffset + cipherTextCount, authenticationTagOffset + authenticationTag.length), 0, Math.min(cipherTextCount, authenticationTag.length))) {
throw new Error('Specified ciphertext has an invalid authentication tag.');
}
let plainText;
const decipher = (0, _crypto.createDecipheriv)('aes-256-cbc', this.columnEncryptionkey.getEncryptionKey(), iv);
try {
plainText = decipher.update(cipherText.slice(cipherTextOffset, cipherTextOffset + cipherTextCount));
plainText = Buffer.concat([plainText, decipher.final()]);
} catch (error) {
throw new Error(`Internal error while decryption: ${error.message}`);
}
return plainText;
}
_prepareAuthenticationTag(iv, cipherText, offset, length) {
const hmac = (0, _crypto.createHmac)('sha256', this.columnEncryptionkey.getMacKey());
hmac.update(this.version);
hmac.update(iv);
hmac.update(cipherText.slice(offset, offset + length));
hmac.update(this.versionSize);
return hmac.digest();
}
}
exports.AeadAes256CbcHmac256Algorithm = AeadAes256CbcHmac256Algorithm;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhbGdvcml0aG1OYW1lIiwiYWxnb3JpdGhtVmVyc2lvbiIsImJsb2NrU2l6ZUluQnl0ZXMiLCJBZWFkQWVzMjU2Q2JjSG1hYzI1NkFsZ29yaXRobSIsImNvbnN0cnVjdG9yIiwiY29sdW1uRW5jcnlwdGlvbktleSIsImVuY3J5cHRpb25UeXBlIiwiY29sdW1uRW5jcnlwdGlvbmtleSIsImlzRGV0ZXJtaW5pc3RpYyIsImtleVNpemVJbkJ5dGVzIiwidmVyc2lvbiIsInZlcnNpb25TaXplIiwibWluaW11bUNpcGhlclRleHRMZW5ndGhJbkJ5dGVzTm9BdXRoZW50aWNhdGlvblRhZyIsIm1pbmltdW1DaXBoZXJUZXh0TGVuZ3RoSW5CeXRlc1dpdGhBdXRoZW50aWNhdGlvblRhZyIsImtleVNpemUiLCJCdWZmZXIiLCJmcm9tIiwiU1FMU2VydmVyRW5jcnlwdGlvblR5cGUiLCJEZXRlcm1pbmlzdGljIiwiZW5jcnlwdERhdGEiLCJwbGFpbnRUZXh0IiwiaXYiLCJobWFjSXYiLCJnZXRJdktleSIsInVwZGF0ZSIsImRpZ2VzdCIsInNsaWNlIiwiZW5jcnlwdENpcGhlciIsImdldEVuY3J5cHRpb25LZXkiLCJlbmNyeXB0ZWRCdWZmZXIiLCJjb25jYXQiLCJmaW5hbCIsImF1dGhlbnRpY2F0aW9uVGFnIiwiX3ByZXBhcmVBdXRoZW50aWNhdGlvblRhZyIsImxlbmd0aCIsImRlY3J5cHREYXRhIiwiY2lwaGVyVGV4dCIsImFsbG9jIiwibWluaW11bUNpcGVyVGV4dExlbmd0aCIsIkVycm9yIiwic3RhcnRJbmRleCIsInRvU3RyaW5nIiwiYXV0aGVudGljYXRpb25UYWdPZmZzZXQiLCJjb3B5IiwiY2lwaGVyVGV4dE9mZnNldCIsImNpcGhlclRleHRDb3VudCIsImNvbXBhcmUiLCJNYXRoIiwibWluIiwicGxhaW5UZXh0IiwiZGVjaXBoZXIiLCJlcnJvciIsIm1lc3NhZ2UiLCJvZmZzZXQiLCJobWFjIiwiZ2V0TWFjS2V5Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Fsd2F5cy1lbmNyeXB0ZWQvYWVhZC1hZXMtMjU2LWNiYy1obWFjLWFsZ29yaXRobS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGlzIGNvZGUgaXMgYmFzZWQgb24gdGhlIGBtc3NxbC1qZGJjYCBsaWJyYXJ5IHB1Ymxpc2hlZCB1bmRlciB0aGUgY29uZGl0aW9ucyBvZiBNSVQgbGljZW5zZS5cbi8vIENvcHlyaWdodCAoYykgMjAxOSBNaWNyb3NvZnQgQ29ycG9yYXRpb25cblxuaW1wb3J0IHsgRW5jcnlwdGlvbkFsZ29yaXRobSwgU1FMU2VydmVyRW5jcnlwdGlvblR5cGUgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGNyZWF0ZUhtYWMsIHJhbmRvbUJ5dGVzLCBjcmVhdGVDaXBoZXJpdiwgY3JlYXRlRGVjaXBoZXJpdiB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBBZWFkQWVzMjU2Q2JjSG1hYzI1NkVuY3J5cHRpb25LZXksIGtleVNpemUgfSBmcm9tICcuL2FlYWQtYWVzLTI1Ni1jYmMtaG1hYy1lbmNyeXB0aW9uLWtleSc7XG5cbmV4cG9ydCBjb25zdCBhbGdvcml0aG1OYW1lID0gJ0FFQURfQUVTXzI1Nl9DQkNfSE1BQ19TSEEyNTYnO1xuY29uc3QgYWxnb3JpdGhtVmVyc2lvbiA9IDB4MTtcbmNvbnN0IGJsb2NrU2l6ZUluQnl0ZXMgPSAxNjtcblxuZXhwb3J0IGNsYXNzIEFlYWRBZXMyNTZDYmNIbWFjMjU2QWxnb3JpdGhtIGltcGxlbWVudHMgRW5jcnlwdGlvbkFsZ29yaXRobSB7XG4gIHByaXZhdGUgY29sdW1uRW5jcnlwdGlvbmtleTogQWVhZEFlczI1NkNiY0htYWMyNTZFbmNyeXB0aW9uS2V5O1xuICBwcml2YXRlIGlzRGV0ZXJtaW5pc3RpYzogYm9vbGVhbjtcbiAgcHJpdmF0ZSBrZXlTaXplSW5CeXRlczogbnVtYmVyO1xuICBwcml2YXRlIHZlcnNpb246IEJ1ZmZlcjtcbiAgcHJpdmF0ZSB2ZXJzaW9uU2l6ZTogQnVmZmVyO1xuICBwcml2YXRlIG1pbmltdW1DaXBoZXJUZXh0TGVuZ3RoSW5CeXRlc05vQXV0aGVudGljYXRpb25UYWc6IG51bWJlcjtcbiAgcHJpdmF0ZSBtaW5pbXVtQ2lwaGVyVGV4dExlbmd0aEluQnl0ZXNXaXRoQXV0aGVudGljYXRpb25UYWc6IG51bWJlcjtcblxuICBjb25zdHJ1Y3Rvcihjb2x1bW5FbmNyeXB0aW9uS2V5OiBBZWFkQWVzMjU2Q2JjSG1hYzI1NkVuY3J5cHRpb25LZXksIGVuY3J5cHRpb25UeXBlOiBTUUxTZXJ2ZXJFbmNyeXB0aW9uVHlwZSkge1xuICAgIHRoaXMua2V5U2l6ZUluQnl0ZXMgPSBrZXlTaXplIC8gODtcbiAgICB0aGlzLnZlcnNpb24gPSBCdWZmZXIuZnJvbShbYWxnb3JpdGhtVmVyc2lvbl0pO1xuICAgIHRoaXMudmVyc2lvblNpemUgPSBCdWZmZXIuZnJvbShbMV0pO1xuICAgIHRoaXMubWluaW11bUNpcGhlclRleHRMZW5ndGhJbkJ5dGVzTm9BdXRoZW50aWNhdGlvblRhZyA9IDEgKyBibG9ja1NpemVJbkJ5dGVzICsgYmxvY2tTaXplSW5CeXRlcztcbiAgICB0aGlzLm1pbmltdW1DaXBoZXJUZXh0TGVuZ3RoSW5CeXRlc1dpdGhBdXRoZW50aWNhdGlvblRhZyA9IHRoaXMubWluaW11bUNpcGhlclRleHRMZW5ndGhJbkJ5dGVzTm9BdXRoZW50aWNhdGlvblRhZyArIHRoaXMua2V5U2l6ZUluQnl0ZXM7XG4gICAgdGhpcy5jb2x1bW5FbmNyeXB0aW9ua2V5ID0gY29sdW1uRW5jcnlwdGlvbktleTtcblxuICAgIHRoaXMuaXNEZXRlcm1pbmlzdGljID0gZW5jcnlwdGlvblR5cGUgPT09IFNRTFNlcnZlckVuY3J5cHRpb25UeXBlLkRldGVybWluaXN0aWM7XG4gIH1cblxuICBlbmNyeXB0RGF0YShwbGFpbnRUZXh0OiBCdWZmZXIpOiBCdWZmZXIge1xuICAgIGxldCBpdjogQnVmZmVyO1xuXG4gICAgaWYgKHRoaXMuaXNEZXRlcm1pbmlzdGljID09PSB0cnVlKSB7XG4gICAgICBjb25zdCBobWFjSXYgPSBjcmVhdGVIbWFjKCdzaGEyNTYnLCB0aGlzLmNvbHVtbkVuY3J5cHRpb25rZXkuZ2V0SXZLZXkoKSk7XG4gICAgICBobWFjSXYudXBkYXRlKHBsYWludFRleHQpO1xuICAgICAgaXYgPSBobWFjSXYuZGlnZXN0KCkuc2xpY2UoMCwgYmxvY2tTaXplSW5CeXRlcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGl2ID0gcmFuZG9tQnl0ZXMoYmxvY2tTaXplSW5CeXRlcyk7XG4gICAgfVxuXG4gICAgY29uc3QgZW5jcnlwdENpcGhlciA9IGNyZWF0ZUNpcGhlcml2KCdhZXMtMjU2LWNiYycsIHRoaXMuY29sdW1uRW5jcnlwdGlvbmtleS5nZXRFbmNyeXB0aW9uS2V5KCksIGl2KTtcblxuICAgIGNvbnN0IGVuY3J5cHRlZEJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW2VuY3J5cHRDaXBoZXIudXBkYXRlKHBsYWludFRleHQpLCBlbmNyeXB0Q2lwaGVyLmZpbmFsKCldKTtcblxuICAgIGNvbnN0IGF1dGhlbnRpY2F0aW9uVGFnOiBCdWZmZXIgPSB0aGlzLl9wcmVwYXJlQXV0aGVudGljYXRpb25UYWcoaXYsIGVuY3J5cHRlZEJ1ZmZlciwgMCwgZW5jcnlwdGVkQnVmZmVyLmxlbmd0aCk7XG5cbiAgICByZXR1cm4gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oW2FsZ29yaXRobVZlcnNpb25dKSwgYXV0aGVudGljYXRpb25UYWcsIGl2LCBlbmNyeXB0ZWRCdWZmZXJdKTtcbiAgfVxuXG4gIGRlY3J5cHREYXRhKGNpcGhlclRleHQ6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgY29uc3QgaXY6IEJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhibG9ja1NpemVJbkJ5dGVzKTtcblxuICAgIGNvbnN0IG1pbmltdW1DaXBlclRleHRMZW5ndGg6IG51bWJlciA9IHRoaXMubWluaW11bUNpcGhlclRleHRMZW5ndGhJbkJ5dGVzV2l0aEF1dGhlbnRpY2F0aW9uVGFnO1xuXG4gICAgaWYgKGNpcGhlclRleHQubGVuZ3RoIDwgbWluaW11bUNpcGVyVGV4dExlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTcGVjaWZpZWQgY2lwaGVydGV4dCBoYXMgYW4gaW52YWxpZCBzaXplIG9mICR7Y2lwaGVyVGV4dC5sZW5ndGh9IGJ5dGVzLCB3aGljaCBpcyBiZWxvdyB0aGUgbWluaW11bSAke21pbmltdW1DaXBlclRleHRMZW5ndGh9IGJ5dGVzIHJlcXVpcmVkIGZvciBkZWNyeXB0aW9uLmApO1xuICAgIH1cblxuICAgIGxldCBzdGFydEluZGV4ID0gMDtcbiAgICBpZiAoY2lwaGVyVGV4dFswXSAhPT0gYWxnb3JpdGhtVmVyc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgc3BlY2lmaWVkIGNpcGhlcnRleHQncyBlbmNyeXB0aW9uIGFsZ29yaXRobSB2ZXJzaW9uICR7QnVmZmVyLmZyb20oW2NpcGhlclRleHRbMF1dKS50b1N0cmluZygnaGV4Jyl9IGRvZXMgbm90IG1hdGNoIHRoZSBleHBlY3RlZCBlbmNyeXB0aW9uIGFsZ29yaXRobSB2ZXJzaW9uICR7YWxnb3JpdGhtVmVyc2lvbn0uYCk7XG4gICAgfVxuXG4gICAgc3RhcnRJbmRleCArPSAxO1xuICAgIGxldCBhdXRoZW50aWNhdGlvblRhZ09mZnNldCA9IDA7XG5cbiAgICBhdXRoZW50aWNhdGlvblRhZ09mZnNldCA9IHN0YXJ0SW5kZXg7XG4gICAgc3RhcnRJbmRleCArPSB0aGlzLmtleVNpemVJbkJ5dGVzO1xuXG4gICAgY2lwaGVyVGV4dC5jb3B5KGl2LCAwLCBzdGFydEluZGV4LCBzdGFydEluZGV4ICsgaXYubGVuZ3RoKTtcbiAgICBzdGFydEluZGV4ICs9IGl2Lmxlbmd0aDtcblxuICAgIGNvbnN0IGNpcGhlclRleHRPZmZzZXQgPSBzdGFydEluZGV4O1xuICAgIGNvbnN0IGNpcGhlclRleHRDb3VudCA9IGNpcGhlclRleHQubGVuZ3RoIC0gc3RhcnRJbmRleDtcblxuICAgIGNvbnN0IGF1dGhlbnRpY2F0aW9uVGFnOiBCdWZmZXIgPSB0aGlzLl9wcmVwYXJlQXV0aGVudGljYXRpb25UYWcoaXYsIGNpcGhlclRleHQsIGNpcGhlclRleHRPZmZzZXQsIGNpcGhlclRleHRDb3VudCk7XG5cbiAgICBpZiAoMCAhPT0gYXV0aGVudGljYXRpb25UYWcuY29tcGFyZShjaXBoZXJUZXh0LCBhdXRoZW50aWNhdGlvblRhZ09mZnNldCwgTWF0aC5taW4oYXV0aGVudGljYXRpb25UYWdPZmZzZXQgKyBjaXBoZXJUZXh0Q291bnQsIGF1dGhlbnRpY2F0aW9uVGFnT2Zmc2V0ICsgYXV0aGVudGljYXRpb25UYWcubGVuZ3RoKSwgMCwgTWF0aC5taW4oY2lwaGVyVGV4dENvdW50LCBhdXRoZW50aWNhdGlvblRhZy5sZW5ndGgpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTcGVjaWZpZWQgY2lwaGVydGV4dCBoYXMgYW4gaW52YWxpZCBhdXRoZW50aWNhdGlvbiB0YWcuJyk7XG4gICAgfVxuXG4gICAgbGV0IHBsYWluVGV4dDogQnVmZmVyO1xuXG4gICAgY29uc3QgZGVjaXBoZXIgPSBjcmVhdGVEZWNpcGhlcml2KCdhZXMtMjU2LWNiYycsIHRoaXMuY29sdW1uRW5jcnlwdGlvbmtleS5nZXRFbmNyeXB0aW9uS2V5KCksIGl2KTtcbiAgICB0cnkge1xuICAgICAgcGxhaW5UZXh0ID0gZGVjaXBoZXIudXBkYXRlKGNpcGhlclRleHQuc2xpY2UoY2lwaGVyVGV4dE9mZnNldCwgY2lwaGVyVGV4dE9mZnNldCArIGNpcGhlclRleHRDb3VudCkpO1xuICAgICAgcGxhaW5UZXh0ID0gQnVmZmVyLmNvbmNhdChbcGxhaW5UZXh0LCBkZWNpcGhlci5maW5hbCgpXSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnRlcm5hbCBlcnJvciB3aGlsZSBkZWNyeXB0aW9uOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBsYWluVGV4dDtcbiAgfVxuXG4gIF9wcmVwYXJlQXV0aGVudGljYXRpb25UYWcoaXY6IEJ1ZmZlciwgY2lwaGVyVGV4dDogQnVmZmVyLCBvZmZzZXQ6IG51bWJlciwgbGVuZ3RoOiBudW1iZXIpOiBCdWZmZXIge1xuICAgIGNvbnN0IGhtYWMgPSBjcmVhdGVIbWFjKCdzaGEyNTYnLCB0aGlzLmNvbHVtbkVuY3J5cHRpb25rZXkuZ2V0TWFjS2V5KCkpO1xuXG4gICAgaG1hYy51cGRhdGUodGhpcy52ZXJzaW9uKTtcbiAgICBobWFjLnVwZGF0ZShpdik7XG4gICAgaG1hYy51cGRhdGUoY2lwaGVyVGV4dC5zbGljZShvZmZzZXQsIG9mZnNldCArIGxlbmd0aCkpO1xuICAgIGhtYWMudXBkYXRlKHRoaXMudmVyc2lvblNpemUpO1xuICAgIHJldHVybiBobWFjLmRpZ2VzdCgpO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFHQTs7QUFDQTs7QUFDQTs7QUFMQTtBQUNBO0FBTU8sTUFBTUEsYUFBYSxHQUFHLDhCQUF0Qjs7QUFDUCxNQUFNQyxnQkFBZ0IsR0FBRyxHQUF6QjtBQUNBLE1BQU1DLGdCQUFnQixHQUFHLEVBQXpCOztBQUVPLE1BQU1DLDZCQUFOLENBQW1FO0VBU3hFQyxXQUFXLENBQUNDLG1CQUFELEVBQXlEQyxjQUF6RCxFQUFrRztJQUFBLEtBUnJHQyxtQkFRcUc7SUFBQSxLQVByR0MsZUFPcUc7SUFBQSxLQU5yR0MsY0FNcUc7SUFBQSxLQUxyR0MsT0FLcUc7SUFBQSxLQUpyR0MsV0FJcUc7SUFBQSxLQUhyR0MsaURBR3FHO0lBQUEsS0FGckdDLG1EQUVxRztJQUMzRyxLQUFLSixjQUFMLEdBQXNCSywwQ0FBVSxDQUFoQztJQUNBLEtBQUtKLE9BQUwsR0FBZUssTUFBTSxDQUFDQyxJQUFQLENBQVksQ0FBQ2YsZ0JBQUQsQ0FBWixDQUFmO0lBQ0EsS0FBS1UsV0FBTCxHQUFtQkksTUFBTSxDQUFDQyxJQUFQLENBQVksQ0FBQyxDQUFELENBQVosQ0FBbkI7SUFDQSxLQUFLSixpREFBTCxHQUF5RCxJQUFJVixnQkFBSixHQUF1QkEsZ0JBQWhGO0lBQ0EsS0FBS1csbURB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