zgapdfsigner/lib/zgacertsutil.js

1020 lines
23 KiB
JavaScript

'use strict';
/**
* @param {Object<string, *>} z
*/
function supplyZgaCertsChain(z){
//Only for nodejs Start//
if(z.forge){
var forge = z.forge;
}
//Only for nodejs End//
/**
* When converting the issuer of signature to asn1, forge will encode the
* value of issuer to utf8 if the valueTagClass is UTF8.
* But the value load from a file which is DER format, is already utf8 encoded,
* so the encoding action will break the final data.
* To avoid the broken data issue, we decode the value before the later actions.
* @param {forge_cert} cert
*/
z.fixCertAttributes = function(cert){
cert.issuer.attributes.forEach(function(a_ele){
if(a_ele.valueTagClass === forge.asn1.Type.UTF8){
a_ele.value = forge.util.decodeUtf8(a_ele.value);
}
});
};
/**
* @param {forge.asn1|string} asnder
* @return {forge_cert}
*/
z.loadCert = function(asnder){
/** @type {forge.asn1} */
var asn1 = null;
if(typeof asnder === "string"){
asn1 = forge.asn1.fromDer(asnder);
}else{
asn1 = asnder;
}
/** @type {forge_cert} */
var cert = forge.pki.certificateFromAsn1(asn1);
return cert;
};
/**
* @param {string} oid
* @return {string}
*/
z.oidToDstr = function(oid){
return forge.asn1.oidToDer(oid).getBytes();
};
/**
* @param {forge.asn1} asn1
* @param {Object<string, *>} vadt
* @param {string|Array<string>=} oid
* @return {Object<string, *>}
*/
z.parseAsn1 = function(asn1, vadt, oid){
/** @type {Object<string, *>} */
var capt = {};
/** @type {Array<string>} */
var errs = [];
forge.asn1.validate(asn1, vadt, capt, errs);
if(errs.length > 0){
// console.log(errs);
return null;
}else if(oid){
if(capt.oid){
if(Array.isArray(oid)){
if(oid.indexOf(capt.oid) >= 0){
return capt;
}else{
return null;
}
}else if(oid == capt.oid){
return capt;
}else{
return null;
}
}else{
return null;
}
}else{
return capt;
}
};
/**
* @param {string|number|boolean|forge.asn1|Array<forge.asn1>} aval
* @param {number=} atyp
* @param {number=} atag
* @return {forge.asn1}
*/
z.createAsn1 = function(aval, atyp, atag){
/** @lends {forge.asn1} */
const asn1 = forge.asn1;
/** @lends {forge.asn1.Class} */
const asnc = asn1.Class;
/** @lends {forge.asn1.Type} */
const asnt = asn1.Type;
/** @type {string|number|forge.asn1|Array<forge.asn1>} */
var a_val = null;
/** @type {number} */
var a_typ = (atyp || atyp === asnt.NONE) ? atyp : -1;
/** @type {boolean} */
var a_con = false;
if(Array.isArray(aval)){
a_con = true;
}else{
switch(typeof aval){
case "string":
if(a_typ == asnt.OID){
a_val = asn1.oidToDer(aval).getBytes();
}else if(a_typ < 0){
a_typ = asnt.OCTETSTRING;
}
break;
case "number":
a_val = asn1.integerToDer(aval).getBytes();
if(a_typ < 0){
a_typ = asnt.INTEGER;
}
break;
case "boolean":
if(aval){
a_val = 1;
}else{
a_val = 0;
}
if(a_typ < 0){
a_typ = asnt.BOOLEAN;
}
}
}
if(a_typ < 0){
a_typ = asnt.SEQUENCE;
}
if(!a_val && a_val !== 0){
a_val = /** @type {Array|forge.asn1|number|string} */(aval);
}
return asn1.create(atag ? atag : asnc.UNIVERSAL, a_typ, a_con, a_val);
};
/**
* @param {string} url
* @param {forge.asn1} asn1Req
* @param {Object<string, *>} headers
* @return {Promise<Uint8Array>}
*/
z.queryAsn1 = async function(url, asn1Req, headers){
/** @type {string} */
var tsr = forge.asn1.toDer(asn1Req).getBytes();
/** @type {Uint8Array} */
var tu8s = z.rawToU8arr(tsr);
/** @type {UrlFetchParams} */
var options = {
"method": "POST",
"headers": headers,
"payload": tu8s,
};
/** @type {Uint8Array} */
var tesp = await z.urlFetch(url, options);
// /** @type {string} */
// var tstr = z.u8arrToRaw(tesp);
return tesp;
};
/**
* @param {forge_cert} cert1
* @param {forge_cert} cert2
* @return {boolean}
*/
z.sameCert = function(cert1, cert2){
/** @type {forge_cert_issuer} */
var c1 = cert1.subject;
/** @type {forge_cert_issuer} */
var c2 = cert2.subject;
if(c1.attributes.length === c2.attributes.length) {
// all attributes are the same so issuer matches subject
/** @type {?forge_cert_attr} */
var attr1 = null;
/** @type {?forge_cert_attr} */
var attr2 = null;
for(var n = 0; n < c1.attributes.length; n++) {
attr1 = c1.attributes[n];
attr2 = c2.attributes[n];
if(attr1.type !== attr2.type || attr1.value !== attr2.value){
// attribute mismatch
return false;
}
}
return true;
}else{
return false;
}
};
z.CertsChain = class{
/**
* @param {Array<forge_cert|forge.asn1|string>=} certs
*/
constructor(certs){
/** @private @lends {forge.asn1} */
this.asn1 = forge.asn1;
/** @private @lends {forge.asn1.Class} */
this.asnc = forge.asn1.Class;
/** @private @lends {forge.asn1.Type} */
this.asnt = forge.asn1.Type;
/** @private @const {string} */
this.ocsp_oid = z.oidToDstr("1.3.6.1.5.5.7.48.1");
/** @private @const {string} */
this.issuer_oid = z.oidToDstr("1.3.6.1.5.5.7.48.2");
/** @private @const {string} */
this.ocspBasic_oid = z.oidToDstr("1.3.6.1.5.5.7.48.1.1");
/** @private @const {Object<string, *>} */
this.oidval_validator = {
name: "Seq",
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.SEQUENCE,
constructed: true,
value: [{
name: "Oid",
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.OID,
constructed: false,
capture: "oid",
}, {
name: "Ovalue",
tagClass: this.asnc.CONTEXT_SPECIFIC,
type: 6,
constructed: false,
capture: "oval",
}],
};
/** @private @const {Object<string, *>} */
this.oresp_validator = {
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.SEQUENCE,
constructed: true,
value: [{
name: "Status",
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.ENUMERATED,
constructed: false,
capture: "status",
}, {
tagClass: this.asnc.CONTEXT_SPECIFIC,
type: 0,
constructed: true,
value: [{
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.SEQUENCE,
constructed: true,
value: [{
name: "Oid",
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.OID,
constructed: false,
capture: "oid",
}, {
name: "OcspBasic",
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.OCTETSTRING,
constructed: false,
capture: "ob",
}],
}],
}],
};
/** @private @const {Object<string, *>} */
this.ob_validator = {
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.SEQUENCE,
constructed: true,
value: [{
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.SEQUENCE,
constructed: true,
}, {
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.SEQUENCE,
constructed: true,
}, {
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.BITSTRING,
constructed: false,
}, {
tagClass: this.asnc.CONTEXT_SPECIFIC,
type: 0,
constructed: true,
optional: true,
value: [{
name: "Certs",
tagClass: this.asnc.UNIVERSAL,
type: this.asnt.SEQUENCE,
constructed: true,
capture: "certs",
}],
}],
};
/** @private @type {Array<forge_cert>} */
this.certs = null;
/** @private @type {forge_cert} */
this.rootCert = null;
/** @private @type {Array<string>} */
this.crls = null;
/** @private @type {Array<OcspData>} */
this.ocspDatas = null;
/** @private @type {Array<z.CertsChain>} */
this.extraChains = null;
/** @private @type {boolean} */
this.ocspOk = false;
if(certs){
this.setCerts(certs);
}
}
/**
* @public
* @param {Array<forge_cert|forge.asn1|string>} certs
*/
setCerts(certs){
/** @type {z.CertsChain} */
var _this = this;
/** @type {Array<forge_cert>} */
var fcertarr = [];
_this.certs = [];
/** @type {forge_cert} */
var wkcert = null;
certs.forEach(function(/** @type {forge_cert|forge.asn1|string} */a_data){
if(a_data.issuer){
wkcert = /** @type {forge_cert} */(a_data);
}else{
wkcert = z.loadCert(/** @type {forge.asn1|string} */(a_data));
}
if(wkcert.isIssuer(wkcert)){
// A selfSigned cert is a root cert.
_this.rootCert = wkcert;
}else{
/** @type {forge_cert_extension} */
var bext = wkcert.getExtension("basicConstraints");
if(bext && bext.cA){
fcertarr.push(wkcert);
}else{
_this.certs.push(wkcert);
}
}
});
/** @type {number} */
var cnt = fcertarr.length;
if(_this.certs.length == 1){
wkcert = _this.certs[0];
while(cnt > 0){
for(var j=0; j<fcertarr.length; j++){
if(fcertarr[j] && wkcert.isIssuer(fcertarr[j])){
wkcert = fcertarr[j];
_this.certs.push(wkcert);
fcertarr[j] = null;
cnt--;
}
}
}
}else if(cnt > 0){
_this.certs.push(fcertarr.pop());
cnt--;
while(cnt > 0){
for(var j=0; j<fcertarr.length; j++){
if(fcertarr[j]){
for(var k=0; k<_this.certs.length; k++){
wkcert = _this.certs[k];
if(wkcert.isIssuer(fcertarr[j])){
_this.certs.splice(k+1, 0, fcertarr[j]);
fcertarr[j] = null;
cnt--;
break;
}else if(fcertarr[j].isIssuer(wkcert)){
_this.certs.splice(k, 0, fcertarr[j]);
fcertarr[j] = null;
cnt--;
break;
}
}
}
}
}
}
}
/**
* @public
* @return {forge_cert}
*/
getSignCert(){
if(this.certs.length > 0){
return this.certs[0];
}else{
return this.rootCert;
}
}
/**
* @public
* @return {boolean}
*/
isSelfSignedCert(){
return (this.certs.length == 0);
}
/**
* @public
* @return {Array<forge_cert>}
*/
getAllCerts(){
/** @type {Array<forge_cert>} */
var ret = [].concat(this.certs);
if(this.rootCert){
ret.push(this.rootCert);
}
return ret;
}
/**
* @public
* @param {forge_cert} cert
* @return {boolean}
*/
isCertInChain(cert){
return this.isCertInArray(this.getAllCerts(), cert);
}
/**
* @public
* @param {forge_cert} cert
* @return {Promise<boolean>}
*/
async buildChain(cert){
/** @type {z.CertsChain} */
var _this = this;
if(cert.isIssuer(cert)){
_this.certs = [];
_this.rootCert = cert;
}else{
_this.certs = [cert];
_this.rootCert = null;
}
return /** @type {boolean} */(await _this.amendRootCert());
}
/**
* @public
* @param {boolean=} crlOnly
* @return {Promise<DSSInfo>}
*/
async prepareDSSInf(crlOnly){
/** @type {z.CertsChain} */
var _this = this;
var flg = /** @type {boolean} */(await _this.amendRootCert());
if(!flg){
throw new Error("Can't prepare DSS infomation because of unable to find the root certificate.");
}
if(crlOnly){
flg = false;
}else{
_this.ocspDatas = [];
_this.extraChains = [];
flg = await _this.checkAllOcsps(_this.extraChains);
}
/** @type {Array<Uint8Array>} */
var ocsps = [];
/** @type {Array<forge_cert>} */
var certs = [];
if(flg){
_this.ocspDatas.forEach(function(/** @type {OcspData} */a_dat){
ocsps.push(a_dat.resp);
});
_this.extraChains.forEach(function(/** @type {z.CertsChain} */a_chain){
a_chain.ocspDatas.forEach(function(/** @type {OcspData} */b_dat){
ocsps.push(b_dat.resp);
});
a_chain.certs.forEach(function(/** @type {forge_cert} */b_cert){
if(!(_this.isCertInArray(_this.certs, b_cert) || _this.isCertInArray(certs, b_cert))){
certs.push(b_cert);
}
});
});
}
/** @type {Array<Uint8Array>} */
var crls = [];
if(!flg){
_this.crls = [];
for(var i=0; i<_this.certs.length; i++){
/** @type {forge.asn1} */
var cdpts = _this.getExtAsn1(_this.certs[i], "cRLDistributionPoints"); //"2.5.29.31"
if(cdpts){
_this.findCrls(cdpts);
}
}
for(var i=0; i<_this.crls.length; i++){
z.log("Query crl for [" + _this.crls[i] + "]");
/** @type {Uint8Array} */
var crl = await z.urlFetch(_this.crls[i]);
if(crl){
crls.push(crl);
}
}
}
/** @type {DSSInfo} */
var ret = {};
if(certs.length > 0){
ret.certs = certs;
}
if(ocsps.length > 0){
ret.ocsps = ocsps;
}
if(crls.length > 0){
ret.crls = crls;
}
return ret;
}
/**
* @private
* @return {Promise<!boolean>}
*/
async amendRootCert(){
while(!this.rootCert){
/** @type {forge_cert} */
var cert = await this.queryIssuerCert(-1);
if(!cert){
return false;
}
}
return true;
}
/**
* @private
* @param {forge_cert|number} certIdx
* @return {Promise<forge_cert>}
*/
async queryIssuerCert(certIdx){
/** @type {z.CertsChain} */
var _this = this;
/** @type {forge_cert} */
var cert = null;
if(typeof certIdx === "number"){
if(certIdx < 0){
cert = _this.certs[_this.certs.length - 1];
}else{
cert = _this.certs[certIdx];
}
}else{
cert = /** @type {forge_cert} */(certIdx);
}
/** @type {forge.asn1} */
var aiass = _this.getExtAsn1(cert, "authorityInfoAccess");
if(!aiass){
return null;
}
/** @type {string} */
var issuerUrl = _this.findOidValue(aiass, _this.issuer_oid);
if(!issuerUrl){
return null;
}
z.log("Query certificate of [" + issuerUrl + "]");
/** @type {Uint8Array} */
var u8cert = await z.urlFetch(issuerUrl);
if(!u8cert){
return null;
}
cert = z.loadCert(z.u8arrToRaw(u8cert));
if(typeof certIdx === "number"){
if(cert.isIssuer(cert)){
_this.rootCert = cert;
}else if(certIdx < 0){
_this.certs.push(cert);
}else{
_this.certs[certIdx + 1] = cert;
}
}
return cert;
}
/**
* @private
* @param {Array<z.CertsChain>} xchains
* @return {Promise<boolean>}
*/
async checkAllOcsps(xchains){
/** @type {z.CertsChain} */
var _this = this;
/** @type {number} */
var i = 0;
/** @type {boolean} */
var ret = (_this.certs.length > 0);
for(i=0; i<_this.certs.length; i++){
if(!(await _this.queryOcsp(i, xchains))){
ret = false;
break;
}
}
_this.ocspOk = ret;
return ret;
}
/**
* @private
* @param {number} idx
* @param {Array<z.CertsChain>} xchains
* @return {Promise<boolean>}
*/
async queryOcsp(idx, xchains){
/** @type {z.CertsChain} */
var _this = this;
/** @type {forge_cert} */
var cert = _this.certs[idx];
z.log("Query ocsp for [" + cert.subject.getField("CN").value + "]");
/** @type {string} */
var ocspUrl = "";
/** @type {forge.asn1} */
var aiass = _this.getExtAsn1(cert, "authorityInfoAccess"); //"1.3.6.1.5.5.7.1.1"
if(aiass){
ocspUrl = _this.findOidValue(aiass, _this.ocsp_oid);
}
if(!ocspUrl){
z.log("Can't find the url of ocsp.");
return false;
}
/** @type {string} */
var serialNum = z.u8arrToRaw(forge.util.binary.hex.decode(cert.serialNumber));
/** @type {number} */
var pidx = idx + 1;
/** @type {forge_cert} *///parent cert(issuer cert)
var pcert = pidx < _this.certs.length ? _this.certs[pidx] : _this.rootCert;
/** @type {forge.asn1} */
var subjectAsn1 = forge.pki.distinguishedNameToAsn1(pcert.subject);
/** @type {forge.asn1} */
var publicKeyAsn1 = forge.pki.publicKeyToRSAPublicKey(pcert.publicKey);
/** @type {string} */
var dnsha1 = _this.sha1(subjectAsn1);
/** @type {string} */
var keysha1 = _this.sha1(publicKeyAsn1);
/** @type {string} */
var nonce = forge.random.getBytesSync(16);
nonce = _this.asn1.toDer(z.createAsn1(nonce)).getBytes();
/** @type {forge.asn1} */
var asn1Req = z.createAsn1([
z.createAsn1([
z.createAsn1([
z.createAsn1([
z.createAsn1([
z.createAsn1([
z.createAsn1(forge.oids.sha1, _this.asnt.OID),
z.createAsn1("", _this.asnt.NULL),
]),
z.createAsn1(dnsha1),
z.createAsn1(keysha1),
z.createAsn1(serialNum, _this.asnt.INTEGER),
])
])
]),
z.createAsn1([
z.createAsn1([
z.createAsn1([
z.createAsn1("1.3.6.1.5.5.7.48.1.2", _this.asnt.OID), //OCSP Nonce
z.createAsn1(nonce),
])
])
], 2, _this.asnc.CONTEXT_SPECIFIC)
])
]);
/** @type {Object<string, *>} */
var hds = {
"Content-Type": "application/ocsp-request",
};
/** @type {Uint8Array} */
var ou8arr = await z.queryAsn1(ocspUrl, asn1Req, hds);
// console.log(forge.util.createBuffer(ou8arr).toHex());
/** @type {forge.asn1} */
var asn1Oresp = _this.asn1.fromDer(z.u8arrToRaw(ou8arr));
/** @type {Object<string, *>} */
var ocapt = z.parseAsn1(asn1Oresp, _this.oresp_validator, _this.ocspBasic_oid);
if(ocapt){
/** @type {number} */
var respsts = ocapt.status.charCodeAt(0);
if(respsts != 0){
/** @type {string} */
var msg = "ocsp response is not successful. ";
switch(respsts){
case 1:
msg += "malformedRequest";
break;
case 2:
msg += "internalError";
break;
case 3:
msg += "tryLater";
break;
case 5:
msg += "sigRequired";
break;
case 6:
msg += "unauthorized";
break;
default:
msg += "unknown error";
}
msg += "(" + respsts + ")";
z.log(msg);
return false;
}
}else{
z.log("ocsp response is an unknown format.");
return false;
}
if(ocapt.ob){
/** @type {forge.asn1} */
var asn1Obasic = _this.asn1.fromDer(ocapt.ob);
/** @type {Object<string, *>} */
var obcapt = z.parseAsn1(asn1Obasic, _this.ob_validator);
if(obcapt){
_this.ocspDatas[idx] = {
resp: ou8arr,
};
if(obcapt.certs){
/** @type {z.CertsChain} */
var xchain = new z.CertsChain(obcapt.certs);
/** @type {number} */
var i = 0;
for(i=0; i<xchains.length; i++){
if(xchains[i].isCertInChain(xchain.getSignCert())){
xchain = null;
break;
}
}
_this.ocspDatas[idx].cchainIdx = i;
if(xchain){
/** @type {boolean} */
var ocspNoCheck = true;
xchain.certs.forEach(function(/** @type {forge_cert} */a_cert){
if(ocspNoCheck && !a_cert.getExtension({id: "1.3.6.1.5.5.7.48.1.5"})){
ocspNoCheck = false;
}
});
if(ocspNoCheck){
xchain.ocspOk = true;
}else{
xchains.push(xchain);
await xchain.amendRootCert();
await xchain.checkAllOcsps(xchains);
}
}else{
xchain = xchains[i];
}
return xchain.ocspOk;
}else{
return true;
}
}else{
z.log("ocsp basic is an unknown format.");
return false;
}
}else{
z.log("There is no ocsp basic in ocsp response.");
return false;
}
}
/**
* @private
* @param {forge_cert} cert
* @param {string|forge_cert_extension} nm
* @return {forge.asn1}
*/
getExtAsn1(cert, nm){
/** @type {forge_cert_extension} */
var ext = cert.getExtension(nm);
if(ext){
return this.asn1.fromDer(/** @type {string} */(ext.value));
}else{
return null;
}
}
/**
* @private
* @param {forge.asn1} asn1
*/
findCrls(asn1){
/** @type {z.CertsChain} */
var _this = this;
if(Array.isArray(asn1.value)){
asn1.value.forEach(function(/** @type {forge.asn1} */a_asn1){
_this.findCrls(a_asn1);
});
}else{
var crl = /** @type {string} */(asn1.value);
if(_this.crls.indexOf(crl) < 0){
_this.crls.push(crl);
}
}
}
/**
* @private
* @param {forge.asn1} asn1
* @param {string} oid
* @return {string}
*/
findOidValue(asn1, oid){
/** @type {z.CertsChain} */
var _this = this;
/** @type {Object<string, *>} */
var capt = z.parseAsn1(asn1, _this.oidval_validator, oid);
if(capt && capt.oval){
return capt.oval;
}
var oval = "";
if(Array.isArray(asn1.value)){
for(var i=0; i<asn1.value.length; i++){
oval = _this.findOidValue(asn1.value[i], oid);
if(oval){
break;
}
}
}
return oval;
}
/**
* @private
* @param {forge.asn1} asn1
* @return {string}
*/
sha1(asn1){
var sha = forge.md.sha1.create();
sha.update(this.asn1.toDer(asn1).getBytes());
return sha.digest().getBytes();
}
/**
* @private
* @param {Array<forge_cert>} certs
* @param {forge_cert} cert
* @return {boolean}
*/
isCertInArray(certs, cert){
/** @type {number} */
var i = 0;
for(i=0; i<certs.length; i++){
if(z.sameCert(certs[i], cert)){
return true;
}
}
return false;
}
}
z.TsaFetcher = class{
/**
* @param {TsaServiceInfo} inf
*/
constructor(inf){
/** @private @lends {forge.asn1} */
this.asn1 = forge.asn1;
/** @private @lends {forge.asn1.Class} */
this.asnc = forge.asn1.Class;
/** @private @lends {forge.asn1.Type} */
this.asnt = forge.asn1.Type;
/** @public @type {string} */
this.url = inf.url;
/** @public @type {number} */
this.len = inf.len ? inf.len : 0;
/** @private @type {Object<string, *>|undefined} */
this.headers = inf.headers;
/** @private @type {forge.asn1} */
this.respAsn1 = null;
}
/**
* @public
* @param {string=} data
* @return {Promise<string>} Error message
*/
async queryTsa(data){
/** @type {z.TsaFetcher} */
var _this = this;
// Generate SHA256 hash from data for TSA
/** @type {forge.md.digest} */
var md = forge.md.sha256.create();
md.update(data);
// Generate TSA request
/** @type {forge.asn1} */
var asn1Req = z.createAsn1([
// Version
z.createAsn1(1),
z.createAsn1([
z.createAsn1([
z.createAsn1(forge.oids.sha256, _this.asnt.OID),
z.createAsn1("", _this.asnt.NULL),
]),
// Message imprint
z.createAsn1(md.digest().getBytes()),
]),
// Get REQ certificates
z.createAsn1(true),
]);
/** @type {Object<string, *>} */
var hds = _this.headers ? _this.headers : {};
if(!hds["Content-Type"]){
hds["Content-Type"] = "application/timestamp-query";
}
/** @type {Uint8Array} */
var tu8arr = await z.queryAsn1(_this.url, asn1Req, hds);
/** @type {string} */
var tstr = z.u8arrToRaw(tu8arr);
// console.log(forge.util.createBuffer(tstr).toHex());
_this.respAsn1 = _this.asn1.fromDer(tstr);
/** @type {string} */
var respsts = _this.respAsn1.value[0].value[0].value;
if(respsts == "\x00"){
return "";
}else{
/** @type {forge.asn1} */
var msgAsn1 = _this.respAsn1.value[0].value[1].value[0];
var msg = /** @type {string} */(msgAsn1.value);
if(msgAsn1.type == _this.asnt.UTF8){
msg = forge.util.decodeUtf8(msg);
}
return msg + "(" + respsts.charCodeAt(0) + ")";
}
}
/**
* @public
* @param {boolean=} forP7
* @return {forge.asn1}
*/
getToken(forP7){
/** @type {z.TsaFetcher} */
var _this = this;
/** @type {forge.asn1} */
var token = _this.respAsn1.value[1];
if(forP7){
// create the asn1 to append to the p7 signature
return z.createAsn1([
z.createAsn1([
// Attribute Type (forge.pki.oids.timeStampToken)
z.createAsn1("1.2.840.113549.1.9.16.2.14", _this.asnt.OID),
// Attribute Value
z.createAsn1([token], _this.asnt.SET),
]),
], 1, _this.asnc.CONTEXT_SPECIFIC);
}else{
return token;
}
}
/**
* @public
* @return {z.CertsChain}
*/
getCertsChain(){
/** @type {z.TsaFetcher} */
var _this = this;
if(!_this.respAsn1){
throw new Error("You must query tsa first.");
}
var tsdats = /** @type {Array<forge.asn1>} */(_this.respAsn1.value[1].value[1].value[0].value);
// Get all certs in tsa token.
/** @type {Array<forge.asn1>} */
var certAsn1s = null;
for(var i=3; i<tsdats.length; i++){
/** @type {forge.asn1} */
var tsdat = tsdats[i];
/** @type {Object<string, *>} */
var capt = z.parseAsn1(tsdat, {
name: "Certs",
tagClass: _this.asnc.CONTEXT_SPECIFIC,
type: _this.asnt.NONE,
constructed: true,
capture: "certs",
});
if(capt){
certAsn1s = capt.certs;
break;
}
}
if(certAsn1s){
return new z.CertsChain(certAsn1s);
}else{
return null;
}
}
};
}
//Only for nodejs Start//
if(typeof exports === "object" && typeof module !== "undefined"){
module.exports = supplyZgaCertsChain;
}
//Only for nodejs End//