@syncfusion/ej2-pdf
Version:
Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.
199 lines (198 loc) • 7.81 kB
JavaScript
import { _bytesToBigInt, _bigIntToBytes, _modPow, _createRandomInRange, _modInverse, _getBigInt } from '../../../utils';
/**
* Provides the internal RSA core operations, including modular exponentiation,
* CRT optimization for private keys, and block size management.
*
* @private
*/
var _PdfRsaCoreAlgorithm = /** @class */ (function () {
function _PdfRsaCoreAlgorithm() {
}
/**
* Gets the maximum input block size in bytes based on the key size and operation mode.
*
* @private
* @returns {number} The allowed input block size in bytes.
*/
_PdfRsaCoreAlgorithm.prototype._getInputBlockSize = function () {
return this._isEncryption ? (this._bitSize - 1) >>> 3 : (this._bitSize + 7) >>> 3;
};
/**
* Gets the maximum output block size in bytes based on the key size and operation mode.
*
* @private
* @returns {number} The output block size in bytes.
*/
_PdfRsaCoreAlgorithm.prototype._getOutputBlockSize = function () {
return this._isEncryption ? (this._bitSize + 7) >>> 3 : (this._bitSize - 1) >>> 3;
};
/**
* Initializes the RSA core engine with the specified mode and key parameters.
*
* @private
* @param {boolean} isEncryption Specifies whether to operate in encryption mode.
* @param {_PdfCipherParameter} parameters The RSA key parameters to use.
* @returns {void} nothing.
*/
_PdfRsaCoreAlgorithm.prototype._initialize = function (isEncryption, parameters) {
this._key = parameters;
this._isEncryption = isEncryption;
this._bitSize = this._key.modulus._bitLength();
};
/**
* Converts a segment of bytes into a bigint suitable for RSA modular operations,
* validating the block size and modulus constraints.
*
* @private
* @param {Uint8Array} bytes The source byte array.
* @param {number} offset The starting index within the array.
* @param {number} length The number of bytes to read.
* @returns {bigint} The bigint representation of the input block.
*/
_PdfRsaCoreAlgorithm.prototype._convertInput = function (bytes, offset, length) {
var subBytes = bytes.subarray(offset, offset + length);
if (subBytes.length > this._getInputBlockSize() + 1) {
throw new Error('Input data too large for RSA block.');
}
var input = _bytesToBigInt(subBytes);
if (input >= this._key.modulus) {
throw new Error('Input data is larger than modulus.');
}
return input;
};
/**
* Converts a bigint result back into a byte array, padding as required for encryption output size.
*
* @private
* @param {bigint} result The bigint value to convert.
* @returns {Uint8Array} The converted byte array.
*/
_PdfRsaCoreAlgorithm.prototype._convertOutput = function (result) {
var output = _bigIntToBytes(result);
if (this._isEncryption) {
var outSize = this._getOutputBlockSize();
if (output.length < outSize) {
var paddedOutput = new Uint8Array(outSize);
paddedOutput.set(output, outSize - output.length);
return paddedOutput;
}
}
return output;
};
/**
* Processes a single RSA block using modular exponentiation. If a CRT private key is present,
* uses the CRT optimization; otherwise, falls back to standard exponentiation.
*
* @private
* @param {bigint} input The bigint block to process.
* @returns {bigint} The processed bigint result.
*/
_PdfRsaCoreAlgorithm.prototype._processBlock = function (input) {
var bigInt = _getBigInt();
var privateKey = this._key; // eslint-disable-line
if (privateKey._isPrivate && privateKey.p && privateKey.q) {
var p = privateKey.p._toBigInt();
var q = privateKey.q._toBigInt();
var dP = privateKey.dP._toBigInt();
var dQ = privateKey.dQ._toBigInt();
var qInv = privateKey.inverse._toBigInt();
var mP = _modPow(input % p, dP, p);
var mQ = _modPow(input % q, dQ, q);
var h = (mP - mQ) * qInv;
h = h % p;
if (h < bigInt('0')) {
h += p;
}
var m = h * q;
m = m + mQ;
return m;
}
return _modPow(input, this._key.exponent, this._key.modulus);
};
return _PdfRsaCoreAlgorithm;
}());
export { _PdfRsaCoreAlgorithm };
/**
* Provides the internal RSA block cipher wrapper built on top of the RSA core,
* exposing block size and processing methods for encryption/decryption.
*
* @private
*/
var _PdfRsaAlgorithm = /** @class */ (function () {
function _PdfRsaAlgorithm() {
this._rsaCoreEngine = new _PdfRsaCoreAlgorithm();
}
/**
* Gets the internal algorithm name.
*
* @private
* @returns {string} The algorithm name, i.e., "RSA".
*/
_PdfRsaAlgorithm.prototype._getAlgorithmName = function () {
return 'RSA';
};
/**
* Gets the maximum input block size in bytes for the current key and mode.
*
* @private
* @returns {number} The input block size in bytes.
*/
_PdfRsaAlgorithm.prototype._getInputBlock = function () {
return this._rsaCoreEngine._getInputBlockSize();
};
/**
* Gets the maximum output block size in bytes for the current key and mode.
*
* @private
* @returns {number} The output block size in bytes.
*/
_PdfRsaAlgorithm.prototype._getOutputBlock = function () {
return this._rsaCoreEngine._getOutputBlockSize();
};
/**
* Initializes the RSA algorithm with the specified mode and parameters.
*
* @private
* @param {boolean} isEncryption Specifies whether to operate in encryption mode.
* @param {_PdfCipherParameter} parameter The RSA key parameters to use.
* @returns {void} nothing.
*/
_PdfRsaAlgorithm.prototype._initialize = function (isEncryption, parameter) {
this._rsaCoreEngine._initialize(isEncryption, parameter);
this._key = parameter;
};
/**
* Processes a single block of input using RSA. Applies blinding when a private key is used
* and a public exponent is available to mitigate timing attacks.
*
* @private
* @param {Uint8Array} bytes The input buffer containing the block data.
* @param {number} offset The starting index of the block within the buffer.
* @param {number} length The number of bytes to process from the buffer.
* @returns {Uint8Array} The processed output block.
*/
_PdfRsaAlgorithm.prototype._processBlock = function (bytes, offset, length) {
var bigInt = _getBigInt();
if (!this._key) {
throw new Error('RSA engine not initialized.');
}
var input = this._rsaCoreEngine._convertInput(bytes, offset, length);
var result;
var privateKey = this._key; // eslint-disable-line
if (privateKey._isPrivate && privateKey.publicExponent) {
var e = privateKey.publicExponent._toBigInt();
var m = this._key.modulus._toBigInt();
var r = _createRandomInRange(bigInt(1), m - bigInt(1));
var blindedInput = (_modPow(r, e, m) * input) % m;
var blindedResult = this._rsaCoreEngine._processBlock(blindedInput);
var rInverse = _modInverse(r, m);
result = (blindedResult * rInverse) % m;
}
else {
result = this._rsaCoreEngine._processBlock(input);
}
return this._rsaCoreEngine._convertOutput(result);
};
return _PdfRsaAlgorithm;
}());
export { _PdfRsaAlgorithm };