mirror of
https://gitee.com/Donal/ofd.js.git
synced 2024-12-02 03:48:44 +08:00
兼容签章版本号异常的情况
This commit is contained in:
parent
84444b9424
commit
0edffef713
@ -69,59 +69,59 @@
|
||||
<p class="content-title">签章信息</p>
|
||||
<div class="subcontent">
|
||||
<span class="title">签章人</span>
|
||||
<span class="value" id="spSigner">Signer</span>
|
||||
<span class="value" id="spSigner">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">签章提供者</span>
|
||||
<span class="value" id="spProvider">Provider</span>
|
||||
<span class="value" id="spProvider">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">原文摘要值</span>
|
||||
<span class="value" id="spHashedValue" @click="showMore('原文摘要值', 'spHashedValue')"
|
||||
style="cursor: pointer">HashedValue</span>
|
||||
style="cursor: pointer">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">签名值</span>
|
||||
<span class="value" id="spSignedValue" @click="showMore('签名值', 'spSignedValue')"
|
||||
style="cursor: pointer">SignedValue</span>
|
||||
style="cursor: pointer">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">签名算法</span>
|
||||
<span class="value" id="spSignMethod">SignMethod</span>
|
||||
<span class="value" id="spSignMethod">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">版本号</span>
|
||||
<span class="value" id="spVersion">Version</span>
|
||||
<span class="value" id="spVersion">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">验签结果</span>
|
||||
<span class="value" id="VerifyRet">VerifyRet</span>
|
||||
<span class="value" id="VerifyRet">[无效的签章结构]</span>
|
||||
</div>
|
||||
|
||||
<p class="content-title">印章信息</p>
|
||||
<div class="subcontent">
|
||||
<span class="title">印章标识</span>
|
||||
<span class="value" id="spSealID">SealID</span>
|
||||
<span class="value" id="spSealID">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">印章名称</span>
|
||||
<span class="value" id="spSealName">SealName</span>
|
||||
<span class="value" id="spSealName">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">印章类型</span>
|
||||
<span class="value" id="spSealType">SealType</span>
|
||||
<span class="value" id="spSealType">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">有效时间</span>
|
||||
<span class="value" id="spSealAuthTime">从NotBefore到NotAfter</span>
|
||||
<span class="value" id="spSealAuthTime">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">制章日期</span>
|
||||
<span class="value" id="spSealMakeTime">MakeTime</span>
|
||||
<span class="value" id="spSealMakeTime">[无效的签章结构]</span>
|
||||
</div>
|
||||
<div class="subcontent">
|
||||
<span class="title">印章版本</span>
|
||||
<span class="value" id="spSealVersion">Version</span>
|
||||
<span class="value" id="spSealVersion">[无效的签章结构]</span>
|
||||
</div>
|
||||
</div>
|
||||
<input style="position:absolute;right:1%;top:1%;" type="button" name="" id="" value="X"
|
||||
@ -196,6 +196,19 @@ export default {
|
||||
|
||||
closeSealInfoDialog() {
|
||||
this.$refs.sealInfoDiv.setAttribute('style', 'display: none');
|
||||
document.getElementById('spSigner').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spProvider').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spHashedValue').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSignedValue').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSignMethod').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSealID').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSealName').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSealType').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSealAuthTime').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSealMakeTime').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spSealVersion').innerText = "[无效的签章结构]";
|
||||
document.getElementById('spVersion').innerText = "[无效的签章结构]";
|
||||
document.getElementById('VerifyRet').innerText = "[无效的签章结构]";
|
||||
},
|
||||
|
||||
showMore(title, id) {
|
||||
@ -332,51 +345,55 @@ export default {
|
||||
},
|
||||
|
||||
addEventOnSealDiv(div, SES_Signature, signedInfo) {
|
||||
global.HashRet=null;
|
||||
div.addEventListener("click",function(){
|
||||
document.getElementById('sealInfoDiv').hidden = false;
|
||||
document.getElementById('sealInfoDiv').setAttribute('style', 'display:flex;align-items: center;justify-content: center;');
|
||||
if(SES_Signature.toSign.version<4){
|
||||
document.getElementById('spSigner').innerText = SES_Signature.toSign.cert['commonName'];
|
||||
document.getElementById('spProvider').innerText = signedInfo['Provider']['ofd:ProviderName'];
|
||||
document.getElementById('spHashedValue').innerText = SES_Signature.toSign.dataHash.replace(/\n/g,'');
|
||||
document.getElementById('spSignedValue').innerText = SES_Signature.signature.replace(/\n/g,'');
|
||||
document.getElementById('spSignMethod').innerText = SES_Signature.toSign.signatureAlgorithm.replace(/\n/g,'');
|
||||
document.getElementById('spSealID').innerText = SES_Signature.toSign.eseal.esealInfo.esID;
|
||||
document.getElementById('spSealName').innerText = SES_Signature.toSign.eseal.esealInfo.property.name;
|
||||
document.getElementById('spSealType').innerText = SES_Signature.toSign.eseal.esealInfo.property.type;
|
||||
document.getElementById('spSealAuthTime').innerText = "从 "+SES_Signature.toSign.eseal.esealInfo.property.validStart+" 到 "+SES_Signature.toSign.eseal.esealInfo.property.validEnd;
|
||||
document.getElementById('spSealMakeTime').innerText = SES_Signature.toSign.eseal.esealInfo.property.createDate;
|
||||
document.getElementById('spSealVersion').innerText = SES_Signature.toSign.eseal.esealInfo.header.version;
|
||||
}else{
|
||||
document.getElementById('spSigner').innerText = SES_Signature.cert['commonName'];
|
||||
document.getElementById('spProvider').innerText = signedInfo['Provider']['@_ProviderName'];
|
||||
document.getElementById('spHashedValue').innerText = SES_Signature.toSign.dataHash.replace(/\n/g,'');
|
||||
document.getElementById('spSignedValue').innerText = SES_Signature.signature.replace(/\n/g,'');
|
||||
document.getElementById('spSignMethod').innerText = SES_Signature.signatureAlgID.replace(/\n/g,'');
|
||||
document.getElementById('spSealID').innerText = SES_Signature.toSign.eseal.esealInfo.esID;
|
||||
document.getElementById('spSealName').innerText = SES_Signature.toSign.eseal.esealInfo.property.name;
|
||||
document.getElementById('spSealType').innerText = SES_Signature.toSign.eseal.esealInfo.property.type;
|
||||
document.getElementById('spSealAuthTime').innerText = "从 "+SES_Signature.toSign.eseal.esealInfo.property.validStart+" 到 "+SES_Signature.toSign.eseal.esealInfo.property.validEnd;
|
||||
document.getElementById('spSealMakeTime').innerText = SES_Signature.toSign.eseal.esealInfo.property.createDate;
|
||||
document.getElementById('spSealVersion').innerText = SES_Signature.toSign.eseal.esealInfo.header.version;
|
||||
}
|
||||
document.getElementById('spVersion').innerText = SES_Signature.toSign.version;
|
||||
global.VerifyRet=signedInfo['VerifyRet'];
|
||||
document.getElementById('VerifyRet').innerText = "文件摘要值后台验证中,请稍等... "+(signedInfo['VerifyRet']?"签名值验证成功":"签名值验证失败");
|
||||
if(global.HashRet==null||global.HashRet==undefined||Object.keys(global.HashRet).length <= 0){
|
||||
setTimeout(function(){
|
||||
const signRetStr = global.VerifyRet?"签名值验证成功":"签名值验证失败";
|
||||
global.HashRet = digestCheck(global.toBeChecked.get(signedInfo['signatureID']));
|
||||
const hashRetStr = global.HashRet?"文件摘要值验证成功":"文件摘要值验证失败";
|
||||
document.getElementById('VerifyRet').innerText = hashRetStr+" "+signRetStr;
|
||||
},1000);
|
||||
}
|
||||
|
||||
if (!global.VerifyRet) {
|
||||
div.setAttribute('class', 'gray');
|
||||
}
|
||||
});
|
||||
try {
|
||||
global.HashRet=null;
|
||||
global.VerifyRet=signedInfo.VerifyRet;
|
||||
console.log(signedInfo);
|
||||
div.addEventListener("click",function(){
|
||||
document.getElementById('sealInfoDiv').hidden = false;
|
||||
document.getElementById('sealInfoDiv').setAttribute('style', 'display:flex;align-items: center;justify-content: center;');
|
||||
if(SES_Signature.realVersion<4){
|
||||
document.getElementById('spSigner').innerText = SES_Signature.toSign.cert['commonName'];
|
||||
document.getElementById('spProvider').innerText = signedInfo.Provider['@_ProviderName'];
|
||||
document.getElementById('spHashedValue').innerText = SES_Signature.toSign.dataHash.replace(/\n/g,'');
|
||||
document.getElementById('spSignedValue').innerText = SES_Signature.signature.replace(/\n/g,'');
|
||||
document.getElementById('spSignMethod').innerText = SES_Signature.toSign.signatureAlgorithm.replace(/\n/g,'');
|
||||
document.getElementById('spSealID').innerText = SES_Signature.toSign.eseal.esealInfo.esID;
|
||||
document.getElementById('spSealName').innerText = SES_Signature.toSign.eseal.esealInfo.property.name;
|
||||
document.getElementById('spSealType').innerText = SES_Signature.toSign.eseal.esealInfo.property.type;
|
||||
document.getElementById('spSealAuthTime').innerText = "从 "+SES_Signature.toSign.eseal.esealInfo.property.validStart+" 到 "+SES_Signature.toSign.eseal.esealInfo.property.validEnd;
|
||||
document.getElementById('spSealMakeTime').innerText = SES_Signature.toSign.eseal.esealInfo.property.createDate;
|
||||
document.getElementById('spSealVersion').innerText = SES_Signature.toSign.eseal.esealInfo.header.version;
|
||||
}else{
|
||||
document.getElementById('spSigner').innerText = SES_Signature.cert['commonName'];
|
||||
document.getElementById('spProvider').innerText = signedInfo.Provider['@_ProviderName'];
|
||||
document.getElementById('spHashedValue').innerText = SES_Signature.toSign.dataHash.replace(/\n/g,'');
|
||||
document.getElementById('spSignedValue').innerText = SES_Signature.signature.replace(/\n/g,'');
|
||||
document.getElementById('spSignMethod').innerText = SES_Signature.signatureAlgID.replace(/\n/g,'');
|
||||
document.getElementById('spSealID').innerText = SES_Signature.toSign.eseal.esealInfo.esID;
|
||||
document.getElementById('spSealName').innerText = SES_Signature.toSign.eseal.esealInfo.property.name;
|
||||
document.getElementById('spSealType').innerText = SES_Signature.toSign.eseal.esealInfo.property.type;
|
||||
document.getElementById('spSealAuthTime').innerText = "从 "+SES_Signature.toSign.eseal.esealInfo.property.validStart+" 到 "+SES_Signature.toSign.eseal.esealInfo.property.validEnd;
|
||||
document.getElementById('spSealMakeTime').innerText = SES_Signature.toSign.eseal.esealInfo.property.createDate;
|
||||
document.getElementById('spSealVersion').innerText = SES_Signature.toSign.eseal.esealInfo.header.version;
|
||||
}
|
||||
document.getElementById('spVersion').innerText = SES_Signature.toSign.version;
|
||||
document.getElementById('VerifyRet').innerText = "文件摘要值后台验证中,请稍等... "+(global.VerifyRet?"签名值验证成功":"签名值验证失败");
|
||||
if(global.HashRet==null||global.HashRet==undefined||Object.keys(global.HashRet).length <= 0){
|
||||
setTimeout(function(){
|
||||
const signRetStr = global.VerifyRet?"签名值验证成功":"签名值验证失败";
|
||||
global.HashRet = digestCheck(global.toBeChecked.get(signedInfo.signatureID));
|
||||
const hashRetStr = global.HashRet?"文件摘要值验证成功":"文件摘要值验证失败";
|
||||
document.getElementById('VerifyRet').innerText = hashRetStr+" "+signRetStr;
|
||||
},1000);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
if (!global.VerifyRet) {
|
||||
div.setAttribute('class', 'gray');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ const decode = function (der, offset) {
|
||||
const SES_Signature = decodeSES_Signature(der,offset);
|
||||
const type = SES_Signature.toSign.eseal.esealInfo.picture.type;
|
||||
const ofdArray = SES_Signature.toSign.eseal.esealInfo.picture.data.byte;
|
||||
console.log(SES_Signature_Verify(SES_Signature));
|
||||
return {ofdArray, 'type': type.toLowerCase(), SES_Signature,'verifyRet':SES_Signature_Verify(SES_Signature)};
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
@ -79,82 +80,82 @@ const decodeUTCTime = function (str) {
|
||||
|
||||
const decodeSES_Signature = function (der, offset) {
|
||||
offset = offset || 0;
|
||||
let asn1 = ASN1.decode(der, offset);
|
||||
var SES_Signature;
|
||||
try {
|
||||
let asn1 = ASN1.decode(der, offset);
|
||||
var SES_Signature;
|
||||
//V1 V4分支判断
|
||||
const version = asn1.sub[0]?.sub[0]?.stream.parseInteger(asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header, asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header + asn1.sub[0].sub[0].length);
|
||||
if(version<4){
|
||||
//V1
|
||||
//Unrecognized time:
|
||||
const createDate = decodeUTCTime(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[3]?.stream.parseTime(asn1.sub[0].sub[1].sub[0].sub[2].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[3].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[3].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[3].length));
|
||||
const validStart = decodeUTCTime(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[4]?.stream.parseTime(asn1.sub[0].sub[1].sub[0].sub[2].sub[4].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[4].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[4].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[4].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[4].length));
|
||||
const validEnd = decodeUTCTime(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[5]?.stream.parseTime(asn1.sub[0].sub[1].sub[0].sub[2].sub[5].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[5].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[5].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[5].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[5].length));
|
||||
const timeInfo = decodeUTCTime(asn1.sub[0]?.sub[2]?.stream.parseTime(asn1.sub[0].sub[2].stream.pos + asn1.sub[0].sub[2].header, asn1.sub[0].sub[2].stream.pos + asn1.sub[0].sub[2].header + asn1.sub[0].sub[2].length, false));
|
||||
const asn1CertList = asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[2];
|
||||
let certList = new Array();
|
||||
if(asn1CertList){
|
||||
asn1CertList.sub.forEach(asn1Cert => {
|
||||
certList.push(asn1Cert.stream.parseOctetString(asn1Cert.stream.pos + asn1Cert.header, asn1Cert.stream.pos + asn1Cert.header+asn1Cert.length));
|
||||
});
|
||||
}
|
||||
const asn1ExtDatas = asn1.sub[0]?.sub[1]?.sub[0]?.sub[4];
|
||||
let extDatas = new Array();
|
||||
if(asn1ExtDatas){
|
||||
asn1ExtDatas.sub.forEach(asn1ExtData => {
|
||||
extDatas.push({
|
||||
'extnID':asn1ExtData.sub[0]?.stream.parseOID(asn1ExtData.sub[0].stream.pos + asn1ExtData.sub[0].header, asn1ExtData.sub[0].stream.pos + asn1ExtData.sub[0].header+asn1ExtData.sub[0].length),
|
||||
'critical':asn1ExtData.sub[1]?.stream.parseInteger(asn1ExtData.sub[1].stream.pos + asn1ExtData.sub[1].header, asn1ExtData.sub[1].stream.pos + asn1ExtData.sub[1].header+asn1ExtData.sub[1].length),
|
||||
'extnValue':asn1ExtData.sub[2]?.stream.parseOctetString(asn1ExtData.sub[2].stream.pos + asn1ExtData.sub[2].header, asn1ExtData.sub[2].stream.pos + asn1ExtData.sub[2].header+asn1ExtData.sub[2].length),
|
||||
})
|
||||
});
|
||||
}
|
||||
//ASN1.decode(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[3]);
|
||||
SES_Signature =
|
||||
{
|
||||
'toSignDer':asn1.sub[0]?.stream.enc.subarray(asn1.sub[0].stream.pos,asn1.sub[0].stream.pos+asn1.sub[0].header+asn1.sub[0].length),
|
||||
'toSign':{
|
||||
'version':asn1.sub[0]?.sub[0]?.stream.parseInteger(asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header, asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header + asn1.sub[0].sub[0].length),
|
||||
'eseal':{
|
||||
'esealInfo':{
|
||||
'header':{
|
||||
'ID':asn1.sub[0]?.sub[1]?.sub[0]?.sub[0]?.sub[0]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[0].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[0].header, asn1.sub[0].sub[1].sub[0].sub[0].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[0].header + asn1.sub[0].sub[1].sub[0].sub[0].sub[0].length),
|
||||
'version':asn1.sub[0]?.sub[1]?.sub[0]?.sub[0]?.sub[1]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[0].sub[1].length),
|
||||
'Vid':asn1.sub[0]?.sub[1]?.sub[0]?.sub[0]?.sub[2]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[0].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[2].header, asn1.sub[0].sub[1].sub[0].sub[0].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[2].header + asn1.sub[0].sub[1].sub[0].sub[0].sub[2].length),
|
||||
},
|
||||
'esID':asn1.sub[0]?.sub[1]?.sub[0]?.sub[1]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[1].length),
|
||||
'property':{
|
||||
'type':asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[0]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[2].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[0].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[0].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[0].length),
|
||||
'name':asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[1]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[2].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[1].length),
|
||||
'certList':certList,
|
||||
'createDate':createDate,
|
||||
'validStart':validStart,
|
||||
'validEnd':validEnd,
|
||||
},
|
||||
'picture':{
|
||||
'type':asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[0]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[3].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[0].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[0].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[0].length),
|
||||
'data': {'hex': asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[1]?.stream.parseOctetString(asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].length), byte: asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[1]?.stream.enc.subarray(asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].length)},
|
||||
'width':asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[2]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[3].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[2].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[2].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[2].length),
|
||||
'height':asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[3]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[3].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[3].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[3].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[3].length),
|
||||
},
|
||||
'extDatas':extDatas,
|
||||
//V1
|
||||
//Unrecognized time:
|
||||
const createDate = decodeUTCTime(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[3]?.stream.parseTime(asn1.sub[0].sub[1].sub[0].sub[2].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[3].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[3].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[3].length));
|
||||
const validStart = decodeUTCTime(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[4]?.stream.parseTime(asn1.sub[0].sub[1].sub[0].sub[2].sub[4].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[4].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[4].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[4].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[4].length));
|
||||
const validEnd = decodeUTCTime(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[5]?.stream.parseTime(asn1.sub[0].sub[1].sub[0].sub[2].sub[5].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[5].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[5].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[5].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[5].length));
|
||||
const timeInfo = decodeUTCTime(asn1.sub[0]?.sub[2]?.stream.parseTime(asn1.sub[0].sub[2].stream.pos + asn1.sub[0].sub[2].header, asn1.sub[0].sub[2].stream.pos + asn1.sub[0].sub[2].header + asn1.sub[0].sub[2].length, false));
|
||||
const asn1CertList = asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[2];
|
||||
let certList = new Array();
|
||||
if(asn1CertList){
|
||||
asn1CertList.sub.forEach(asn1Cert => {
|
||||
certList.push(asn1Cert.stream.parseOctetString(asn1Cert.stream.pos + asn1Cert.header, asn1Cert.stream.pos + asn1Cert.header+asn1Cert.length));
|
||||
});
|
||||
}
|
||||
const asn1ExtDatas = asn1.sub[0]?.sub[1]?.sub[0]?.sub[4];
|
||||
let extDatas = new Array();
|
||||
if(asn1ExtDatas){
|
||||
asn1ExtDatas.sub.forEach(asn1ExtData => {
|
||||
extDatas.push({
|
||||
'extnID':asn1ExtData.sub[0]?.stream.parseOID(asn1ExtData.sub[0].stream.pos + asn1ExtData.sub[0].header, asn1ExtData.sub[0].stream.pos + asn1ExtData.sub[0].header+asn1ExtData.sub[0].length),
|
||||
'critical':asn1ExtData.sub[1]?.stream.parseInteger(asn1ExtData.sub[1].stream.pos + asn1ExtData.sub[1].header, asn1ExtData.sub[1].stream.pos + asn1ExtData.sub[1].header+asn1ExtData.sub[1].length),
|
||||
'extnValue':asn1ExtData.sub[2]?.stream.parseOctetString(asn1ExtData.sub[2].stream.pos + asn1ExtData.sub[2].header, asn1ExtData.sub[2].stream.pos + asn1ExtData.sub[2].header+asn1ExtData.sub[2].length),
|
||||
})
|
||||
});
|
||||
}
|
||||
//ASN1.decode(asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[3]);
|
||||
SES_Signature =
|
||||
{
|
||||
'realVersion':1,
|
||||
'toSignDer':asn1.sub[0]?.stream.enc.subarray(asn1.sub[0].stream.pos,asn1.sub[0].stream.pos+asn1.sub[0].header+asn1.sub[0].length),
|
||||
'toSign':{
|
||||
'version':asn1.sub[0]?.sub[0]?.stream.parseInteger(asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header, asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header + asn1.sub[0].sub[0].length),
|
||||
'eseal':{
|
||||
'esealInfo':{
|
||||
'header':{
|
||||
'ID':asn1.sub[0]?.sub[1]?.sub[0]?.sub[0]?.sub[0]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[0].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[0].header, asn1.sub[0].sub[1].sub[0].sub[0].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[0].header + asn1.sub[0].sub[1].sub[0].sub[0].sub[0].length),
|
||||
'version':asn1.sub[0]?.sub[1]?.sub[0]?.sub[0]?.sub[1]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[0].sub[1].length),
|
||||
'Vid':asn1.sub[0]?.sub[1]?.sub[0]?.sub[0]?.sub[2]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[0].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[2].header, asn1.sub[0].sub[1].sub[0].sub[0].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[0].sub[2].header + asn1.sub[0].sub[1].sub[0].sub[0].sub[2].length),
|
||||
},
|
||||
'signInfo':{
|
||||
'cert':decodeCert(asn1.sub[0]?.sub[1]?.sub[1]?.sub[0]),
|
||||
'signatureAlgorithm':asn1.sub[0]?.sub[1]?.sub[1]?.sub[1]?.stream.parseOID(asn1.sub[0].sub[1].sub[1].sub[1].stream.pos + asn1.sub[0].sub[1].sub[1].sub[1].header, asn1.sub[0].sub[1].sub[1].sub[1].stream.pos + asn1.sub[0].sub[1].sub[1].sub[1].header + asn1.sub[0].sub[1].sub[1].sub[1].length),
|
||||
'signData':asn1.sub[0]?.sub[1]?.sub[1]?.sub[2]?.stream.hexDump(asn1.sub[0].sub[1].sub[1].sub[2].stream.pos + asn1.sub[0].sub[1].sub[1].sub[2].header, asn1.sub[0].sub[1].sub[1].sub[2].stream.pos + asn1.sub[0].sub[1].sub[1].sub[2].header + asn1.sub[0].sub[1].sub[1].sub[2].length, false)
|
||||
'esID':asn1.sub[0]?.sub[1]?.sub[0]?.sub[1]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[1].length),
|
||||
'property':{
|
||||
'type':asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[0]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[2].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[0].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[0].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[0].length),
|
||||
'name':asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[1]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[2].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[1].length),
|
||||
'certList':certList,
|
||||
'createDate':createDate,
|
||||
'validStart':validStart,
|
||||
'validEnd':validEnd,
|
||||
},
|
||||
|
||||
'picture':{
|
||||
'type':asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[0]?.stream.parseStringUTF(asn1.sub[0].sub[1].sub[0].sub[3].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[0].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[0].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[0].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[0].length),
|
||||
'data': {'hex': asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[1]?.stream.parseOctetString(asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].length), byte: asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[1]?.stream.enc.subarray(asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[1].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[1].length)},
|
||||
'width':asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[2]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[3].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[2].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[2].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[2].length),
|
||||
'height':asn1.sub[0]?.sub[1]?.sub[0]?.sub[3]?.sub[3]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[3].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[3].header, asn1.sub[0].sub[1].sub[0].sub[3].sub[3].stream.pos + asn1.sub[0].sub[1].sub[0].sub[3].sub[3].header + asn1.sub[0].sub[1].sub[0].sub[3].sub[3].length),
|
||||
},
|
||||
'extDatas':extDatas,
|
||||
},
|
||||
'timeInfo':timeInfo,
|
||||
'dataHash':asn1.sub[0]?.sub[3]?.stream.hexDump(asn1.sub[0].sub[3].stream.pos + asn1.sub[0].sub[3].header, asn1.sub[0].sub[3].stream.pos + asn1.sub[0].sub[3].header + asn1.sub[0].sub[3].length, false),
|
||||
'propertyInfo':asn1.sub[0]?.sub[4]?.stream.parseStringUTF(asn1.sub[0].sub[4].stream.pos + asn1.sub[0].sub[4].header, asn1.sub[0].sub[4].stream.pos + asn1.sub[0].sub[4].header + asn1.sub[0].sub[4].length),
|
||||
'cert':decodeCert(asn1.sub[0]?.sub[5]),
|
||||
'signatureAlgorithm':asn1.sub[0]?.sub[6]?.stream.parseOID(asn1.sub[0].sub[6].stream.pos + asn1.sub[0].sub[6].header, asn1.sub[0].sub[6].stream.pos + asn1.sub[0].sub[6].header + asn1.sub[0].sub[6].length),
|
||||
'signInfo':{
|
||||
'cert':decodeCert(asn1.sub[0]?.sub[1]?.sub[1]?.sub[0]),
|
||||
'signatureAlgorithm':asn1.sub[0]?.sub[1]?.sub[1]?.sub[1]?.stream.parseOID(asn1.sub[0].sub[1].sub[1].sub[1].stream.pos + asn1.sub[0].sub[1].sub[1].sub[1].header, asn1.sub[0].sub[1].sub[1].sub[1].stream.pos + asn1.sub[0].sub[1].sub[1].sub[1].header + asn1.sub[0].sub[1].sub[1].sub[1].length),
|
||||
'signData':asn1.sub[0]?.sub[1]?.sub[1]?.sub[2]?.stream.hexDump(asn1.sub[0].sub[1].sub[1].sub[2].stream.pos + asn1.sub[0].sub[1].sub[1].sub[2].header, asn1.sub[0].sub[1].sub[1].sub[2].stream.pos + asn1.sub[0].sub[1].sub[1].sub[2].header + asn1.sub[0].sub[1].sub[1].sub[2].length, false)
|
||||
},
|
||||
|
||||
},
|
||||
'signature':asn1.sub[1]?.stream.hexDump(asn1.sub[1].stream.pos + asn1.sub[1].header, asn1.sub[1].stream.pos + asn1.sub[1].header + asn1.sub[1].length, false),
|
||||
};
|
||||
}else{
|
||||
'timeInfo':timeInfo,
|
||||
'dataHash':asn1.sub[0]?.sub[3]?.stream.hexDump(asn1.sub[0].sub[3].stream.pos + asn1.sub[0].sub[3].header, asn1.sub[0].sub[3].stream.pos + asn1.sub[0].sub[3].header + asn1.sub[0].sub[3].length, false),
|
||||
'propertyInfo':asn1.sub[0]?.sub[4]?.stream.parseStringUTF(asn1.sub[0].sub[4].stream.pos + asn1.sub[0].sub[4].header, asn1.sub[0].sub[4].stream.pos + asn1.sub[0].sub[4].header + asn1.sub[0].sub[4].length),
|
||||
'cert':decodeCert(asn1.sub[0]?.sub[5]),
|
||||
'signatureAlgorithm':asn1.sub[0]?.sub[6]?.stream.parseOID(asn1.sub[0].sub[6].stream.pos + asn1.sub[0].sub[6].header, asn1.sub[0].sub[6].stream.pos + asn1.sub[0].sub[6].header + asn1.sub[0].sub[6].length),
|
||||
},
|
||||
'signature':asn1.sub[1]?.stream.hexDump(asn1.sub[1].stream.pos + asn1.sub[1].header, asn1.sub[1].stream.pos + asn1.sub[1].header + asn1.sub[1].length, false),
|
||||
};
|
||||
} catch (e) {
|
||||
try {
|
||||
//V4
|
||||
const certListType = asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[2]?.stream.parseInteger(asn1.sub[0].sub[1].sub[0].sub[2].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[2].header, asn1.sub[0].sub[1].sub[0].sub[2].sub[2].stream.pos + asn1.sub[0].sub[1].sub[0].sub[2].sub[2].header + asn1.sub[0].sub[1].sub[0].sub[2].sub[2].length);
|
||||
const asn1CertList = asn1.sub[0]?.sub[1]?.sub[0]?.sub[2]?.sub[3];
|
||||
@ -177,6 +178,7 @@ const decodeSES_Signature = function (der, offset) {
|
||||
}
|
||||
SES_Signature =
|
||||
{
|
||||
'realVersion':4,
|
||||
'toSignDer':asn1.sub[0]?.stream.enc.subarray(asn1.sub[0].stream.pos,asn1.sub[0].stream.pos+asn1.sub[0].header+asn1.sub[0].length),
|
||||
'toSign':{
|
||||
'version':asn1.sub[0]?.sub[0]?.stream.parseInteger(asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header, asn1.sub[0].sub[0].stream.pos + asn1.sub[0].sub[0].header + asn1.sub[0].sub[0].length),
|
||||
@ -218,13 +220,13 @@ const decodeSES_Signature = function (der, offset) {
|
||||
'signatureAlgID':asn1.sub[2]?.stream.parseOID(asn1.sub[2].stream.pos + asn1.sub[2].header, asn1.sub[2].stream.pos + asn1.sub[2].header + asn1.sub[2].length),
|
||||
'signature':asn1.sub[3]?.stream.hexDump(asn1.sub[3].stream.pos + asn1.sub[3].header, asn1.sub[3].stream.pos + asn1.sub[3].header + asn1.sub[3].length, false),
|
||||
'timpStamp':asn1.sub[4]?.stream.parseTime(asn1.sub[4].stream.pos + asn1.sub[4].header, asn1.sub[4].stream.pos + asn1.sub[4].header + asn1.sub[4].length)
|
||||
};
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
SES_Signature={};
|
||||
}
|
||||
return SES_Signature;
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return {};
|
||||
}
|
||||
return SES_Signature;
|
||||
}
|
||||
|
||||
const decodeCert = function (asn1, offset) {
|
||||
|
@ -10,46 +10,51 @@ import Base64 from "@lapo/asn1js/base64";
|
||||
|
||||
export const digestByteArray = function(data,hashedBase64,checkMethod){
|
||||
const hashedHex = Uint8ArrayToHexString(Base64.decode(hashedBase64));
|
||||
checkMethod = checkMethod.toLowerCase()
|
||||
if(checkMethod === "1.2.156.10197.1.401" || checkMethod.indexOf('sm3') !== -1){
|
||||
return hashedHex === sm3(Uint8ArrayToHexString(data));
|
||||
}else if(checkMethod.indexOf('md5') !== -1){
|
||||
return hashedHex === md5(data);
|
||||
}else if(checkMethod.indexOf('sha1') !== -1){
|
||||
return hashedHex === sha1(data);
|
||||
checkMethod = checkMethod.toLowerCase();
|
||||
if(checkMethod.indexOf("1.2.156.10197.1.401")>=0 || checkMethod.indexOf("sm3")>=0){
|
||||
return hashedHex==sm3(Uint8ArrayToHexString(data));
|
||||
}else if(checkMethod.indexOf("md5")>=0){
|
||||
return hashedHex==md5(data);
|
||||
}else if(checkMethod.indexOf("sha1")>=0){
|
||||
return hashedHex==sha1(data);
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export const SES_Signature_Verify = function(SES_Signature){
|
||||
let signAlg = SES_Signature.toSign.version<4?SES_Signature.toSign.signatureAlgorithm:SES_Signature.signatureAlgID;
|
||||
const msg = SES_Signature.toSignDer;
|
||||
signAlg = signAlg.toLowerCase();
|
||||
if(signAlg.indexOf("1.2.156.10197.1.501")>=0 || signAlg.indexOf("sm2")>=0){
|
||||
let sigValueHex = SES_Signature.signature.replace(/ /g,'').replace(/\n/g,'');
|
||||
if(sigValueHex.indexOf('00')===0){
|
||||
sigValueHex = sigValueHex.substr(2,sigValueHex.length-2);
|
||||
try {
|
||||
let signAlg = SES_Signature.realVersion<4?SES_Signature.toSign.signatureAlgorithm:SES_Signature.signatureAlgID;
|
||||
signAlg = signAlg.toLowerCase();
|
||||
const msg = SES_Signature.toSignDer;
|
||||
if(signAlg.indexOf("1.2.156.10197.1.501")>=0 || signAlg.indexOf("sm2")>=0){
|
||||
let sigValueHex = SES_Signature.signature.replace(/ /g,'').replace(/\n/g,'');
|
||||
if(sigValueHex.indexOf('00')==0){
|
||||
sigValueHex = sigValueHex.substr(2,sigValueHex.length-2);
|
||||
}
|
||||
const cert = SES_Signature.realVersion<4?SES_Signature.toSign.cert:SES_Signature.cert;
|
||||
let publicKey = cert.subjectPublicKeyInfo.subjectPublicKey.replace(/ /g,'').replace(/\n/g,'');
|
||||
if(publicKey.indexOf('00')==0){
|
||||
publicKey = publicKey.substr(2,publicKey.length-2);
|
||||
}
|
||||
return sm2.doVerifySignature(msg, sigValueHex, publicKey, {
|
||||
der : true,
|
||||
hash: true,
|
||||
userId:"1234567812345678"
|
||||
});
|
||||
}else{
|
||||
let sig = new rsa.KJUR.crypto.Signature({"alg": "SHA1withRSA"});
|
||||
const cert = SES_Signature.realVersion<4?SES_Signature.toSign.cert:SES_Signature.cert;
|
||||
let sigValueHex = SES_Signature.signature.replace(/ /g,'').replace(/\n/g,'');
|
||||
if(sigValueHex.indexOf('00')==0){
|
||||
sigValueHex = sigValueHex.substr(2,sigValueHex.length-2);
|
||||
}
|
||||
sig.init(cert);
|
||||
sig.updateHex(msg);
|
||||
return sig.verify(sigValueHex);
|
||||
}
|
||||
const cert = SES_Signature.toSign.version<4?SES_Signature.toSign.cert:SES_Signature.cert;
|
||||
let publicKey = cert.subjectPublicKeyInfo.subjectPublicKey.replace(/ /g,'').replace(/\n/g,'');
|
||||
if(publicKey.indexOf('00')===0){
|
||||
publicKey = publicKey.substr(2,publicKey.length-2);
|
||||
}
|
||||
return sm2.doVerifySignature(msg, sigValueHex, publicKey, {
|
||||
der : true,
|
||||
hash: true,
|
||||
userId:"1234567812345678"
|
||||
});
|
||||
}else{
|
||||
let sig = new rsa.KJUR.crypto.Signature({"alg": "SHA1withRSA"});
|
||||
const cert = SES_Signature.toSign.version<4?SES_Signature.toSign.cert:SES_Signature.cert;
|
||||
let sigValueHex = SES_Signature.signature.replace(/ /g,'').replace(/\n/g,'');
|
||||
if(sigValueHex.indexOf('00')==0){
|
||||
sigValueHex = sigValueHex.substr(2,sigValueHex.length-2);
|
||||
}
|
||||
sig.init(cert);
|
||||
sig.updateHex(msg);
|
||||
return sig.verify(sigValueHex);
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user