UNPKG

@syncfusion/ej2-pdf

Version:

Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.

338 lines (337 loc) 17.5 kB
/** * Triple DES implementation used internally for PDF encryption. * * @private */ var _TripleDataEncryptionStandardCipher = /** @class */ (function () { /** * Create a Triple DES cipher instance with the given key. * * @private * @param {Uint8Array} key - The 16- or 24-byte Triple DES key. * @param {boolean} isEncryption - Whether the cipher will be used for encryption. */ function _TripleDataEncryptionStandardCipher(key, isEncryption) { if (isEncryption === void 0) { isEncryption = true; } /** * Block size in bytes (DES block size). * * @private */ this._blockSize = 8; this._isEncryption = true; /** * S-box 1 table. * * @private */ this._sp1 = [0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004]; /** * S-box 2 table. * * @private */ this._sp2 = [0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000]; /** * S-box 3 table. * * @private */ this._sp3 = [0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200]; /** * S-box 4 table. * * @private */ this._sp4 = [0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080]; /** * S-box 5 table. * * @private */ this._sp5 = [0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100]; /** * S-box 6 table. * * @private */ this._sp6 = [0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010]; /** * S-box 7 table. * * @private */ this._sp7 = [0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002]; /** * S-box 8 table. * * @private */ this._sp8 = [0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000]; if (!(key instanceof Uint8Array) || (key.length !== 16 && key.length !== 24)) { throw new Error('Triple DES key must be 16 or 24 bytes.'); } this._isEncryption = isEncryption; var key1 = key.subarray(0, 8); var key2 = key.subarray(8, 16); var key3 = (key.length === 24) ? key.subarray(16, 24) : key1; this._key1 = this._generateWorkingKey(isEncryption, key1); this._key2 = this._generateWorkingKey(!isEncryption, key2); this._key3 = this._generateWorkingKey(isEncryption, key3); } /** * Read a big-endian unsigned 32-bit integer from a byte array. * * @private * @param {Uint8Array} b - Source byte array. * @param {number} off - Byte offset to read from. * @returns {number} The 32-bit unsigned integer value. */ _TripleDataEncryptionStandardCipher.prototype._beToUint32 = function (b, off) { return ((b[off] << 24) | (b[off + 1] << 16) | (b[off + 2] << 8) | b[off + 3]) >>> 0; }; /** * Write a 32-bit unsigned integer to a byte array in big-endian order. * * @private * @param {number} v - Value to write. * @param {Uint8Array} b - Destination byte array. * @param {number} off - Byte offset to write to. * @returns {void} */ _TripleDataEncryptionStandardCipher.prototype._uint32ToBe = function (v, b, off) { b[off] = (v >>> 24) & 0xff; b[off + 1] = (v >>> 16) & 0xff; b[off + 2] = (v >>> 8) & 0xff; b[off + 3] = v & 0xff; }; /** * Generate the DES round keys (working key) from the provided key bytes. * * @private * @param {boolean} isEncrypt - Whether the keys are for encryption (true) or decryption (false). * @param {Uint8Array} keyBytes - The 8-byte key material. * @returns {Int32Array} An `Int32Array` representing round subkeys. */ _TripleDataEncryptionStandardCipher.prototype._generateWorkingKey = function (isEncrypt, keyBytes) { var ByteBit = [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01]; var BigByte = [ 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 ]; var Pc1 = [56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3]; var Totrot = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; var Pc2 = [13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31]; var newKeys = new Int32Array(32); var bytes1 = new Array(56).fill(false); //eslint-disable-line var bytes2 = new Array(56).fill(false); //eslint-disable-line for (var j = 0; j < 56; j++) { var length_1 = Pc1[j]; bytes1[j] = ((keyBytes[length_1 >> 3] & ByteBit[length_1 & 7]) !== 0); } for (var i = 0; i < 16; i++) { var b = isEncrypt ? i << 1 : (15 - i) << 1; var c = b + 1; newKeys[b] = newKeys[c] = 0; for (var j = 0; j < 28; j++) { var a = j + Totrot[i]; bytes2[j] = (a < 28) ? bytes1[a] : bytes1[a - 28]; } for (var j = 28; j < 56; j++) { var a = j + Totrot[i]; bytes2[j] = (a < 56) ? bytes1[a] : bytes1[a - 28]; } for (var j = 0; j < 24; j++) { if (bytes2[Pc2[j]]) { newKeys[b] |= BigByte[j]; } if (bytes2[Pc2[j + 24]]) { newKeys[c] |= BigByte[j]; } } } for (var i = 0; i !== 32; i += 2) { var value1 = newKeys[i]; var value2 = newKeys[i + 1]; newKeys[i] = ((value1 & 0x00fc0000) << 6) | ((value1 & 0x00000fc0) << 10) | ((value2 & 0x00fc0000) >>> 10) | ((value2 & 0x00000fc0) >>> 6); newKeys[i + 1] = ((value1 & 0x0003f000) << 12) | ((value1 & 0x0000003f) << 16) | ((value2 & 0x0003f000) >>> 4) | (value2 & 0x0000003f); } return newKeys; }; /** * Process a single DES round using the supplied subkeys. * * @private * @param {Int32Array} keys - Round subkeys to use. * @param {Uint8Array} inBytes - Input byte array. * @param {number} inOffset - Offset into input array. * @param {Uint8Array} outBytes - Output byte array. * @param {number} outOffset - Offset into output array. * @returns {void} */ _TripleDataEncryptionStandardCipher.prototype._processEncryptionBlock = function (keys, inBytes, inOffset, outBytes, outOffset) { var left = this._beToUint32(inBytes, inOffset) >>> 0; var right = this._beToUint32(inBytes, inOffset + 4) >>> 0; var data = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= data; left ^= (data << 4); data = ((left >>> 16) ^ right) & 0x0000ffff; right ^= data; left ^= (data << 16); data = ((right >>> 2) ^ left) & 0x33333333; left ^= data; right ^= (data << 2); data = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= data; right ^= (data << 8); right = ((right << 1) | (right >>> 31)) >>> 0; data = (left ^ right) & 0xaaaaaaaa; left ^= data; right ^= data; left = ((left << 1) | (left >>> 31)) >>> 0; for (var round = 0; round < 8; round++) { data = ((right << 28) | (right >>> 4)) >>> 0; data = data ^ keys[round * 4 + 0]; var value = this._sp7[data & 0x3f] | this._sp5[(data >>> 8) & 0x3f] | this._sp3[(data >>> 16) & 0x3f] | this._sp1[(data >>> 24) & 0x3f]; data = (right ^ keys[round * 4 + 1]) >>> 0; value |= this._sp8[data & 0x3f] | this._sp6[(data >>> 8) & 0x3f] | this._sp4[(data >>> 16) & 0x3f] | this._sp2[(data >>> 24) & 0x3f]; left ^= value; data = ((left << 28) | (left >>> 4)) >>> 0; data = data ^ keys[round * 4 + 2]; value = this._sp7[data & 0x3f] | this._sp5[(data >>> 8) & 0x3f] | this._sp3[(data >>> 16) & 0x3f] | this._sp1[(data >>> 24) & 0x3f]; data = (left ^ keys[round * 4 + 3]) >>> 0; value |= this._sp8[data & 0x3f] | this._sp6[(data >>> 8) & 0x3f] | this._sp4[(data >>> 16) & 0x3f] | this._sp2[(data >>> 24) & 0x3f]; right ^= value; } right = ((right << 31) | (right >>> 1)) >>> 0; data = (left ^ right) & 0xaaaaaaaa; left ^= data; right ^= data; left = ((left << 31) | (left >>> 1)) >>> 0; data = ((left >>> 8) ^ right) & 0x00ff00ff; right ^= data; left ^= (data << 8); data = ((left >>> 2) ^ right) & 0x33333333; right ^= data; left ^= (data << 2); data = ((right >>> 16) ^ left) & 0x0000ffff; left ^= data; right ^= (data << 16); data = ((right >>> 4) ^ left) & 0x0f0f0f0f; left ^= data; right ^= (data << 4); this._uint32ToBe(right, outBytes, outOffset); this._uint32ToBe(left, outBytes, outOffset + 4); }; /** * Process a Triple DES block. * * @private * @param {Uint8Array} input - Input bytes containing the block. * @param {number} inOffset - Offset into `input` where the block starts. * @param {Uint8Array} output - Destination byte array. * @param {number} outOffset - Offset into `output` to write the block. * @returns {number} The block size in bytes. */ _TripleDataEncryptionStandardCipher.prototype._processBlock = function (input, inOffset, output, outOffset) { var blockSize = this._blockSize; var tempBytes = new Uint8Array(blockSize); if (this._isEncryption) { this._processEncryptionBlock(this._key1, input, inOffset, tempBytes, 0); this._processEncryptionBlock(this._key2, tempBytes, 0, tempBytes, 0); this._processEncryptionBlock(this._key3, tempBytes, 0, output, outOffset); } else { this._processEncryptionBlock(this._key3, input, inOffset, tempBytes, 0); this._processEncryptionBlock(this._key2, tempBytes, 0, tempBytes, 0); this._processEncryptionBlock(this._key1, tempBytes, 0, output, outOffset); } return blockSize; }; return _TripleDataEncryptionStandardCipher; }()); export { _TripleDataEncryptionStandardCipher };