@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
JavaScript
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 };