UNPKG

@syncfusion/ej2-pdf

Version:

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

803 lines (802 loc) 39.2 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; import { CryptographicStandard, DigestAlgorithm } from '../../../enumerator'; import { PdfDocument } from '../../../pdf-document'; import { _PdfDictionary, _PdfName, _PdfReference } from '../../../pdf-primitives'; import { _PdfCertificate } from '../pdf-certificate'; import { _PdfX509CertificateParser } from '../x509/x509-certificate-parser'; import { _PdfSignaturePrivateKey } from './signature-privatekey'; import { _PdfCryptographicMessageSyntaxSigner } from './cryptographic-signer'; import { _bytesToHex, _padStart } from '../../../utils'; /** * Helper class that builds and manages the PDF signature dictionary. * * @private */ var _PdfSignatureDictionary = /** @class */ (function () { function _PdfSignatureDictionary(arg1, arg2) { /** * @private */ this._dictionary = new _PdfDictionary(); this._transParam = 'TransformParams'; this._signaturePermissionsDictionary = 'DocMDP'; this._cryptographicFilterType = 'adbe.pkcs7.detached'; this._advanceFilterType = 'ETSI.CAdES.detached'; this._requestForCommentsFilterType = 'ETSI.RFC3161'; /** * Estimated buffer size used for padding signatures. */ this._estimatedSize = 8192; if (!arg1) { throw new Error('A valid argument must be provided.'); } if (!arg2) { throw new Error('Argument signature is null or undefined.'); } if (arg1 instanceof PdfDocument) { this._document = arg1; this._crossReference = arg1._crossReference; } else { this._dictionary = arg1; } this._signature = arg2; this._certificate = arg2._certificate; } /** * Parse a PDF 'Contents' value into raw bytes. * * @private * @param {any} contents - The raw contents value from the PDF dictionary. * @returns {Uint8Array} The decoded byte array or undefined. */ _PdfSignatureDictionary.prototype._parsePdfContents = function (contents) { var result; if (contents instanceof Uint8Array) { return contents; } else if (typeof contents === 'string') { var trimmed = contents.trim(); var isHexFormat = trimmed.startsWith('<') && trimmed.endsWith('>'); if (isHexFormat) { var hex = trimmed.slice(1, -1).replace(/[^0-9a-fA-F]/g, ''); if (hex.length % 2 !== 0) { hex += '0'; } result = new Uint8Array(hex.length / 2); for (var i = 0; i < hex.length; i += 2) { result[i / 2] = parseInt(hex.slice(i, i + 2), 16); } return result; } result = new Uint8Array(trimmed.length); for (var i = 0; i < trimmed.length; i++) { result[i] = trimmed.charCodeAt(i) & 0xff; } return result; } return result; }; /** * Determine the digest algorithm used by the embedded CMS signer. * * @private * @returns {DigestAlgorithm} The detected digest algorithm. */ _PdfSignatureDictionary.prototype._parseDigestAlgorithm = function () { var digest; if (this._dictionary.has('Contents')) { var contents = this._dictionary.get('Contents'); var bytes = this._parsePdfContents(contents); var isDeferredSigning = bytes && bytes.length > 0 && bytes.every(function (byte) { return byte === 0; }); if (bytes && bytes.length > 0 && !isDeferredSigning) { var parser = new _PdfX509CertificateParser(); var certificateChain = parser._readCertificate(bytes, true); var certificate = new _PdfCertificate(certificateChain); this._certificate = certificate; this._cmsSigner = new _PdfCryptographicMessageSyntaxSigner(bytes, this._dictionary.get('SubFilter').name); if (this._cmsSigner && this._cmsSigner._hasTimeStamp && this._cmsSigner._timeStampTokenBytes && this._cmsSigner._timeStampTokenBytes.length > 0) { this._signature._hasTimeStamp = this._cmsSigner._hasTimeStamp; this._signature._timeStampTokenBytes = this._cmsSigner._timeStampTokenBytes; this._signature._isTimestampOnly = this._cmsSigner._isTimestampOnly; } } } if (this._cmsSigner) { var messageDigest = this._cmsSigner._getHashAlgorithm(); switch (messageDigest) { case 'SHA512': digest = DigestAlgorithm.sha512; break; case 'SHA384': digest = DigestAlgorithm.sha384; break; case 'SHA1': digest = DigestAlgorithm.sha1; break; case 'RIPEMD160': digest = DigestAlgorithm.ripemd160; break; default: digest = DigestAlgorithm.sha256; break; } } return digest; }; /** * Read a direct string value from the signature dictionary by key. * * @private * @param {string} key - The dictionary key to read. * @returns {string} The stored string value, or undefined. */ _PdfSignatureDictionary.prototype._parseDirect = function (key) { var value; if (this._dictionary.has(key)) { value = this._dictionary.get(key); } return value; }; /** * Parse the signing date ('M' entry) from the signature dictionary. * * @private * @returns {Date} The parsed signing date, or undefined. */ _PdfSignatureDictionary.prototype._parseSignedDate = function () { var signedDate; if (this._dictionary.has('M')) { var dateEntry = this._dictionary.get('M'); signedDate = this._parsePdfDate(dateEntry); } return signedDate; }; /** * Convert a PDF date string (e.g. "D:YYYYMMDDHHmmSSOHH'mm'") into a Date object. * * @private * @param {string} v - The PDF date string to parse. * @returns {Date} The parsed Date or undefined if parsing failed. */ _PdfSignatureDictionary.prototype._parsePdfDate = function (v) { if (typeof v !== 'string' || v.length === 0) { return undefined; } var s = v.trim(); if (s.startsWith('D:')) { s = s.slice(2); } var year = Number(s.slice(0, 4)); var month = Number(s.slice(4, 6) || '01'); var day = Number(s.slice(6, 8) || '01'); var hour = Number(s.slice(8, 10) || '00'); var minute = Number(s.slice(10, 12) || '00'); var second = Number(s.slice(12, 14) || '00'); var offsetMinutes = 0; var tzStart = 14; if (s.length > tzStart) { var tzRaw = s.slice(tzStart).replace(/'/g, ''); if (tzRaw.toUpperCase() !== 'Z') { var sign = tzRaw.startsWith('-') ? -1 : 1; var hh = Number(tzRaw.slice(1, 3)); var mm = tzRaw.length >= 5 ? Number(tzRaw.slice(3, 5)) : 0; offsetMinutes = sign * (hh * 60 + mm); } } var millisLocal = Date.UTC(year, month - 1, day, hour, minute, second); var time = millisLocal - offsetMinutes * 60000; var dt = new Date(time); return isNaN(dt.getTime()) ? undefined : dt; }; /** * Save the internal dictionary and signature-related entries into the buffer. * * @private * @param {number[]} buffer - The output byte buffer to write into. * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._dictionarySave = function (buffer) { if (!this._dictionary || buffer.length <= 0) { throw new Error('dictionary or writer is null.'); } if (this._signature) { this._addRequiredItems(); this._addOptionalItems(); } this._addContents(buffer); this._addRange(buffer); if (this._signature && this._signature._certify) { this._addDigest(buffer); } }; /** * Add digest-related reference entries when the signature is a certifying signature. * * @private * @param {number[]} buffer - The output buffer to append to. * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addDigest = function (buffer) { if (this._signature && this._signature._certify && this._allowMessageDigestProcessing()) { var writer = this._document._crossReference; writer._writeString("/Reference[<</TransformParams<<\r\n/V /1.2\r\n/P " + this._signature._documentPermissions + "\r\n /Type /TransformParams\r\n>>\r\n/TransformMethod/DocMDP/Type/SigRef/DigestValue", buffer); var offset = buffer.length + writer._currentLength; writer._writeString('<', buffer); for (var i = 0; i < 32; i++) { writer._writeString('0', buffer); } var reference = this._document._catalog._catalogDictionary.objId.toString(); writer._writeString('>/DigestLocation[' + offset + ' 34]/DigestMethod/MD5/Data ' + reference + ' R>><</TransformParams<<\r\n/V /1.2\r\n/Fields [(Signature)]\r\n/Type /TransformParams\r\n/Action /Include\r\n>>\r\n/TransformMethod/FieldMDP/Type/SigRef/DigestValue', buffer); // eslint-disable-line offset = buffer.length + writer._currentLength; writer._writeString('<', buffer); for (var i = 0; i < 32; i++) { writer._writeString('0', buffer); } writer._writeString('>/DigestLocation[' + offset + ' 34]/DigestMethod/MD5/Data ' + reference + ' R>>]\r\n', buffer); } }; /** * Add required signature dictionary entries (Type, Filter, SubFilter, Date, etc.). * * @private * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addRequiredItems = function () { if (this._signature && this._signature._certify && this._allowMessageDigestProcessing()) { this._addReference(); } this._addType(); this._addDate(); this._addFilter(); this._addSubFilter(); }; /** * Determine whether message-digest processing is allowed for this signature. * * @private * @returns {boolean} True when message-digest processing is permitted. */ _PdfSignatureDictionary.prototype._allowMessageDigestProcessing = function () { var dictionary = this._document._catalog._catalogDictionary.get('Perms'); if (typeof dictionary !== 'undefined' && dictionary !== null) { var docMDP = dictionary.get('DocMDP'); // eslint-disable-line if (docMDP instanceof _PdfReference) { var docMDPDictionary = this._document._crossReference._fetch(docMDP); var signatureDictionary = this._dictionary; if (signatureDictionary.has('Reference') || docMDPDictionary.has('Reference')) { return false; } } else if (docMDP instanceof _PdfDictionary) { if (docMDP.objId !== this._dictionary.objId) { return false; } } } return true; }; /** * Add optional entries such as Reason, Location, ContactInfo and Name/Prop_Build. * * @private * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addOptionalItems = function () { if (this._signature) { if (this._signature._reason) { this._dictionary.update('Reason', this._signature._reason); } if (this._signature._locationInfo) { this._dictionary.update('Location', this._signature._locationInfo); } if (this._signature._contactInfo) { this._dictionary.update('ContactInfo', this._signature._contactInfo); } if (this._signature._signedName) { this._dictionary.update('Name', this._signature._signedName); var tempDictionary = new _PdfDictionary(); var appDictionary = new _PdfDictionary(); tempDictionary.update('Name', this._signature._signedName); var ref = this._document._crossReference._getNextReference(); this._document._crossReference._cacheMap.set(ref, tempDictionary); appDictionary.update('App', ref); ref = this._document._crossReference._getNextReference(); this._document._crossReference._cacheMap.set(ref, appDictionary); this._dictionary.update('Prop_Build', ref); } } }; /** * Build the /Reference structure used for DocMDP-style permissions. * * @private * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addReference = function () { var trans = new _PdfDictionary(); var reference = new _PdfDictionary(); var array = []; // eslint-disable-line trans.update('V', _PdfName.get('1.2')); trans.update('P', this._signature._documentPermissions); trans.update('Type', _PdfName.get(this._transParam)); reference.update('TransformMethod', _PdfName.get(this._signaturePermissionsDictionary)); reference.update('Type', _PdfName.get('SigRef')); reference.update(this._transParam, trans); reference.update(this._transParam, trans); array.push(reference); this._dictionary.update('Reference', array); }; /** * Add the Type entry to the dictionary, choosing DocTimeStamp for timestamps. * * @private * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addType = function () { if (this._signature && this._signature._isTimestampOnly && this._signature._externalChain.length === 0) { this._dictionary.update('Type', new _PdfName('DocTimeStamp')); } else { this._dictionary.update('Type', new _PdfName('Sig')); } }; /** * Format and add the signing date ('M' entry) to the signature dictionary. * * @private * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addDate = function () { var dateTime = new Date(); if (this._signature && this._signature._signedDate) { dateTime = this._signature._signedDate; } var year = dateTime.getFullYear().toString(); var month = _padStart((dateTime.getMonth() + 1).toString(), 2, '0'); var day = _padStart(dateTime.getDate().toString(), 2, '0'); var hours = _padStart(dateTime.getHours().toString(), 2, '0'); var minutes = _padStart(dateTime.getMinutes().toString(), 2, '0'); var seconds = _padStart(dateTime.getSeconds().toString(), 2, '0'); var totalMinutesOffset = dateTime.getTimezoneOffset(); var offsetHours = _padStart(Math.floor(Math.abs(totalMinutesOffset) / 60).toString(), 2, '0'); var offsetMinutes = _padStart((Math.abs(totalMinutesOffset) % 60).toString(), 2, '0'); var offsetSign = totalMinutesOffset > 0 ? '-' : '+'; this._dictionary.update('M', "D:" + year + month + day + hours + minutes + seconds + offsetSign + offsetHours + "'" + offsetMinutes + "'"); }; /** * Add a default Filter entry for the signature dictionary. * * @private * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addFilter = function () { this._dictionary.update('Filter', new _PdfName('Adobe.PPKLite')); }; /** * Add the SubFilter entry depending on timestamp/standard selection. * * @private * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addSubFilter = function () { if (this._signature && this._signature._isTimestampOnly) { this._dictionary.update('SubFilter', new _PdfName(this._requestForCommentsFilterType)); } else if (this._signature && this._signature._cryptographicStandard === CryptographicStandard.cades) { this._dictionary.update('SubFilter', new _PdfName(this._advanceFilterType)); } else { this._dictionary.update('SubFilter', new _PdfName(this._cryptographicFilterType)); } }; /** * Compute the combined length of pending uint8 chunks in the cross-reference. * * @private * @returns {number} The accumulated length of cached chunks. */ _PdfSignatureDictionary.prototype._getLength = function () { var length = 0; if (this._crossReference._uint8Chunks.length > 0) { for (var i = 0; i < this._crossReference._uint8Chunks.length; i++) { var arr = this._crossReference._uint8Chunks[i]; length += arr.length; } } return length; }; /** * Reserve space in the PDF for the /Contents entry and record byte positions. * * @private * @param {number[]} buffer - The output buffer being written to. * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addContents = function (buffer) { var chunksLength = this._getLength(); var writer = this._crossReference; writer._writeString('/Contents ', buffer); this._firstRangeLength = this._crossReference._currentLength + buffer.length + chunksLength; var length = this._estimatedSize * 2; if (this._signature && this._certificate) { length = this._estimatedSize; if (this._signature && this._signature) { length = this._estimatedSize + 4192; } } writer._writeString('<' + ' '.repeat(length * 2) + '>', buffer); this._secondRangeIndex = buffer.length + chunksLength + this._crossReference._currentLength; writer._writeString('\r\n', buffer); }; /** * Reserve and write the /ByteRange array placeholder into the output buffer. * * @private * @param {number[]} buffer - The output buffer to write into. * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._addRange = function (buffer) { var chunksLength = this._getLength(); var writer = this._crossReference; writer._writeString("" + '/' + 'ByteRange' + ' ' + '[', buffer); this._startPositionByteRange = buffer.length + this._document._crossReference._currentLength + chunksLength; for (var i = 0; i < 32; i++) { writer._writeString(' ', buffer); } writer._writeString("" + ']' + '\r\n', buffer); }; /** * Finalize the saved document by patching ByteRange and embedding the signature. * * @private * @param {Uint8Array} buffer - The complete document buffer to update. * @returns {void} nothing. */ _PdfSignatureDictionary.prototype._documentSaved = function (buffer) { var secondRangeLength = buffer.length - this._secondRangeIndex; var byteRangeStrings = ['0 ', this._firstRangeLength + " ", this._secondRangeIndex + " ", secondRangeLength.toString() ]; var currentPosition = this._saveRangeItem(buffer, byteRangeStrings[0], this._startPositionByteRange); currentPosition = this._saveRangeItem(buffer, byteRangeStrings[1], currentPosition); currentPosition = this._saveRangeItem(buffer, byteRangeStrings[2], currentPosition); this._saveRangeItem(buffer, byteRangeStrings[3], currentPosition); var buf1 = buffer.subarray(0, this._firstRangeLength); var buf2 = buffer.subarray(this._secondRangeIndex); var combined = new Uint8Array(buf1.length + buf2.length); combined.set(buf1, 0); combined.set(buf2, buf1.length); var pkcs7Content = this._getCryptographicStandardContent(combined); var hexEncodedSignature = _bytesToHex(pkcs7Content); var signatureStartPos = this._firstRangeLength; buffer[signatureStartPos] = '<'.charCodeAt(0) & 0xff; for (var i = 0; i < hexEncodedSignature.length; i++) { buffer[signatureStartPos + 1 + i] = hexEncodedSignature.charCodeAt(i) & 0xff; } var signatureEndPos = signatureStartPos + 1 + hexEncodedSignature.length; var paddingLength = this._secondRangeIndex - signatureEndPos - 1; if (paddingLength > 0) { buffer.fill('0'.charCodeAt(0) & 0xff, signatureEndPos, signatureEndPos + paddingLength); } buffer[this._secondRangeIndex - 1] = '>'.charCodeAt(0) & 0xff; }; /** * Build and return the PKCS#7/CAdES/CMS content bytes for the supplied data. * * @private * @param {Uint8Array} data - The data to be signed. * @returns {Uint8Array} The encoded CMS/PKCS#7 signed content. */ _PdfSignatureDictionary.prototype._getCryptographicStandardContent = function (data) { try { var hashAlgorithm = ''; var externalSignature = void 0; var crlBytes = void 0; var ocspByte = void 0; var chain_1 = []; if (this._signature._externalSignatureCallback) { if (this._signature._externalChain && this._signature._externalChain.length > 0) { hashAlgorithm = DigestAlgorithm[this._signature._digestAlgorithm]; var pks = new _PdfSignaturePrivateKey(hashAlgorithm); externalSignature = pks; chain_1.push.apply(chain_1, this._signature._externalChain); } else { var value = this._signature._externalSignatureCallback(data, { algorithm: this._signature._digestAlgorithm, cryptographicStandard: CryptographicStandard.cms }); return value.signedData; } } else { var certificateAlias_1 = ''; var pk_1; var keys = this._certificate._publicKeyCryptographyCertificate._keys; // eslint-disable-line keys.forEach(function (keyEntry, alias) { var entry = keyEntry; if (entry.privateKey) { certificateAlias_1 = alias; pk_1 = entry; } }); var certificates = this._certificate._publicKeyCryptographyCertificate._getCertificateChain(certificateAlias_1); certificates.forEach(function (c) { chain_1.push(c._certificate); }); var digest = DigestAlgorithm[this._signature._digestAlgorithm]; var pks = new _PdfSignaturePrivateKey(digest, pk_1.privateKey); hashAlgorithm = digest; externalSignature = pks; } var pkcs7 = new _PdfCryptographicMessageSyntaxSigner(null, chain_1, hashAlgorithm, false); var hash = pkcs7._getDigestAlgorithm()._digest(data, hashAlgorithm); var sequenceDataSet = pkcs7._getSequenceDataSet(hash, ocspByte, crlBytes, this._signature._cryptographicStandard); var extSignature = void 0; if (this._signature._externalChain && this._signature._externalChain.length > 0) { var value = this._signature._externalSignatureCallback(sequenceDataSet, { algorithm: this._signature._digestAlgorithm, cryptographicStandard: this._signature._cryptographicStandard }); if (value && value.signedData) { extSignature = value.signedData; } if (!value.signedData) { return new Uint8Array(this._estimatedSize).fill(0); } } else { extSignature = externalSignature._sign(sequenceDataSet); } pkcs7._setSignedData(extSignature, null, externalSignature._getEncryptionAlgorithm()); var cryptographicStandard = void 0; if (this._signature && this._signature._cryptographicStandard) { cryptographicStandard = this._signature._cryptographicStandard; } else { cryptographicStandard = CryptographicStandard.cms; } return pkcs7._sign(hash, null, ocspByte, crlBytes, cryptographicStandard, hashAlgorithm); } catch (error) { return new Uint8Array(this._estimatedSize).fill(0); } }; /** * Write a string representation into the provided buffer at the given start position. * * @private * @param {Uint8Array} buffer - The buffer to write into. * @param {string} str - The string to encode and save. * @param {number} startPosition - The offset where the string should be written. * @returns {number} The next write position after the saved string. */ _PdfSignatureDictionary.prototype._saveRangeItem = function (buffer, str, startPosition) { var utf8Bytes = []; for (var i = 0; i < str.length; i++) { utf8Bytes.push(str.charCodeAt(i) & 0xff); } buffer.set(utf8Bytes, startPosition); return startPosition + str.length; }; /** * Async variant of `_documentSaved` which finalizes and embeds the signature. * * @private * @param {Uint8Array} buffer - The document buffer to update. * @returns {Promise<void>} A promise that resolves when the operation completes. */ _PdfSignatureDictionary.prototype._documentSavedAsync = function (buffer) { return __awaiter(this, void 0, void 0, function () { var secondRangeLength, byteRangeStrings, currentPosition, buf1, buf2, combined, pkcs7Content, hexEncodedSignature, signatureStartPos, i, signatureEndPos, paddingLength; return __generator(this, function (_a) { switch (_a.label) { case 0: secondRangeLength = buffer.length - this._secondRangeIndex; byteRangeStrings = [ '0 ', this._firstRangeLength + " ", this._secondRangeIndex + " ", secondRangeLength.toString() ]; currentPosition = this._saveRangeItem(buffer, byteRangeStrings[0], this._startPositionByteRange); currentPosition = this._saveRangeItem(buffer, byteRangeStrings[1], currentPosition); currentPosition = this._saveRangeItem(buffer, byteRangeStrings[2], currentPosition); this._saveRangeItem(buffer, byteRangeStrings[3], currentPosition); buf1 = buffer.subarray(0, this._firstRangeLength); buf2 = buffer.subarray(this._secondRangeIndex); combined = new Uint8Array(buf1.length + buf2.length); combined.set(buf1, 0); combined.set(buf2, buf1.length); if (!(this._signature && this._signature._isTimestampOnly)) return [3 /*break*/, 2]; return [4 /*yield*/, this._getCryptographicStandardTimestampContentAsync(combined)]; case 1: pkcs7Content = _a.sent(); return [3 /*break*/, 4]; case 2: return [4 /*yield*/, this._getCryptographicStandardContentAsync(combined)]; case 3: pkcs7Content = _a.sent(); _a.label = 4; case 4: hexEncodedSignature = _bytesToHex(pkcs7Content); signatureStartPos = this._firstRangeLength; buffer[signatureStartPos] = '<'.charCodeAt(0) & 0xff; for (i = 0; i < hexEncodedSignature.length; i++) { buffer[signatureStartPos + 1 + i] = hexEncodedSignature.charCodeAt(i) & 0xff; } signatureEndPos = signatureStartPos + 1 + hexEncodedSignature.length; paddingLength = this._secondRangeIndex - signatureEndPos - 1; if (paddingLength > 0) { buffer.fill('0'.charCodeAt(0) & 0xff, signatureEndPos, signatureEndPos + paddingLength); } buffer[this._secondRangeIndex - 1] = '>'.charCodeAt(0) & 0xff; return [2 /*return*/]; } }); }); }; /** * Async variant of `_getCryptographicStandardContent` that may call external callbacks. * * @private * @param {Uint8Array} data - The data to sign. * @returns {Promise<Uint8Array>} The signed content bytes. */ _PdfSignatureDictionary.prototype._getCryptographicStandardContentAsync = function (data) { return __awaiter(this, void 0, void 0, function () { var timeStampResponse, hashAlgorithm, externalSignature, crlBytes, ocspByte, chain_2, pks, value, certificateAlias_2, pk_2, keys, cryptographicCertificate, certificates, digest, pkcs7, hash, sequenceDataSet, extSignature, value, cryptographicStandard, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 6, , 7]); hashAlgorithm = ''; externalSignature = void 0; crlBytes = void 0; ocspByte = void 0; chain_2 = []; if (this._signature._externalSignatureCallback) { if (this._signature._externalChain && this._signature._externalChain.length > 0) { hashAlgorithm = DigestAlgorithm[this._signature._digestAlgorithm]; pks = new _PdfSignaturePrivateKey(hashAlgorithm); externalSignature = pks; chain_2.push.apply(chain_2, this._signature._externalChain); } else { value = this._signature._externalSignatureCallback(data, { algorithm: this._signature._digestAlgorithm, cryptographicStandard: CryptographicStandard.cms }); return [2 /*return*/, value.signedData]; } } else { certificateAlias_2 = ''; keys = this._certificate._publicKeyCryptographyCertificate._keys; keys.forEach(function (keyEntry, alias) { if (keyEntry.privateKey) { certificateAlias_2 = alias; pk_2 = keyEntry; } }); cryptographicCertificate = this._certificate._publicKeyCryptographyCertificate; certificates = cryptographicCertificate._getCertificateChain(certificateAlias_2); certificates.forEach(function (c) { return chain_2.push(c._certificate); }); digest = DigestAlgorithm[this._signature._digestAlgorithm]; externalSignature = new _PdfSignaturePrivateKey(digest, pk_2.privateKey); hashAlgorithm = digest; } pkcs7 = new _PdfCryptographicMessageSyntaxSigner(null, chain_2, hashAlgorithm, false); hash = pkcs7._getDigestAlgorithm()._digest(data, hashAlgorithm); sequenceDataSet = pkcs7._getSequenceDataSet(hash, ocspByte, crlBytes, this._signature._cryptographicStandard); extSignature = void 0; if (!(this._signature._externalChain && this._signature._externalChain.length > 0)) return [3 /*break*/, 2]; return [4 /*yield*/, this._signature._externalSignatureCallback(sequenceDataSet, { algorithm: this._signature._digestAlgorithm, cryptographicStandard: this._signature._cryptographicStandard })]; case 1: value = _a.sent(); if (value.timestampData) { timeStampResponse = value.timestampData; } if (value.signedData) { extSignature = value.signedData; } else { return [2 /*return*/, new Uint8Array(this._estimatedSize).fill(0)]; } return [3 /*break*/, 4]; case 2: return [4 /*yield*/, Promise.resolve(externalSignature._sign(sequenceDataSet))]; case 3: extSignature = _a.sent(); _a.label = 4; case 4: pkcs7._setSignedData(extSignature, null, externalSignature._getEncryptionAlgorithm()); cryptographicStandard = this._signature._cryptographicStandard ? this._signature._cryptographicStandard : CryptographicStandard.cms; return [4 /*yield*/, pkcs7._signAsync(hash, this._signature, timeStampResponse, ocspByte, crlBytes, cryptographicStandard)]; case 5: return [2 /*return*/, _a.sent()]; case 6: error_1 = _a.sent(); return [2 /*return*/, new Uint8Array(this._estimatedSize).fill(0)]; case 7: return [2 /*return*/]; } }); }); }; /** * Create timestamp-only PKCS#7/CMS content asynchronously for timestamp signatures. * * @private * @param {Uint8Array} data - The timestamped data. * @returns {Promise<Uint8Array>} The encoded timestamped content. */ _PdfSignatureDictionary.prototype._getCryptographicStandardTimestampContentAsync = function (data) { return __awaiter(this, void 0, void 0, function () { var hashAlgorithm, pkcs7, hash, externalSignature, encodedBytes, padded, e_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 3, , 4]); hashAlgorithm = DigestAlgorithm[this._signature._digestAlgorithm] || 'SHA256'; pkcs7 = new _PdfCryptographicMessageSyntaxSigner(null, [], hashAlgorithm, false); hash = pkcs7._getDigestAlgorithm()._digest(data, hashAlgorithm); externalSignature = new _PdfSignaturePrivateKey(hashAlgorithm); pkcs7._setSignedData(hash, null, externalSignature._getEncryptionAlgorithm()); encodedBytes = void 0; if (!this._signature) return [3 /*break*/, 2]; return [4 /*yield*/, pkcs7._getEncodedTimestamp(hash, this._signature, hashAlgorithm)]; case 1: encodedBytes = _a.sent(); _a.label = 2; case 2: padded = new Uint8Array(encodedBytes.length); padded.set(encodedBytes); return [2 /*return*/, padded]; case 3: e_1 = _a.sent(); throw new Error(e_1.message); case 4: return [2 /*return*/]; } }); }); }; return _PdfSignatureDictionary; }()); export { _PdfSignatureDictionary };