parent
8c2a614a08
commit
c4e5dafa17
|
@ -0,0 +1,16 @@
|
|||
@echo off
|
||||
|
||||
set csr=\java\8\jre\bin\java.exe -jar \closure-compiler\closure-compiler-v20220104.jar --charset UTF-8 --compilation_level SIMPLE_OPTIMIZATIONS --warning_level VERBOSE
|
||||
doskey csr=%csr% $*
|
||||
set externs=--externs closure\google-ext.js --externs closure\forge-ext.js --externs closure\pdflib-ext.js --externs closure\zb-externs.js
|
||||
|
||||
rem main
|
||||
set src=.
|
||||
set jss=--js %src%\zgapdfcryptor.js --js %src%\zgapdfsigner.js
|
||||
echo $
|
||||
set chkj=%%externs%% --checks_only %%jss%%
|
||||
echo chkj=csr %chkj%
|
||||
doskey chkj=%csr% %chkj%
|
||||
set csrj=%%externs%% %%jss%% --js_output_file %src%\dist\zgapdfsigner.min.js
|
||||
echo csrj=csr %csrj%
|
||||
doskey csrj=%csr% %csrj%
|
|
@ -0,0 +1,319 @@
|
|||
/** @const */
|
||||
var forge = {};
|
||||
forge.random = {};
|
||||
/**
|
||||
* @param {number} count
|
||||
* @return {string}
|
||||
*/
|
||||
forge.random.getBytesSync = function(count){};
|
||||
|
||||
forge.util = {};
|
||||
/** @constructor */
|
||||
forge.util.ByteStringBuffer = function(){};
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
forge.util.ByteStringBuffer.prototype.getBytes = function(){};
|
||||
/**
|
||||
* @param {string} value
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.util.ByteStringBuffer.prototype.putBytes = function(value){};
|
||||
/**
|
||||
* @param {number} i
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.util.ByteStringBuffer.prototype.putInt24Le = function(i){};
|
||||
/**
|
||||
* @param {number} i
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.util.ByteStringBuffer.prototype.putInt32Le = function(i){};
|
||||
/**
|
||||
* @param {number} b
|
||||
* @param {number} n
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.util.ByteStringBuffer.prototype.fillWithByte = function(b, n){};
|
||||
/**
|
||||
* @param {number} count
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.util.ByteStringBuffer.prototype.truncate = function(count){};
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
forge.util.ByteStringBuffer.prototype.toHex = function(){};
|
||||
/** @type {string} */
|
||||
forge.util.ByteStringBuffer.prototype.data;
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {string=} encoding
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.util.createBuffer = function(input, encoding){};
|
||||
/**
|
||||
* @param {string} hex
|
||||
* @return {string}
|
||||
*/
|
||||
forge.util.hexToBytes = function(hex){};
|
||||
/**
|
||||
* @param {string} value
|
||||
* @return {string}
|
||||
*/
|
||||
forge.util.decodeUtf8 = function(value){};
|
||||
|
||||
/** @constructor */
|
||||
forge.asn1 = function(){};
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* strict: (boolean|undefined),
|
||||
* parseAllBytes: (boolean|undefined),
|
||||
* decodeBitStrings: (boolean|undefined),
|
||||
* }}
|
||||
*/
|
||||
var DerOption;
|
||||
/**
|
||||
* @param {forge.util.ByteStringBuffer|string} bytes
|
||||
* @param {DerOption=} options
|
||||
* @return {forge.asn1}
|
||||
*/
|
||||
forge.asn1.fromDer = function(bytes, options){};
|
||||
/**
|
||||
* @param {forge.asn1} obj
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.asn1.toDer = function(obj){};
|
||||
/**
|
||||
* @param {number} num
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.asn1.integerToDer = function(num){};
|
||||
/**
|
||||
* @param {string} oid
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.asn1.oidToDer = function(oid){};
|
||||
forge.asn1.Type = {};
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.UTF8;
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.SET;
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.SEQUENCE;
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.BOOLEAN;
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.INTEGER;
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.OID;
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.NULL;
|
||||
/** @type {number} */
|
||||
forge.asn1.Type.OCTETSTRING;
|
||||
forge.asn1.Class = {};
|
||||
/** @type {string} */
|
||||
forge.asn1.Class.UNIVERSAL;
|
||||
/**
|
||||
* @param {string} tagClass
|
||||
* @param {number} type
|
||||
* @param {boolean} constructed
|
||||
* @param {Array<string>} value
|
||||
* @param {Object=} options
|
||||
* @return {forge.asn1}
|
||||
*/
|
||||
forge.asn1.create = function(tagClass, type, constructed, value, options){};
|
||||
/** @type {Array<forge.asn1>} */
|
||||
forge.asn1.prototype.value;
|
||||
|
||||
/** @constructor */
|
||||
const forge_BigInteger = function(){};
|
||||
/**
|
||||
* @param {forge_BigInteger} a
|
||||
* @return {number}
|
||||
*/
|
||||
forge_BigInteger.prototype.compareTo = function(a){};
|
||||
/** @constructor */
|
||||
const forge_cert = function(){};
|
||||
/** @type {forge_key} */
|
||||
forge_cert.prototype.publicKey;
|
||||
/** @type {forge_cert_issuer} */
|
||||
forge_cert.prototype.issuer;
|
||||
/** @constructor */
|
||||
const forge_key = function(){};
|
||||
/** @type {forge_BigInteger} */
|
||||
forge_key.prototype.n;
|
||||
/** @type {forge_BigInteger} */
|
||||
forge_key.prototype.e;
|
||||
/** @constructor */
|
||||
const forge_cert_issuer = function(){};
|
||||
/** @type {Array<forge_cert_attr>} */
|
||||
forge_cert_issuer.prototype.attributes;
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* valueTagClass: (string|undefined),
|
||||
* type: (string|undefined),
|
||||
* value: (string|undefined),
|
||||
* }}
|
||||
*/
|
||||
var forge_cert_attr;
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* key: (forge_key|undefined),
|
||||
* certificate: (forge_cert|undefined),
|
||||
* digestAlgorithm: (string|undefined),
|
||||
* authenticatedAttributes: (Array<forge_cert_attr>|undefined),
|
||||
* unauthenticatedAttributes: (Array<forge_cert_attr>|undefined),
|
||||
* signature: (string|undefined),
|
||||
* }}
|
||||
*/
|
||||
var forge_signer;
|
||||
|
||||
/** @constructor */
|
||||
forge.pkcs7 = function(){};
|
||||
/**
|
||||
* @return {forge.pkcs7}
|
||||
*/
|
||||
forge.pkcs7.createSignedData = function(){};
|
||||
/**
|
||||
* @param {forge_cert} cert
|
||||
*/
|
||||
forge.pkcs7.prototype.addCertificate = function(cert){};
|
||||
/**
|
||||
* @param {forge_signer} signer
|
||||
*/
|
||||
forge.pkcs7.prototype.addSigner = function(signer){};
|
||||
/** @type {Array<forge_signer>} */
|
||||
forge.pkcs7.prototype.signers;
|
||||
/** @type {Array<forge.asn1>} */
|
||||
forge.pkcs7.prototype.signerInfos;
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* detached: (boolean|undefined),
|
||||
* }}
|
||||
*/
|
||||
var forge_sign_option;
|
||||
/**
|
||||
* @param {forge_sign_option} options
|
||||
*/
|
||||
forge.pkcs7.prototype.sign = function(options){};
|
||||
/**
|
||||
* @return {forge.asn1}
|
||||
*/
|
||||
forge.pkcs7.prototype.toAsn1 = function(){};
|
||||
|
||||
/** @constructor */
|
||||
forge.pkcs12 = function(){};
|
||||
/**
|
||||
* @param {forge.asn1} obj
|
||||
* @param {boolean=} strict
|
||||
* @param {string=} password
|
||||
* @return {forge.pkcs12}
|
||||
*/
|
||||
forge.pkcs12.pkcs12FromAsn1 = function(obj, strict, password){};
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* localKeyId: (string|undefined),
|
||||
* localKeyIdHex: (string|undefined),
|
||||
* friendlyName: (string|undefined),
|
||||
* bagType: (string|undefined),
|
||||
* }}
|
||||
*/
|
||||
var P12BagsFilter;
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* cert: forge_cert,
|
||||
* key: forge_key,
|
||||
* }}
|
||||
*/
|
||||
var P12Bag;
|
||||
/**
|
||||
* @param {P12BagsFilter} filter
|
||||
* @return {Object<string, Object<string|number, P12Bag>>}
|
||||
*/
|
||||
forge.pkcs12.prototype.getBags = function(filter){};
|
||||
|
||||
forge.oids = {};
|
||||
/** @type {string} */
|
||||
forge.oids.sha256;
|
||||
forge.pki = {};
|
||||
forge.pki.oids = {};
|
||||
/** @type {string} */
|
||||
forge.pki.oids.certBag;
|
||||
/** @type {string} */
|
||||
forge.pki.oids.pkcs8ShroudedKeyBag;
|
||||
/** @type {string} */
|
||||
forge.pki.oids.sha256;
|
||||
/** @type {string} */
|
||||
forge.pki.oids.contentType;
|
||||
/** @type {string} */
|
||||
forge.pki.oids.data;
|
||||
/** @type {string} */
|
||||
forge.pki.oids.messageDigest;
|
||||
/** @type {string} */
|
||||
forge.pki.oids.signingTime;
|
||||
|
||||
forge.md = {};
|
||||
/** @constructor */
|
||||
forge.md.digest = function(){};
|
||||
/**
|
||||
* @param {string=} msg
|
||||
* @param {string=} encoding
|
||||
* @return {forge.md.digest}
|
||||
*/
|
||||
forge.md.digest.prototype.update = function(msg, encoding){};
|
||||
/**
|
||||
* @return {forge.util.ByteStringBuffer}
|
||||
*/
|
||||
forge.md.digest.prototype.digest = function(){};
|
||||
forge.md.md5 = {};
|
||||
forge.md.sha256 = {};
|
||||
/**
|
||||
* @return {forge.md.digest}
|
||||
*/
|
||||
forge.md.md5.create = function(){};
|
||||
/**
|
||||
* @return {forge.md.digest}
|
||||
*/
|
||||
forge.md.sha256.create = function(){};
|
||||
|
||||
forge.cipher = {};
|
||||
/** @constructor */
|
||||
forge.cipher.BlockCipher = function(){};
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* iv: (string|undefined),
|
||||
* additionalData: (string|undefined),
|
||||
* tagLength: (number|undefined),
|
||||
* tag: (string|undefined),
|
||||
* output: (forge.util.ByteStringBuffer|undefined),
|
||||
* }}
|
||||
*/
|
||||
var CipherOptions;
|
||||
/**
|
||||
* @param {CipherOptions} options
|
||||
*/
|
||||
forge.cipher.BlockCipher.prototype.start = function(options){};
|
||||
/**
|
||||
* @param {forge.util.ByteStringBuffer} input
|
||||
*/
|
||||
forge.cipher.BlockCipher.prototype.update = function(input){};
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
forge.cipher.BlockCipher.prototype.finish = function(){};
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
forge.cipher.BlockCipher.prototype.output;
|
||||
/**
|
||||
* @param {string} algorithm
|
||||
* @param {forge.util.ByteStringBuffer} key
|
||||
* @return {forge.cipher.BlockCipher}
|
||||
*/
|
||||
forge.cipher.createCipher = function(algorithm, key) {};
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* contentType: (string|undefined),
|
||||
* headers: (Object<string, *>|undefined),
|
||||
* method: (string|undefined),
|
||||
* payload: (string|Uint8Array|undefined),
|
||||
* useIntranet: (boolean|undefined),
|
||||
* validateHttpsCertificates: (boolean|undefined),
|
||||
* followRedirects: (boolean|undefined),
|
||||
* muteHttpExceptions: (boolean|undefined),
|
||||
* escaping: (boolean|undefined),
|
||||
* }}
|
||||
*/
|
||||
var UrlFetchParams;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function GoogleUrlFetchApp(){}
|
||||
/**
|
||||
* @param {string} url
|
||||
* @param {UrlFetchParams} params
|
||||
* @return {HTTPResponse}
|
||||
*/
|
||||
GoogleUrlFetchApp.prototype.fetch = function(url, params){};
|
||||
|
||||
/**
|
||||
* @const {!GoogleUrlFetchApp}
|
||||
*/
|
||||
var UrlFetchApp;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function HTTPResponse(){}
|
||||
/**
|
||||
* @return {GBlob}
|
||||
*/
|
||||
HTTPResponse.prototype.getBlob = function(){};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function GBlob(){}
|
||||
/**
|
||||
* @return {Array<number>}
|
||||
*/
|
||||
GBlob.prototype.getBytes = function(){};
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* ignoreEncryption: (boolean|undefined),
|
||||
* parseSpeed: (number|undefined),
|
||||
* throwOnInvalidObject: (boolean|undefined),
|
||||
* }}
|
||||
*/
|
||||
var PdfLoadOptions;
|
||||
|
||||
/** @const */
|
||||
var PDFLib = {};
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFDocument = function(){};
|
||||
/**
|
||||
* @param {string|Uint8Array|ArrayBuffer} pdf
|
||||
* @param {PdfLoadOptions=} options
|
||||
* @return {PDFLib.PDFDocument}
|
||||
*/
|
||||
PDFLib.PDFDocument.load = function(pdf, options){};
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* useObjectStreams: (boolean|undefined),
|
||||
* addDefaultPage: (boolean|undefined),
|
||||
* objectsPerTick: (number|undefined),
|
||||
* }}
|
||||
*/
|
||||
var PdfSaveOptions;
|
||||
/**
|
||||
* @param {PdfSaveOptions} options
|
||||
* @returns {Promise<Uint8Array>}
|
||||
*/
|
||||
PDFLib.PDFDocument.prototype.save = function(options){};
|
||||
/**
|
||||
* @returns {Array<PDFLib.PDFPage>}
|
||||
*/
|
||||
PDFLib.PDFDocument.prototype.getPages = function(){};
|
||||
/**
|
||||
* @param {ArrayBuffer|Uint8Array|string} png
|
||||
* @returns {Promise<PDFLib.PDFImage>}
|
||||
*/
|
||||
PDFLib.PDFDocument.prototype.embedPng = function(png){};
|
||||
/**
|
||||
* @param {ArrayBuffer|Uint8Array|string} jpg
|
||||
* @returns {Promise<PDFLib.PDFImage>}
|
||||
*/
|
||||
PDFLib.PDFDocument.prototype.embedJpg = function(jpg){};
|
||||
/** @type {PDFLib.PDFCatalog} */
|
||||
PDFLib.PDFDocument.prototype.catalog;
|
||||
/** @type {PDFLib.PDFContext} */
|
||||
PDFLib.PDFDocument.prototype.context;
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFCatalog = function(){};
|
||||
/**
|
||||
* @param {PDFLib.PDFName} name
|
||||
* @param {PDFLib.PDFObject} object
|
||||
*/
|
||||
PDFLib.PDFCatalog.prototype.set = function(name, object){};
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFPage = function(){};
|
||||
/** @type {PDFLib.PDFRef} */
|
||||
PDFLib.PDFPage.prototype.ref;
|
||||
/** @type {PDFLib.PDFPageLeaf} */
|
||||
PDFLib.PDFPage.prototype.node;
|
||||
/**
|
||||
* @return {PDFLib.Rotation}
|
||||
*/
|
||||
PDFLib.PDFPage.prototype.getRotation = function(){};
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* width: number,
|
||||
* height: number,
|
||||
* }}
|
||||
*/
|
||||
var PdfSize;
|
||||
/**
|
||||
* @return {PdfSize}
|
||||
*/
|
||||
PDFLib.PDFPage.prototype.getSize = function(){};
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFPageLeaf = function(){};
|
||||
/**
|
||||
* @param {PDFLib.PDFName} name
|
||||
* @param {PDFLib.PDFObject} object
|
||||
*/
|
||||
PDFLib.PDFPageLeaf.prototype.set = function(name, object){};
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFRef = function(){};
|
||||
/** @type {number} */
|
||||
PDFLib.PDFRef.prototype.objectNumber;
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFContext = function(){};
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* 0: PDFLib.PDFRef,
|
||||
* 1: PDFLib.PDFObject,
|
||||
* }}
|
||||
*/
|
||||
var PdfObjEntry;
|
||||
/** @return {Array<PdfObjEntry>} */
|
||||
PDFLib.PDFContext.prototype.enumerateIndirectObjects = function(){};
|
||||
/** @type {Object<string, *>} */
|
||||
PDFLib.PDFContext.prototype.trailerInfo;
|
||||
/**
|
||||
* @param {PDFLib.PDFObject} object
|
||||
* @return {PDFLib.PDFRef}
|
||||
*/
|
||||
PDFLib.PDFContext.prototype.register = function(object){};
|
||||
/**
|
||||
* @param {*} literal
|
||||
* @return {PDFLib.PDFObject}
|
||||
*/
|
||||
PDFLib.PDFContext.prototype.obj = function(literal){};
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFObject = function(){};
|
||||
/** @type {Map<PDFLib.PDFRef, PDFLib.PDFObject>} */
|
||||
PDFLib.PDFObject.prototype.dict;
|
||||
/** @type {Array<PDFLib.PDFName>} */
|
||||
PDFLib.PDFObject.prototype.array;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {PDFLib.PDFObject}
|
||||
*/
|
||||
PDFLib.PDFName = function(){};
|
||||
/**
|
||||
* @param {string} value
|
||||
* @return {PDFLib.PDFName}
|
||||
*/
|
||||
PDFLib.PDFName.of = function(value){};
|
||||
/** @type {string} */
|
||||
PDFLib.PDFName.prototype.encodedName;
|
||||
/** @type {number} */
|
||||
PDFLib.PDFName.prototype.numberValue;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {PDFLib.PDFContext} context
|
||||
*/
|
||||
PDFLib.PDFArray = function(context){};
|
||||
/**
|
||||
* @param {PDFLib.PDFObject} object
|
||||
*/
|
||||
PDFLib.PDFArray.prototype.push = function(object){};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {PDFLib.PDFObject}
|
||||
*/
|
||||
PDFLib.PDFString = function(){};
|
||||
/**
|
||||
* @param {string} value
|
||||
* @return {PDFLib.PDFString}
|
||||
*/
|
||||
PDFLib.PDFString.of = function(value){};
|
||||
/**
|
||||
* @param {Date} value
|
||||
* @return {PDFLib.PDFString}
|
||||
*/
|
||||
PDFLib.PDFString.fromDate = function(value){};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {PDFLib.PDFObject}
|
||||
*/
|
||||
PDFLib.PDFHexString = function(){};
|
||||
/**
|
||||
* @param {string} value
|
||||
* @return {PDFLib.PDFHexString}
|
||||
*/
|
||||
PDFLib.PDFHexString.of = function(value){};
|
||||
/**
|
||||
* @param {string} value
|
||||
* @return {PDFLib.PDFHexString}
|
||||
*/
|
||||
PDFLib.PDFHexString.fromText = function(value){};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {PDFLib.PDFObject}
|
||||
*/
|
||||
PDFLib.PDFNumber = function(){};
|
||||
/**
|
||||
* @param {number} value
|
||||
* @return {PDFLib.PDFNumber}
|
||||
*/
|
||||
PDFLib.PDFNumber.of = function(value){};
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFImage = function(){};
|
||||
/**
|
||||
* @return {PdfSize}
|
||||
*/
|
||||
PDFLib.PDFImage.prototype.size = function(){};
|
||||
/** @type {PDFLib.PDFRef} */
|
||||
PDFLib.PDFImage.prototype.ref;
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFFont = function(){};
|
||||
/** @type {PDFLib.PDFRef} */
|
||||
PDFLib.PDFFont.prototype.ref;
|
||||
/** @constructor */
|
||||
PDFLib.StandardFonts = function(){};
|
||||
|
||||
PDFLib.RotationTypes = {};
|
||||
/** @type {string} */
|
||||
PDFLib.RotationTypes.Degrees;
|
||||
/** @constructor */
|
||||
PDFLib.Rotation = function(){};
|
||||
/** @type {string} */
|
||||
PDFLib.Rotation.prototype.type;
|
||||
/**
|
||||
* @param {number} d
|
||||
* @return {PDFLib.Rotation}
|
||||
*/
|
||||
PDFLib.degrees = function(d){};
|
||||
/**
|
||||
* @param {PDFLib.Rotation} rot
|
||||
* @return {PDFLib.Rotation}
|
||||
*/
|
||||
PDFLib.toDegrees = function(rot){};
|
||||
|
||||
/** @constructor */
|
||||
PDFLib.PDFOperator = function(){};
|
||||
/**
|
||||
* @typedef
|
||||
* {{
|
||||
* x: (number|undefined),
|
||||
* y: (number|undefined),
|
||||
* width: (number|undefined),
|
||||
* height: (number|undefined),
|
||||
* rotate: (PDFLib.Rotation|undefined),
|
||||
* xSkew: (PDFLib.Rotation|undefined),
|
||||
* ySkew: (PDFLib.Rotation|undefined),
|
||||
* }}
|
||||
*/
|
||||
var PdfDrawimgOption;
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {PdfDrawimgOption} options
|
||||
*/
|
||||
PDFLib.drawImage = function(name, options){};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {PDFLib.PDFObject}
|
||||
*/
|
||||
PDFLib.PDFContentStream = function(){};
|
||||
/**
|
||||
* @param {PDFLib.PDFObject} dict
|
||||
* @param {Array<PDFLib.PDFOperator>} operators
|
||||
* @param {boolean=} encode
|
||||
* @return {PDFLib.PDFContentStream}
|
||||
*/
|
||||
PDFLib.PDFContentStream.of = function(dict, operators, encode){};
|
|
@ -51,7 +51,7 @@ var SignOption;
|
|||
* @typedef
|
||||
* {{
|
||||
* c: string,
|
||||
* p: (Array<Zga.Crypto.Permission>|undefined),
|
||||
* p: (Array<string>|undefined),
|
||||
* }}
|
||||
*/
|
||||
var PubKeyInfo;
|
||||
|
@ -74,7 +74,7 @@ var PubKeyInfo;
|
|||
* @typedef
|
||||
* {{
|
||||
* mode: Zga.Crypto.Mode,
|
||||
* permissions: (Array<Zga.Crypto.Permission>|undefined),
|
||||
* permissions: (Array<string>|undefined),
|
||||
* userpwd: (string|undefined),
|
||||
* ownerpwd: (string|undefined),
|
||||
* pubkeys: (Array<PubKeyInfo>|undefined),
|
||||
|
@ -101,3 +101,25 @@ var CFType;
|
|||
* }}
|
||||
*/
|
||||
var RC4LastInfo;
|
||||
|
||||
var Zga = {};
|
||||
Zga.Crypto = {};
|
||||
/** @enum {number} */
|
||||
Zga.Crypto.Mode = {
|
||||
RC4_40: 0,
|
||||
RC4_128: 1,
|
||||
AES_128: 2,
|
||||
AES_256: 3,
|
||||
};
|
||||
/**
|
||||
* @constructor
|
||||
* @param {EncryptOption} encopt
|
||||
*/
|
||||
Zga.PdfCryptor = function(encopt){};
|
||||
/**
|
||||
* @param {PDFLib.PDFDocument|Array<number>|Uint8Array|ArrayBuffer|string} pdf
|
||||
* @param {boolean=} reload
|
||||
* @return {Promise<PDFLib.PDFDocument>}
|
||||
*/
|
||||
Zga.PdfCryptor.prototype.encryptPdf = function(pdf, reload){};
|
||||
|
||||
|
|
119
zgapdfcryptor.js
119
zgapdfcryptor.js
|
@ -14,11 +14,11 @@ z.loadPdf = async function(pdf){
|
|||
/** @type {PDFLib.PDFDocument} */
|
||||
var pdfdoc = null;
|
||||
if(pdf.addPage){
|
||||
pdfdoc = pdf;
|
||||
pdfdoc = /** @type {PDFLib.PDFDocument} */(pdf);
|
||||
}else if(Array.isArray(pdf)){
|
||||
pdfdoc = await PDFLib.PDFDocument.load(new Uint8Array(pdf));
|
||||
}else{
|
||||
pdfdoc = await PDFLib.PDFDocument.load(pdf);
|
||||
pdfdoc = await PDFLib.PDFDocument.load(/** @type {(ArrayBuffer|Uint8Array|string)} */(pdf));
|
||||
}
|
||||
return pdfdoc;
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ z.u8arrToRaw = function(uarr){
|
|||
* @return {Uint8Array}
|
||||
*/
|
||||
z.rawToU8arr = function(raw){
|
||||
/** @type {Uint8Array} */
|
||||
var arr = new Uint8Array(raw.length);
|
||||
for(var i=0; i<raw.length; i++){
|
||||
arr[i] = raw.charCodeAt(i);
|
||||
|
@ -86,9 +87,12 @@ z.Crypto = {
|
|||
if(!s){
|
||||
return s;
|
||||
}
|
||||
/** @const {Array<string>} */
|
||||
const CHARS = "\\()".split("");
|
||||
/** @type {Array<string>} */
|
||||
var arr = [];
|
||||
for(var i=0; i<s.length; i++){
|
||||
/** @type {string} */
|
||||
var c = s.charAt(i);
|
||||
if(c == "\r"){
|
||||
arr.push("\\r");
|
||||
|
@ -108,6 +112,7 @@ z.Crypto = {
|
|||
* @return {string} containing random data
|
||||
*/
|
||||
getRandomSeed: function(seed){
|
||||
/** @type {string} */
|
||||
var ret = forge.random.getBytesSync(256);
|
||||
if(seed){
|
||||
ret += seed;
|
||||
|
@ -127,10 +132,14 @@ z.Crypto = {
|
|||
_RC4: function(key, txt, lastinf){
|
||||
/** @type {Array<number>} */
|
||||
var rc4 = null;
|
||||
/** @type {number} */
|
||||
var i = 0;
|
||||
/** @type {number} */
|
||||
var j = 0;
|
||||
/** @type {number} */
|
||||
var t = 0;
|
||||
if(lastinf.enckey != key){
|
||||
/** @type {string} */
|
||||
var k = key.repeat(256 / key.length + 1);
|
||||
rc4 = new Array(256);
|
||||
// Initialize rc4
|
||||
|
@ -148,9 +157,13 @@ z.Crypto = {
|
|||
}else{
|
||||
rc4 = [].concat(lastinf.enckeyc);
|
||||
}
|
||||
/** @type {number} */
|
||||
var len = txt.length;
|
||||
/** @type {number} */
|
||||
var a = 0;
|
||||
/** @type {number} */
|
||||
var b = 0;
|
||||
/** @type {string} */
|
||||
var out = "";
|
||||
for(i=0; i<len; i++){
|
||||
a = (a + 1) % 256;
|
||||
|
@ -167,14 +180,16 @@ z.Crypto = {
|
|||
/**
|
||||
* Return the permission code used on encryption (P value).
|
||||
*
|
||||
* @param {Array<Zga.Crypto.Permission>=} permissions the set of permissions (specify the ones you want to block).
|
||||
* @param {Zga.Crypto.Mode=} mode
|
||||
* @param {Array<string>=} permissions the set of permissions (specify the ones you want to block).
|
||||
* @param {z.Crypto.Mode=} mode
|
||||
* @return {number}
|
||||
*/
|
||||
getUserPermissionCode: function(permissions, mode){
|
||||
/** @type {number} */
|
||||
var protection = 2147422012; // 32 bit: (01111111 11111111 00001111 00111100)
|
||||
if(permissions){
|
||||
permissions.forEach(function(a_itm){
|
||||
/** @type {number} */
|
||||
var a_p = z.Crypto.Permission[a_itm];
|
||||
if(a_p){
|
||||
if(mode > 0 || a_p <= 32){
|
||||
|
@ -198,6 +213,7 @@ z.Crypto = {
|
|||
* @return {string}
|
||||
*/
|
||||
getEncPermissionsString: function(protection){
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var buff = new forge.util.ByteStringBuffer();
|
||||
buff.putInt32Le(protection);
|
||||
return buff.getBytes();
|
||||
|
@ -209,6 +225,7 @@ z.Crypto = {
|
|||
* @return {string} MD5 encrypted binary string
|
||||
*/
|
||||
_md5_16: function(str){
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.md5.create();
|
||||
md.update(str);
|
||||
return md.digest().getBytes();
|
||||
|
@ -223,13 +240,17 @@ z.Crypto = {
|
|||
*/
|
||||
_AES: function(key, txt){
|
||||
// padding (RFC 2898, PKCS #5: Password-Based Cryptography Specification Version 2.0)
|
||||
/** @type {string} */
|
||||
/** @type {number} */
|
||||
var padding = 16 - (txt.length % 16);
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var buff = forge.util.createBuffer(txt);
|
||||
buff.fillWithByte(padding, padding);
|
||||
|
||||
/** @type {string} */
|
||||
var iv = forge.random.getBytesSync(16);
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var key2 = forge.util.createBuffer(key);
|
||||
/** @type {forge.cipher.BlockCipher} */
|
||||
var cipher = forge.cipher.createCipher("AES-CBC", key2);
|
||||
cipher.start({iv: iv});
|
||||
cipher.update(buff);
|
||||
|
@ -245,9 +266,13 @@ z.Crypto = {
|
|||
* @return {string} encrypted text
|
||||
*/
|
||||
_AESnopad: function(key, txt) {
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var buff = forge.util.createBuffer(txt);
|
||||
/** @type {string} */
|
||||
var iv = String.fromCharCode(0).repeat(16);
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var key2 = forge.util.createBuffer(key);
|
||||
/** @type {forge.cipher.BlockCipher} */
|
||||
var cipher = forge.cipher.createCipher("AES-CBC", key2);
|
||||
cipher.start({iv: iv});
|
||||
cipher.update(buff);
|
||||
|
@ -259,18 +284,17 @@ z.Crypto = {
|
|||
|
||||
z.PdfCryptor = class{
|
||||
/**
|
||||
* @constructor
|
||||
* @param {EncryptOption} encopt
|
||||
*/
|
||||
constructor(encopt){
|
||||
/** @private @type {string} */
|
||||
this.fileid = "";
|
||||
/** @private @type {string} */
|
||||
this.key = null;
|
||||
/** @private @type {Array<PubKeyInfo>} */
|
||||
this.key = "";
|
||||
/** @private @type {Array<PubKeyInfo>|undefined} */
|
||||
this.pubkeys = encopt.pubkeys;
|
||||
/** @private @type {number} */
|
||||
this.mode = encopt.mode;
|
||||
/** @private @type {z.Crypto.Mode} */
|
||||
this.mode = /** @type {z.Crypto.Mode} */(encopt.mode);
|
||||
/** @private @type {number} */
|
||||
this.protection = 0;
|
||||
/** @private @type {string} */
|
||||
|
@ -289,7 +313,7 @@ z.PdfCryptor = class{
|
|||
this.V = 1;
|
||||
/** @private @type {number} */
|
||||
this.Length = 0;
|
||||
/** @private @type {CFType} */
|
||||
/** @private @type {?CFType} */
|
||||
this.CF = null;
|
||||
/** @private @type {string} */
|
||||
this.SubFilter = "";
|
||||
|
@ -325,7 +349,6 @@ z.PdfCryptor = class{
|
|||
};
|
||||
|
||||
if(this.pubkeys){
|
||||
throw new Error("Public key mode is not supported yet.");
|
||||
if(this.mode == z.Crypto.Mode.RC4_40){
|
||||
// public-Key Security requires at least 128 bit
|
||||
this.mode = z.Crypto.Mode.RC4_128;
|
||||
|
@ -333,6 +356,7 @@ z.PdfCryptor = class{
|
|||
this.Filter = "Adobe.PubSec";
|
||||
this.StmF = "DefaultCryptFilter";
|
||||
this.StrF = "DefaultCryptFilter";
|
||||
throw new Error("Public key mode is not supported yet.");
|
||||
}
|
||||
|
||||
if(encopt.userpwd){
|
||||
|
@ -341,6 +365,7 @@ z.PdfCryptor = class{
|
|||
if(encopt.ownerpwd){
|
||||
this.ownerpwd = encopt.ownerpwd;
|
||||
}else{
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.md5.create();
|
||||
md.update(z.Crypto.getRandomSeed());
|
||||
this.ownerpwd = md.digest().toHex();
|
||||
|
@ -379,6 +404,8 @@ z.PdfCryptor = class{
|
|||
this.Recipients = [];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unknown crypto mode. " + this.mode);
|
||||
}
|
||||
|
||||
this.protection = z.Crypto.getUserPermissionCode(encopt.permissions, this.mode);
|
||||
|
@ -411,7 +438,7 @@ z.PdfCryptor = class{
|
|||
|
||||
/**
|
||||
* @param {number} a_num
|
||||
* @param {*} a_val
|
||||
* @param {PDFLib.PDFObject} a_val
|
||||
*/
|
||||
var func = function(a_num, a_val){
|
||||
if(a_val instanceof PDFLib.PDFStream){
|
||||
|
@ -430,7 +457,7 @@ z.PdfCryptor = class{
|
|||
if(a_val.dict instanceof Map){
|
||||
/** @type {Iterator} */
|
||||
var a_es = a_val.dict.entries();
|
||||
/** @type {IteratorResult} */
|
||||
/** @type {IIterableResult<PdfObjEntry>} */
|
||||
var a_res = a_es.next();
|
||||
while(!a_res.done){
|
||||
func(a_num, a_res.value[1]);
|
||||
|
@ -438,7 +465,7 @@ z.PdfCryptor = class{
|
|||
}
|
||||
}
|
||||
}.bind(this);
|
||||
pdfcont.enumerateIndirectObjects().forEach(function(a_arr){
|
||||
pdfcont.enumerateIndirectObjects().forEach(function(/** @type {PdfObjEntry} */a_arr){
|
||||
func(a_arr[0].objectNumber, a_arr[1]);
|
||||
});
|
||||
|
||||
|
@ -456,12 +483,17 @@ z.PdfCryptor = class{
|
|||
*/
|
||||
prepareEncrypt(pdfcont){
|
||||
if(!pdfcont.trailerInfo.ID){
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.md5.create();
|
||||
md.update(z.Crypto.getRandomSeed());
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var res = md.digest();
|
||||
/** @type {string} */
|
||||
var idhex = res.toHex();
|
||||
/** @type {string} */
|
||||
this.fileid = res.getBytes();
|
||||
|
||||
/** @type {PDFLib.PDFArray} */
|
||||
var trIds = new PDFLib.PDFArray(pdfcont);
|
||||
trIds.push(PDFLib.PDFHexString.of(idhex));
|
||||
trIds.push(PDFLib.PDFHexString.of(idhex));
|
||||
|
@ -484,6 +516,7 @@ z.PdfCryptor = class{
|
|||
if(this.V >= 4){
|
||||
// A dictionary whose keys shall be crypt filter names and whose values shall be the corresponding crypt filter dictionaries.
|
||||
if(this.CF){
|
||||
/** @type {Object<string, *>} */
|
||||
var objStmF = {
|
||||
Type: "CryptFilter",
|
||||
};
|
||||
|
@ -492,11 +525,11 @@ z.PdfCryptor = class{
|
|||
objStmF.CFM = this.CF.CFM;
|
||||
if(this.pubkeys){
|
||||
/** @type {PDFLib.PDFArray} */
|
||||
var recps = new PDFLib.PDFArray(pdfcont);
|
||||
var recps1 = new PDFLib.PDFArray(pdfcont);
|
||||
this.Recipients.forEach(function(a_ele){
|
||||
recps.push(PDFLib.PDFHexString.of(a_ele));
|
||||
recps1.push(PDFLib.PDFHexString.of(a_ele));
|
||||
});
|
||||
objStmF.Recipients = recps;
|
||||
objStmF.Recipients = recps1;
|
||||
if(typeof this.CF.EncryptMetadata == "boolean" && !this.CF.EncryptMetadata){
|
||||
objStmF.EncryptMetadata = false;
|
||||
}else{
|
||||
|
@ -517,6 +550,7 @@ z.PdfCryptor = class{
|
|||
objStmF.Length = this.CF.Length;
|
||||
}
|
||||
|
||||
/** @type {Object<string, *>} */
|
||||
var objCF = {
|
||||
[this.StmF]: pdfcont.obj(objStmF),
|
||||
};
|
||||
|
@ -569,7 +603,9 @@ z.PdfCryptor = class{
|
|||
* @return {Uint8Array}
|
||||
*/
|
||||
encryptU8arr(num, dat){
|
||||
/** @type {string} */
|
||||
var str = z.u8arrToRaw(dat);
|
||||
/** @type {string} */
|
||||
var enc = this._encrypt_data(num, str);
|
||||
return z.rawToU8arr(enc);
|
||||
}
|
||||
|
@ -581,7 +617,9 @@ z.PdfCryptor = class{
|
|||
* @return {string}
|
||||
*/
|
||||
encryptHexstr(num, dat){
|
||||
/** @type {string} */
|
||||
var str = forge.util.hexToBytes(dat);
|
||||
/** @type {string} */
|
||||
var enc = this._encrypt_data(num, str);
|
||||
return forge.util.createBuffer(enc).toHex();
|
||||
}
|
||||
|
@ -595,6 +633,7 @@ z.PdfCryptor = class{
|
|||
* @return {string} object key
|
||||
*/
|
||||
_objectkey(n){
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var buff = forge.util.createBuffer(this.key);
|
||||
//pack('VXxx', $n)
|
||||
buff.putInt24Le(n);
|
||||
|
@ -604,8 +643,10 @@ z.PdfCryptor = class{
|
|||
buff.putBytes("sAlT");
|
||||
}
|
||||
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.md5.create();
|
||||
md.update(buff.getBytes());
|
||||
/** @type {forge.util.ByteStringBuffer} */
|
||||
var ret = md.digest();
|
||||
return ret.getBytes().substr(0, Math.min(16, (this.Length / 8) + 5));
|
||||
}
|
||||
|
@ -640,13 +681,19 @@ z.PdfCryptor = class{
|
|||
* @return {string} U value
|
||||
*/
|
||||
_Uvalue(){
|
||||
/** @type {string} */
|
||||
var ret = "";
|
||||
if(this.mode == z.Crypto.Mode.RC4_40){
|
||||
return z.Crypto._RC4(this.key, z.Crypto.EncPadding, this.rc4inf);
|
||||
ret = z.Crypto._RC4(this.key, z.Crypto.EncPadding, this.rc4inf);
|
||||
}else if(this.mode < z.Crypto.Mode.AES_256) { // RC4-128, AES-128
|
||||
/** @type {string} */
|
||||
var tmp = z.Crypto._md5_16(z.Crypto.EncPadding + this.fileid);
|
||||
/** @type {string} */
|
||||
var enc = z.Crypto._RC4(this.key, tmp, this.rc4inf);
|
||||
/** @type {number} */
|
||||
var len = tmp.length;
|
||||
for(var i=1; i<=19; i++){
|
||||
/** @type {string} */
|
||||
var ek = "";
|
||||
for(var j=0; j<len; j++){
|
||||
ek += String.fromCharCode(this.key.charCodeAt(j) ^ i);
|
||||
|
@ -654,19 +701,24 @@ z.PdfCryptor = class{
|
|||
enc = z.Crypto._RC4(ek, enc, this.rc4inf);
|
||||
}
|
||||
enc += String.fromCharCode(0).repeat(16);
|
||||
return enc.substr(0, 32);
|
||||
ret = enc.substr(0, 32);
|
||||
|
||||
}else if(this.mode == z.Crypto.Mode.AES_256){
|
||||
/** @type {string} */
|
||||
var seed = z.Crypto._md5_16(z.Crypto.getRandomSeed());
|
||||
// User Validation Salt
|
||||
/** @type {string} */
|
||||
this.UVS = seed.substr(0, 8);
|
||||
// User Key Salt
|
||||
/** @type {string} */
|
||||
this.UKS = seed.substr(8, 16);
|
||||
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.sha256.create();
|
||||
md.update(this.userpwd + this.UVS);
|
||||
return md.digest().getBytes() + this.UVS + this.UKS;
|
||||
ret = md.digest().getBytes() + this.UVS + this.UKS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -675,6 +727,7 @@ z.PdfCryptor = class{
|
|||
* @return {string} UE value
|
||||
*/
|
||||
_UEvalue(){
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.sha256.create();
|
||||
md.update(this.userpwd + this.UKS);
|
||||
return z.Crypto._AESnopad(md.digest().getBytes(), this.key);
|
||||
|
@ -686,37 +739,47 @@ z.PdfCryptor = class{
|
|||
* @return {string} O value
|
||||
*/
|
||||
_Ovalue(){
|
||||
/** @type {string} */
|
||||
var ret = "";
|
||||
if(this.mode < z.Crypto.Mode.AES_256){ // RC4-40, RC4-128, AES-128
|
||||
/** @type {string} */
|
||||
var tmp = z.Crypto._md5_16(this.ownerpwd);
|
||||
if(this.mode > z.Crypto.Mode.RC4_40){
|
||||
for(var i=0; i<50; i++){
|
||||
tmp = z.Crypto._md5_16(tmp);
|
||||
}
|
||||
}
|
||||
/** @type {string} */
|
||||
var owner_key = tmp.substr(0, this.Length / 8);
|
||||
var enc = z.Crypto._RC4(owner_key, this.userpwd, this.rc4inf);
|
||||
ret = z.Crypto._RC4(owner_key, this.userpwd, this.rc4inf);
|
||||
if(this.mode > z.Crypto.Mode.RC4_40){
|
||||
/** @type {number} */
|
||||
var len = owner_key.length;
|
||||
for(var i=1; i<=19; i++){
|
||||
/** @type {string} */
|
||||
var ek = "";
|
||||
for(var j=0; j<len; j++){
|
||||
ek += String.fromCharCode(owner_key.charCodeAt(j) ^ i);
|
||||
}
|
||||
enc = z.Crypto._RC4(ek, enc, this.rc4inf);
|
||||
ret = z.Crypto._RC4(ek, ret, this.rc4inf);
|
||||
}
|
||||
}
|
||||
return enc;
|
||||
}else if(this.mode == z.Crypto.Mode.AES_256){
|
||||
/** @type {string} */
|
||||
var seed = z.Crypto._md5_16(z.Crypto.getRandomSeed());
|
||||
// Owner Validation Salt
|
||||
/** @type {string} */
|
||||
this.OVS = seed.substr(0, 8);
|
||||
// Owner Key Salt
|
||||
/** @type {string} */
|
||||
this.OKS = seed.substr(8, 16);
|
||||
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.sha256.create();
|
||||
md.update(this.ownerpwd + this.OVS + this.U);
|
||||
return md.digest().getBytes() + this.OVS + this.OKS;
|
||||
ret = md.digest().getBytes() + this.OVS + this.OKS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -725,6 +788,7 @@ z.PdfCryptor = class{
|
|||
* @return {string} OE value
|
||||
*/
|
||||
_OEvalue(){
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.sha256.create();
|
||||
md.update(this.ownerpwd + this.OKS + this.U);
|
||||
return z.Crypto._AESnopad(md.digest().getBytes(), this.key);
|
||||
|
@ -745,11 +809,13 @@ z.PdfCryptor = class{
|
|||
* @private
|
||||
*/
|
||||
_generateencryptionkey(){
|
||||
/** @type {number} */
|
||||
var keybytelen = this.Length / 8;
|
||||
// standard mode
|
||||
if(!this.pubkeys){
|
||||
if(this.mode == z.Crypto.Mode.AES_256){
|
||||
// generate 256 bit random key
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.sha256.create();
|
||||
md.update(z.Crypto.getRandomSeed());
|
||||
this.key = md.digest().getBytes().substr(0, keybytelen);
|
||||
|
@ -767,6 +833,7 @@ z.PdfCryptor = class{
|
|||
// Compute P value
|
||||
this.P = this.protection;
|
||||
// Computing the encryption dictionary's Perms (permissions) value
|
||||
/** @type {string} */
|
||||
var perms = z.Crypto.getEncPermissionsString(this.protection); // bytes 0-3
|
||||
perms += String.fromCharCode(255).repeat(4); // bytes 4-7
|
||||
if(typeof this.CF.EncryptMetadata == "boolean" && !this.CF.EncryptMetadata){ // byte 8
|
||||
|
@ -784,8 +851,10 @@ z.PdfCryptor = class{
|
|||
// Compute O value
|
||||
this.O = this._Ovalue();
|
||||
// get default permissions (reverse byte order)
|
||||
/** @type {string} */
|
||||
var permissions = z.Crypto.getEncPermissionsString(this.protection);
|
||||
// Compute encryption key
|
||||
/** @type {string} */
|
||||
var tmp = z.Crypto._md5_16(this.userpwd + this.O + permissions + this.fileid);
|
||||
if(this.mode > z.Crypto.Mode.RC4_40) {
|
||||
for(var i=0; i<50; i++){
|
||||
|
|
|
@ -18,7 +18,6 @@ z.TSAURLS = {
|
|||
|
||||
z.PdfSigner = class{
|
||||
/**
|
||||
* @constructor
|
||||
* @param {SignOption} signopt
|
||||
*/
|
||||
constructor(signopt){
|
||||
|
@ -26,7 +25,7 @@ z.PdfSigner = class{
|
|||
this.DEFAULT_BYTE_RANGE_PLACEHOLDER = "**********";
|
||||
/** @private @type {SignOption} */
|
||||
this.opt = signopt;
|
||||
/** @private @type {TsaServiceInfo} */
|
||||
/** @private @type {?TsaServiceInfo} */
|
||||
this.tsainf = null;
|
||||
/** @private @type {number} */
|
||||
this.siglen = 0;
|
||||
|
@ -47,7 +46,7 @@ z.PdfSigner = class{
|
|||
url: signopt.signdate,
|
||||
};
|
||||
}else if(signopt.signdate.url){
|
||||
this.tsainf = Object.assign({}, signopt.signdate);
|
||||
this.tsainf = /** @type {TsaServiceInfo} */(Object.assign({}, signopt.signdate));
|
||||
}
|
||||
}
|
||||
if(this.tsainf){
|
||||
|
@ -150,7 +149,7 @@ z.PdfSigner = class{
|
|||
* @param {PDFLib.PDFDocument} pdfdoc
|
||||
*/
|
||||
addSignHolder(pdfdoc){
|
||||
/** @const {VisualSignature} */
|
||||
/** @const {z.VisualSignature} */
|
||||
const visign = new z.VisualSignature(this.opt.drawinf);
|
||||
/** @const {PDFLib.PDFRef} */
|
||||
const strmRef = visign.createStream(pdfdoc, this.opt.signame);
|
||||
|
@ -170,7 +169,7 @@ z.PdfSigner = class{
|
|||
bytrng.push(PDFLib.PDFName.of(this.DEFAULT_BYTE_RANGE_PLACEHOLDER));
|
||||
bytrng.push(PDFLib.PDFName.of(this.DEFAULT_BYTE_RANGE_PLACEHOLDER));
|
||||
|
||||
this.siglen = this.tsainf ? this.tsainf.len : 3322;
|
||||
this.siglen = /** @type {number} */(this.tsainf ? this.tsainf.len : 3322);
|
||||
this.sigContents = PDFLib.PDFHexString.of("0".repeat(this.siglen));
|
||||
|
||||
/** @type {Object<string, *>} */
|
||||
|
@ -239,13 +238,13 @@ z.PdfSigner = class{
|
|||
var istgt = false;
|
||||
/** @type {PDFLib.PDFHexString} */
|
||||
var sigContents = null;
|
||||
/** @type {Array<*>} */
|
||||
/** @type {Array<PdfObjEntry>} */
|
||||
var objarr = pdfdoc.context.enumerateIndirectObjects();
|
||||
for(var i=objarr.length - 1; i>= 0; i--){
|
||||
if(objarr[i][1].dict instanceof Map){
|
||||
/** @type {Iterator} */
|
||||
/** @type {Iterator<PdfObjEntry>} */
|
||||
var es = objarr[i][1].dict.entries();
|
||||
/** @type {IteratorResult} */
|
||||
/** @type {IIterableResult<PdfObjEntry>} */
|
||||
var res = es.next();
|
||||
istgt = false;
|
||||
sigContents = null;
|
||||
|
@ -272,6 +271,7 @@ z.PdfSigner = class{
|
|||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -287,24 +287,35 @@ z.PdfSigner = class{
|
|||
}
|
||||
|
||||
// Finds ByteRange information within a given PDF Buffer if one exists
|
||||
/** @type {Array<string>} */
|
||||
var byteRangeStrings = pdfstr.match(/\/ByteRange\s*\[{1}\s*(?:(?:\d*|\/\*{10})\s+){3}(?:\d+|\/\*{10}){1}\s*]{1}/g);
|
||||
/** @type {string|undefined} */
|
||||
var byteRangePlaceholder = byteRangeStrings.find(function(a_str){
|
||||
return a_str.includes("/"+this.DEFAULT_BYTE_RANGE_PLACEHOLDER);
|
||||
}.bind(this));
|
||||
if(!byteRangePlaceholder){
|
||||
throw new Error("no signature placeholder");
|
||||
}
|
||||
/** @type {number} */
|
||||
var byteRangePos = pdfstr.indexOf(byteRangePlaceholder);
|
||||
/** @type {number} */
|
||||
var byteRangeEnd = byteRangePos + byteRangePlaceholder.length;
|
||||
/** @type {number} */
|
||||
var contentsTagPos = pdfstr.indexOf('/Contents ', byteRangeEnd);
|
||||
/** @type {number} */
|
||||
var placeholderPos = pdfstr.indexOf('<', contentsTagPos);
|
||||
/** @type {number} */
|
||||
var placeholderEnd = pdfstr.indexOf('>', placeholderPos);
|
||||
/** @type {number} */
|
||||
var placeholderLengthWithBrackets = placeholderEnd + 1 - placeholderPos;
|
||||
/** @type {number} */
|
||||
var placeholderLength = placeholderLengthWithBrackets - 2;
|
||||
/** @type {Array<number>} */
|
||||
var byteRange = [0, 0, 0, 0];
|
||||
byteRange[1] = placeholderPos;
|
||||
byteRange[2] = byteRange[1] + placeholderLengthWithBrackets;
|
||||
byteRange[3] = pdfstr.length - byteRange[2];
|
||||
/** @type {string} */
|
||||
var actualByteRange = "/ByteRange [" + byteRange.join(" ") +"]";
|
||||
actualByteRange += ' '.repeat(byteRangePlaceholder.length - actualByteRange.length);
|
||||
// Replace the /ByteRange placeholder with the actual ByteRange
|
||||
|
@ -316,20 +327,26 @@ z.PdfSigner = class{
|
|||
this.opt.p12cert = z.u8arrToRaw(new Uint8Array(this.opt.p12cert));
|
||||
}
|
||||
// Convert Buffer P12 to a forge implementation.
|
||||
/** @type {forge.asn1} */
|
||||
var p12Asn1 = forge.asn1.fromDer(this.opt.p12cert);
|
||||
/** @type {forge.pkcs12} */
|
||||
var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, true, this.opt.pwd);
|
||||
|
||||
// Extract safe bags by type.
|
||||
// We will need all the certificates and the private key.
|
||||
/** @type {Object<string|number, P12Bag>} */
|
||||
var certBags = p12.getBags({
|
||||
"bagType": forge.pki.oids.certBag,
|
||||
})[forge.pki.oids.certBag];
|
||||
/** @type {Object<string|number, P12Bag>} */
|
||||
var keyBags = p12.getBags({
|
||||
"bagType": forge.pki.oids.pkcs8ShroudedKeyBag,
|
||||
})[forge.pki.oids.pkcs8ShroudedKeyBag];
|
||||
|
||||
/** @type {forge_key} */
|
||||
var privateKey = keyBags[0].key;
|
||||
// Here comes the actual PKCS#7 signing.
|
||||
/** @type {forge.pkcs7} */
|
||||
var p7 = forge.pkcs7.createSignedData();
|
||||
// Start off by setting the content.
|
||||
p7.content = forge.util.createBuffer(pdfstr);
|
||||
|
@ -337,18 +354,22 @@ z.PdfSigner = class{
|
|||
// Then add all the certificates (-cacerts & -clcerts)
|
||||
// Keep track of the last found client certificate.
|
||||
// This will be the public key that will be bundled in the signature.
|
||||
/** @type {forge_cert} */
|
||||
var cert = null;
|
||||
Object.keys(certBags).forEach(function(a_ele){
|
||||
var a_cert = certBags[a_ele].cert;
|
||||
if(certBags){
|
||||
Object.keys(certBags).forEach(function(a_ele){
|
||||
/** @type {forge_cert} */
|
||||
var a_cert = certBags[a_ele].cert;
|
||||
|
||||
p7.addCertificate(a_cert);
|
||||
p7.addCertificate(a_cert);
|
||||
|
||||
// Try to find the certificate that matches the private key.
|
||||
if(privateKey.n.compareTo(a_cert.publicKey.n) === 0
|
||||
&& privateKey.e.compareTo(a_cert.publicKey.e) === 0){
|
||||
cert = a_cert;
|
||||
}
|
||||
});
|
||||
// Try to find the certificate that matches the private key.
|
||||
if(privateKey.n.compareTo(a_cert.publicKey.n) === 0
|
||||
&& privateKey.e.compareTo(a_cert.publicKey.e) === 0){
|
||||
cert = a_cert;
|
||||
}
|
||||
});
|
||||
}
|
||||
if(cert){
|
||||
// When converting to asn1, forge will encode the value of issuer to utf8 if the valueTagClass is UTF8.
|
||||
// But the value load from pfx is already utf8 encoded, so the encoding action will break the final signature.
|
||||
|
@ -389,6 +410,7 @@ z.PdfSigner = class{
|
|||
p7.sign({"detached": true});
|
||||
|
||||
if(this.tsainf){
|
||||
/** @type {forge.asn1} */
|
||||
var tsatoken = this.queryTsa(p7.signers[0].signature);
|
||||
p7.signerInfos[0].value[6].value[0].value[1] = forge.asn1.create(
|
||||
forge.asn1.Class.UNIVERSAL,
|
||||
|
@ -400,6 +422,7 @@ z.PdfSigner = class{
|
|||
}
|
||||
|
||||
// Check if the PDF has a good enough placeholder to fit the signature.
|
||||
/** @type {string} */
|
||||
var sighex = forge.asn1.toDer(p7.toAsn1()).toHex();
|
||||
// placeholderLength represents the length of the HEXified symbols but we're
|
||||
// checking the actual lengths.
|
||||
|
@ -425,6 +448,7 @@ z.PdfSigner = class{
|
|||
*/
|
||||
convToPDFString(str){
|
||||
// Check if there is a multi-bytes char in the string.
|
||||
/** @type {boolean} */
|
||||
var flg = false;
|
||||
for(var i=0; i<str.length; i++){
|
||||
if(str.charCodeAt(i) > 0xFF){
|
||||
|
@ -441,14 +465,16 @@ z.PdfSigner = class{
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} signature
|
||||
* @param {string=} signature
|
||||
* @return {string}
|
||||
*/
|
||||
genTsrData(signature){
|
||||
// Generate SHA256 hash from signature content for TSA
|
||||
/** @type {forge.md.digest} */
|
||||
var md = forge.md.sha256.create();
|
||||
md.update(signature);
|
||||
// Generate TSA request
|
||||
/** @type {forge.asn1} */
|
||||
var asn1Req = forge.asn1.create(
|
||||
forge.asn1.Class.UNIVERSAL,
|
||||
forge.asn1.Type.SEQUENCE,
|
||||
|
@ -511,19 +537,25 @@ z.PdfSigner = class{
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} signature
|
||||
* @return {Object}
|
||||
* @param {string=} signature
|
||||
* @return {forge.asn1}
|
||||
*/
|
||||
queryTsa(signature){
|
||||
/** @type {string} */
|
||||
var tsr = this.genTsrData(signature);
|
||||
/** @type {Uint8Array} */
|
||||
var tu8s = z.rawToU8arr(tsr);
|
||||
/** @type {UrlFetchParams} */
|
||||
var options = {
|
||||
"method": "POST",
|
||||
"headers": {"Content-Type": "application/timestamp-query"},
|
||||
"payload": tu8s,
|
||||
};
|
||||
/** @type {GBlob} */
|
||||
var tblob = UrlFetchApp.fetch(this.tsainf.url, options).getBlob();
|
||||
/** @type {string} */
|
||||
var tstr = z.u8arrToRaw(new Uint8Array(tblob.getBytes()));
|
||||
/** @type {forge.asn1} */
|
||||
var token = forge.asn1.fromDer(tstr).value[1];
|
||||
return token;
|
||||
}
|
||||
|
@ -541,7 +573,6 @@ z.PdfSigner = class{
|
|||
|
||||
z.VisualSignature = class{
|
||||
/**
|
||||
* @constructor
|
||||
* @param {SignDrawInfo=} drawinf
|
||||
*/
|
||||
constructor(drawinf){
|
||||
|
@ -549,7 +580,7 @@ z.VisualSignature = class{
|
|||
this.pgidx = 0;
|
||||
/** @private @type {Array<number>} */
|
||||
this.rect = [0, 0, 0, 0];
|
||||
/** @private @type {SignDrawInfo} */
|
||||
/** @private @type {?SignDrawInfo} */
|
||||
this.drawinf = null;
|
||||
|
||||
if(drawinf){
|
||||
|
@ -598,21 +629,29 @@ z.VisualSignature = class{
|
|||
}else{
|
||||
throw new Error("Page index is overflow to pdf pages.");
|
||||
}
|
||||
/** @type {PDFLib.Rotation} */
|
||||
var pgrot = page.getRotation();
|
||||
pgrot.angle = PDFLib.toDegrees(pgrot) % 360;
|
||||
pgrot.type = PDFLib.RotationTypes.Degrees;
|
||||
/** @type {PdfSize} */
|
||||
var pgsz = page.getSize();
|
||||
/** @type {SignAreaInfo} */
|
||||
var areainf = this.calcAreaInf(pgsz, pgrot.angle, this.drawinf.area);
|
||||
|
||||
// resources object
|
||||
/** @type {Object<string, *>} */
|
||||
var rscObj = {};
|
||||
/** @type {Array<PDFLib.PDFOperator>} */
|
||||
var sigOprs = [];
|
||||
/** @type {string} */
|
||||
var imgName = signame ? signame.concat("Img") : "SigImg";
|
||||
/** @type {string} */
|
||||
var fontName = signame ? signame.concat("Font") : "SigFont";
|
||||
if(this.drawinf.img){
|
||||
// Get scaled image size
|
||||
/** @type {PdfSize} */
|
||||
var imgsz = this.drawinf.img.size();
|
||||
/** @type {number} */
|
||||
var tmp = areainf.w * imgsz.height / imgsz.width;
|
||||
if(tmp <= areainf.h){
|
||||
areainf.h = tmp;
|
||||
|
@ -633,6 +672,7 @@ z.VisualSignature = class{
|
|||
|
||||
this.rect = this.calcRect(pgrot.angle, areainf);
|
||||
|
||||
/** @type {PDFLib.PDFObject} */
|
||||
var frmDict = pdfdoc.context.obj({
|
||||
"Type": "XObject",
|
||||
"Subtype": "Form",
|
||||
|
@ -640,6 +680,7 @@ z.VisualSignature = class{
|
|||
"BBox": [0, 0, areainf.w, areainf.h],
|
||||
"Resources": rscObj,
|
||||
});
|
||||
/** @type {PDFLib.PDFContentStream} */
|
||||
var strm = PDFLib.PDFContentStream.of(frmDict, sigOprs, false);
|
||||
return pdfdoc.context.register(strm);
|
||||
}
|
||||
|
@ -648,13 +689,13 @@ z.VisualSignature = class{
|
|||
* Calculate area informations for drawing signature after rotate
|
||||
*
|
||||
* @private
|
||||
* @param {Object<string, number>} pgsz // { width, height }
|
||||
* @param {PdfSize} pgsz
|
||||
* @param {number} angle
|
||||
* @param {SignAreaInfo} visinf
|
||||
* @return {SignAreaInfo}
|
||||
*/
|
||||
calcAreaInf(pgsz, angle, visinf){
|
||||
var ret = Object.assign({}, visinf);
|
||||
var ret = /** @type {SignAreaInfo} */(Object.assign({}, visinf));
|
||||
// Calculate position after rotate
|
||||
switch(angle){
|
||||
case 90:
|
||||
|
@ -688,6 +729,7 @@ z.VisualSignature = class{
|
|||
* @return {Array<number>}
|
||||
*/
|
||||
calcRect(angle, areainf){
|
||||
/** @type {Array<number>} */
|
||||
var rect = [0, 0, 0, 0];
|
||||
rect[0] = areainf.x;
|
||||
rect[1] = areainf.y;
|
||||
|
@ -719,9 +761,10 @@ z.VisualSignature = class{
|
|||
* @private
|
||||
* @param {PDFLib.Rotation} rot
|
||||
* @param {SignAreaInfo} areainf // { x, y, w, h }
|
||||
* @return {Object<string, *>} // { x, y, width, height, rotate, xSkew, ySkew }
|
||||
* @return {PdfDrawimgOption}
|
||||
*/
|
||||
calcDrawImgInf(rot, areainf){
|
||||
/** @type {PdfDrawimgOption} */
|
||||
var ret = {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
|
|
Loading…
Reference in New Issue