概要
数字证书(Certificate)用于存储数字证书信息,是一种电子文档,用于证明公钥持有者的身份。有时需要知道证书的过期时间,方便及时更新证书,我们可以通过OpenSSL库来获取证书的有效期。
实现方式
这里使用的是 OpenSSL1.1.0f 版本,可以直接点击下载。首先工程属性配置好头文件和库文件位置:
下面是一段判断证书是否已经过期或者即将过期的代码:
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <ctime>
#include <io.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
// 将ASN1_TIME转换为time_t
time_t ASN1Time_To_Time_t(const ASN1_TIME *time) {
struct tm tm = {};
const char* time_str = reinterpret_cast<const char*>(time->data);
// 解析ASN1时间格式:YYMMDDHHMMSSZ
if (time->length == 13 && time_str[time->length - 1] == 'Z') {
tm.tm_year = (time_str[0] - '0') * 10 + (time_str[1] - '0') + 100; // 2000+年
tm.tm_mon = (time_str[2] - '0') * 10 + (time_str[3] - '0') - 1; // 0-based 月份
tm.tm_mday = (time_str[4] - '0') * 10 + (time_str[5] - '0'); // 日
tm.tm_hour = (time_str[6] - '0') * 10 + (time_str[7] - '0'); // 时
tm.tm_min = (time_str[8] - '0') * 10 + (time_str[9] - '0'); // 分
tm.tm_sec = (time_str[10] - '0') * 10 + (time_str[11] - '0'); // 秒
return mktime(&tm);
}
return -1;
}
// 判断证书是否已经过期或者即将过期
bool IsCertExpired(const char *pFile) {
bool will_expire = false;
FILE *fp = nullptr;
X509 *cert = nullptr;
try {
// 打开证书文件
errno_t err = fopen_s(&fp, pFile, "rb");
if (err != 0 || !fp) {
throw std::runtime_error("Can not open cert file.");
}
// 读取证书
cert = PEM_read_X509(fp, nullptr, nullptr, nullptr);
if (!cert) {
throw std::runtime_error("Can not read cert file.");
}
// 获取当前时间
time_t current_time = time(nullptr);
// 获取证书有效期截止时间
const ASN1_TIME *not_after = X509_get_notAfter(cert);
// 转换截止时间
time_t not_after_time = ASN1Time_To_Time_t(not_after);
if (not_after_time == -1) {
throw std::runtime_error("Can not X509_get_notAfter.");
}
// 计算剩余天数
double seconds_remaining = difftime(not_after_time, current_time);
int days_remaining = static_cast<int>(seconds_remaining / (60 * 60 * 24));
if (days_remaining <= 0) { // 已经过期
will_expire = true;
} else if (days_remaining <= 30) { // 将在30天后过期
will_expire = true;
} else {
will_expire = false;
}
} catch (const std::exception& e) {
will_expire = false;
}
// 清理资源
if (cert) {
X509_free(cert);
}
if (fp) {
fclose(fp);
}
return will_expire;
}