Javascript 检查SSL证书过期日期

Javascript 检查SSL证书过期日期,javascript,Javascript,我需要检查本地计算机的SSl证书过期日期,并将其与当前日期进行比较,并通知用户其证书将在X天后过期。所有这些我都需要用JavaScript来完成。到目前为止,唯一可用的选项是forge,或者客户端的某种自定义扩展 客户端只知道DOM元素,因此无法检查SSL层 关于这一点的更多信息这在客户端是不可能的,但是您可以使用node/shell组合执行类似的操作 假设您有权访问证书运行的服务器,您可以在主机上执行以下操作: var execSync = require('child_process').e

我需要检查本地计算机的SSl证书过期日期,并将其与当前日期进行比较,并通知用户其证书将在X天后过期。所有这些我都需要用JavaScript来完成。

到目前为止,唯一可用的选项是forge,或者客户端的某种自定义扩展

客户端只知道DOM元素,因此无法检查SSL层


关于这一点的更多信息

这在客户端是不可能的,但是您可以使用node/shell组合执行类似的操作

假设您有权访问证书运行的服务器,您可以在主机上执行以下操作:

var execSync = require('child_process').execSync
var cmd = "echo | openssl s_client -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -dates"
var stdout = execSync(cmd).toString()
// "notBefore=Feb 16 15:33:00 2017 GMT\nnotAfter=May 17 15:33:00 2017 GMT"

从那里,您可以解析stdout报告的日期,并将其写入公共资源或json文件,以便从客户端读取,然后从那里进行日期比较

您的证书应如下所示:

-----BEGIN CERTIFICATE-----
MIIGoDCCBIigAwIBAgIJAICRY3cWdgK1MA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD
VQQGEwJCRzERMA8GA1UECAwIQnVsZ2FyaWExDjAMBgNVBAcMBVNvZmlhMQ8wDQYD
..
ud5Nja8+xycA/Jk7bSvB1jJjpc3oL0G9j0HOcxqQKd4e1IQXuss5V7FnQxSOVCq4
GVK0r3LkAxtl/EGmQC1DRlHAUWg=
-----END CERTIFICATE-----
您需要从证书数据中去掉
----BEGIN-CERTIFICATE-----
头和
----END-CERTIFICATE-----
尾,其余是一个编码字节数组。 您需要将其解码为一个字节数组(在本例中表示为数字数组,其中每个数字表示一个介于0和255之间(含0和255)的字节数)。 该字节数组是中定义的编码结构

下面的示例将在剥离了
----BEGIN certificate-----
----END certificate-----
traile之后解析证书的内容

用法:

var-pem=
“MIIGijCCBXKgAwIBAgIQEpI/gkvDS6idH2m2Zwn7ZzANBgkqhkiG9w0BAQsFADCB\n”
...
+“VQ+o34uWo7z19I8eXWSXN6P+Uj1OvHn8zNM1G/ddjQXBwMvzwwJEdVBhdK1uQw==\n”;
var字节=fromBase64(pem);
var validity=getValidity(字节);
var notBefore=有效期。notBefore;
var notAfter=有效期。notAfter;
var now=新日期();
if(notBefore.getTime()
解析:


var TYPE_INTEGER=0x02;
变量类型_序列=0x10;
变量类型UTC时间=0x17;
var类型\u广义\u时间=0x18;
功能子阵列(原始、开始、结束){
var-subar=[];
var指数=0;
对于(变量i=开始;i<结束;i++){
subar[index++]=原始[i];
}
返回子雷达;
}
函数getDigit(d){
开关(d){
违约:
案例0x30:案例“0”:返回0;
案例0x31:案例“1”:返回1;
案例0x32:案例“2”:返回2;
案例0x33:案例“3”:返回3;
案例0x34:案例“4”:返回4;
案例0x35:案例“5”:返回5;
案例0x36:案例“6”:返回6;
案例0x37:案例“7”:返回7;
案例0x38:案例“8”:返回8;
案例0x39:案例“9”:返回9;
}
}
函数enterTag(字节、开始、所需类型、名称){
如果(开始+1>字节.长度){
抛出新错误(“证书输入太短”);
}
var typeByte=bytes[start]&0x0FF;
var lenByte=bytes[start+1]&0x0FF;
var type=typeByte&0x1F;
var len=lenByte;
var指数=start+2;
if(requiredTypes.length>0&&requiredTypes.indexOf(type)=-1){
抛出新错误(“无效类型”);
}
var lengthOfLength=0;
如果(len>0x07F){
lengthOfLength=len&0x7F;
len=0;
对于(变量i=0;i=bytes.length){
抛出新错误(“证书输入太短”);
}
var valueStart=结果指数;
var valueEnd=result.index+result.length;
var值=子数组(字节、值开始、值结束);
返回{index:index,type:result.type,value:value};
}
函数读取日期(字节、开始、名称){
变量日期=新日期();
var result=processTag(字节、开始、,
[UTC时间类型,通用时间类型],名称);
var指数,年份;
如果(result.type==0x17){//UTCTime
如果(结果值长度<12){
抛出新错误(“无效类型”);
}
var yearHigh=getDigit(结果值[0]);
var yearLow=getDigit(结果值[1]);
变量year2Digits=(yearHigh*10)+(yearLow)
如果(年份2数字>=50){
年份=1900+年份2数字;
}否则{
年份=2000年+年份2数字;
}
指数=2;
}如果(result.type=0x18){//GeneralizedTime
如果(结果值长度<14){
抛出新错误(“无效类型”);
}
var year1=getDigit(结果值[0]);
var year2=getDigit(结果值[1]);
var year3=getDigit(结果值[2]);
var year4=getDigit(结果值[3]);
年份=(第1年*1000)+(第2年*100)+(第3年*10)+第4年;
指数=4;
}
var monthHigh=getDigit(result.value[index++]);
var monthLow=getDigit(结果值[index++]);
var dayHigh=getDigit(结果值[index++]);
var dayhLow=getDigit(result.value[index++]);
var hourHigh=getDigit(result.value[index++]);
var hourLow=getDigit(result.value[index++]);
var minuteHigh=getDigit(结果值[index++]);
var minuteLow=getDigit(result.value[index++]);
var secondHigh=getDigit(result.value[index++]);
var secondLow=getDigit(结果值[索引]);
var月=(月高*10)+月低;
风险值日=(日高*10)+日低;
变量小时=(hourHigh*10)+hourLow;
变量分钟=(分钟高*10)+分钟低;
第二个变量=(第二高*10)+第二低;
如果