Made js files to compiled by closure compiler.

pull/2/head 2.0.0
zboris12 2022-10-04 21:37:17 +09:00
parent 8c2a614a08
commit c4e5dafa17
7 changed files with 836 additions and 52 deletions

16
closure/build.bat Normal file
View File

@ -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%

319
closure/forge-ext.js Normal file
View File

@ -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) {};

50
closure/google-ext.js Normal file
View File

@ -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(){};

265
closure/pdflib-ext.js Normal file
View File

@ -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){};

View File

@ -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){};

View File

@ -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++){

View File

@ -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,