前面介绍了加载证书及解析证书链,接下来介绍证书验证

证书验证

Qt提供证书验证的接口

static QList<QSslError> verify(QList<QSslCertificate> certificateChain, const QString &hostName = QString());
  • 传参证书链,证书链可以不用根证书,验的时候会到系统证书库中找
  • 域名验证可选

如果已经有了证书链,那就好办,直接验就可以了

那如果只知道用户证书,不知道上一级证书呢?当然是先取证书链,取到再验

证书作为公开的信息,通过相关途径可以找到关联的证书,方法如下

以百度证书为例,查看证书,找到扩展项授权信息访问

授权信息访问提供了上一级证书的下载地址,通过浏览器打开链接即可下载

接下来查看该证书是否也提供了上一级证书的下载地址

可以看到,并没有提供,那就无法直接获取到上一级证书,也就是根证书

对于使用Qt验证的接口其实不用根证书也能验,因为该根证书是预置在系统证书库中,是受信任的根

既然知道该证书在系统库中,那我们是不是可以取到呢

答案当然是肯定的

通过以下接口可以取到系统库中的证书

QSslSocket::systemCaCertificates();
//或
QSslSocket::defaultCaCertificates();

系统库中这么多证书,那要怎么知道是对应哪个跟证书呢

证书扩展项中有两个字段,其中使用者密钥标识符是作为证书自己的标识符,授权密钥标识符是上一级证书的标识符

意思就是根证书的使用者密钥标识符和签发的下一级证书的授权密钥标识符是相等的

我们就可以通过这个来找出根证书

Code

废话不多说,代码才是硬道理

#include "rddownloadcertchain.h"
#include "httpgetmanager.h"
#include <QSslCertificate>
#include <QSslCertificateExtension>
#include <QSslSocket>
#include <QFile>RdDownloadCertChain::RdDownloadCertChain(QObject *parent):QObject(parent)
{m_pHttpGetManager = new HttpGetManager(this);
//    connect(m_pHttpGetManager, &HttpGetManager::sigGetFinish, this, &RdDownloadCertChain::onGetFinish);
}RdDownloadCertChain::~RdDownloadCertChain()
{delete m_pHttpGetManager;
}int RdDownloadCertChain::dowmloadChain(const QByteArray &certData, QList<QByteArray> &chain)
{QSslCertificate cert(certData);if(cert.isNull()) {cert.clear();cert = QSslCertificate(certData, QSsl::Der);}if(cert.isNull()) {return -1;}chain.append(cert.toPem());QString url = this->getDownloadUrl(cert);qDebug() << __FUNCTION__ << "song" << "url" << url;if(!url.isEmpty()) {m_pHttpGetManager->setUrl(url);QByteArray data = m_pHttpGetManager->httpGet();//递归下载if(dowmloadChain(data, chain) != 0) {return -1;}}else {QList<QSslCertificateExtension> exts = cert.extensions();QString authKeyID, subjectKeyID;foreach (auto ext, exts) {//获取使用者密钥标识符和颁发者密钥标识符if(ext.oid() == "2.5.29.35") {authKeyID = ext.value().toMap().value("keyid").toString();}else if(ext.oid() == "2.5.29.14") {subjectKeyID = ext.value().toString().replace(":", "").toLower();}}//使用者密钥标识符和颁发者密钥标识符一样则为根证书if(authKeyID != subjectKeyID) {QList<QSslCertificate> sysCerts = QSslSocket::systemCaCertificates();foreach (auto sysCert, sysCerts) {QString subKeyID = getSubjectKeyid(sysCert);if(subKeyID == authKeyID) {chain.append(sysCert.toPem());//找到直接结束,系统库可能会存在多个相同的证书return 0;}}}}return 0;
}QString RdDownloadCertChain::getDownloadUrl(const QSslCertificate &cert)
{QString url;QList<QSslCertificateExtension> exts = cert.extensions();foreach (auto ext, exts) {//通过扩展项授权信息访问获取上一级证书的下载地址if(ext.oid() == "1.3.6.1.5.5.7.1.1") {QMap<QString, QVariant> extMap = ext.value().toMap();QMap<QString, QVariant>::iterator iter = extMap.find("caIssuers");if(iter != extMap.end()) {url = iter.value().toString();}}}return url;
}QString RdDownloadCertChain::getSubjectKeyid(const QSslCertificate &cert)
{QString subKeyID;QList<QSslCertificateExtension> sysExts = cert.extensions();foreach (auto ext, sysExts) {if(ext.oid() == "2.5.29.14") {subKeyID = ext.value().toString().replace(":", "").toLower();}}return subKeyID;
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "rddownloadcertchain.h"
#include <QFileDialog>
#include <QDebug>
#include <QSslError>
#include <QTreeWidget>
#include <QHeaderView>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);m_pDownladManager = new RdDownloadCertChain(this);m_pTreeWidget = new QTreeWidget(this);m_pTreeWidget->setGeometry(130, 130, 400, 150);m_pTreeWidget->header()->setVisible(false);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::createTreeItem(const QStringList &chainNameList)
{QTreeWidgetItem *rootItem = nullptr;for(int i = chainNameList.size() -1; i >=0; --i) {QString certName = chainNameList.at(i);if(!rootItem) {rootItem = new QTreeWidgetItem(m_pTreeWidget, QStringList(certName));}else {rootItem = new QTreeWidgetItem(rootItem, QStringList(certName));}}m_pTreeWidget->expandAll();
}void MainWindow::on_pushButton_clicked()
{QString url = QFileDialog::getOpenFileName(this);ui->lineEdit->setText(url);
}void MainWindow::on_pushButton_2_clicked()
{m_sslChains.clear();m_pTreeWidget->clear();QFile file(ui->lineEdit->text());if(!file.open(QIODevice::ReadOnly)) {return;}QByteArray data = file.readAll();file.close();QList<QByteArray> chains;m_pDownladManager->dowmloadChain(data,chains);QStringList chainNameList;foreach (auto certData, chains) {QSslCertificate certtificate(certData);m_sslChains.append(certtificate);qDebug() << __FUNCTION__ << "song" << certtificate.subjectDisplayName();chainNameList.append(certtificate.subjectDisplayName());}createTreeItem(chainNameList);
}void MainWindow::on_pushButton_3_clicked()
{QList<QSslError> errs = QSslCertificate::verify(m_sslChains);if(errs.isEmpty()) {ui->textEdit->setText(u8"此证书已通过验证");}else {QString errText;foreach (auto err, errs) {if(!errText.isEmpty()) {errText.append("\n");}qDebug() << __FUNCTION__ << "song" << "verify err:" << err.errorString();errText.append(err.errorString());}ui->textEdit->setText(errText);}
}

原理上面已经介绍了,代码量不多,以下是运行结果

Demo代码链接

https://download.csdn.net/download/a137748099/18718506

其他API

结合前两篇文章,QSslCertificate支持的接口基本都介绍完了

还剩下面的接口没介绍到

bool isBlacklisted() const; 黑名单判别
bool isSelfSigned() const; 自签证书判别,颁发者和使用者名称一样的证书为自签证书

【Qt】x509证书操作之获取证书链并验证相关推荐

  1. (转)创建X509证书,并获取证书密钥的一点研究

    创建X509证书,并获取证书密钥的一点研究 作者:肖波 个人博客:http://blog.csdn.net/eaglet ; http://www.cnblogs.com/eaglet 2007/7 ...

  2. php获取x509证书信息,创建X509证书,并获取证书密钥的一点研究

    作者:肖波 背景 服务器SSL数字证书和客户端单位数字证书的格式遵循X.509标准.X.509是由国际电信联盟(ITU-T)制定的数字证书标准.为了提供公用网络用户目录信息服务,ITU于1988年制定 ...

  3. 【Qt】x509证书操作之解析证书信息

    QSslCertificate支持x509证书信息的解析 证书信息接口 函数 功能 QByteArray version() const 版本 QByteArray serialNumber() co ...

  4. java解码p7b证书文件,通过OpenSSL解码X509证书文件

    在Windows平台下,如果要解析一个X509证书文件,最直接的办法是使用微软的CryptoAPI.但是在非Windows平台下,就只能使用强大的开源跨平台库OpenSSL了.一个X509证书通过Op ...

  5. PHP的OpenSSL加密扩展学习(三):证书操作

    PHP的OpenSSL加密扩展学习(三):证书操作 关于对称和非对称的加密操作,我们已经学习完两篇文章的内容了,接下来,我们就继续学习关于证书的生成. 生成 CSR 证书签名请求 CSR 是用于生成证 ...

  6. OpenSSL 使用拾遗(二)---- X509 证书的 SKID/AKID 字段

    SKID(证书使用者密钥标识符,subject key identifier 的简称)和 AKID(证书颁发机构密钥标识符,authority key identifier 的简称)是 X509 证书 ...

  7. 教程篇(6.0) 06. 证书操作 ❀ FortiGate 安全 ❀ Fortinet 网络安全专家 NSE 4

    在本课中,你将了解FortiGate为什么使用数字证书,如何配置FortiGate以使用证书(包括使用证书检查加密流量的内容),以及FortiGate如何管理证书. 在本次课程中,你将探讨以下主题: ...

  8. 使用OpenSSL实现证书操作

    使用OpenSSL实现证书操作 伴随着计算机的发展,计算机的安全问题也一直困扰着我们,在现代社会计算机信息安全更显得格外的重要,如今的社会是一个信息的社会,你我每天都在使用计算机,随着电子邮件.社区网 ...

  9. OPENSSL X509证书验证

    openssl实现了标准的x509v3数字证书,其源码在crypto/x509和crypto/x509v3中.其中x509目录实现了数字证书以及证书申请相关的各种函数,包括了X509和X509_REQ ...

  10. 关于X509证书和密钥的概念

    证书概述 证书主要包括颁发者和被办法者的信息,以及被颁发者的公钥,和CA机构对这些信息的认证, 主要内容: **版本** 识别用于该证书的 X.509 标准的版本,这可以影响证书中所能指定的信息.迄今 ...

最新文章

  1. 浮点数能进行取模运算吗?(不行,暂时只能是两个整数之间)
  2. RBF(径向基)神经网络 非线性函数回归的实现
  3. app.vue里使用data_Python爬虫使用正则爬取网站,正则都不会就别玩爬虫了!
  4. Boost:bimap双图的突变关系的测试程序
  5. 深入浅出之虚函数原理篇(笔记三)
  6. 如何和后台接触的_后台产品,不只是做支持
  7. PHP Primary script unknown 终极解决方法
  8. 联想乐云记事2.0高调发布 新增智能语音识别 [多平台]
  9. [转载] Python str title()方法
  10. 【渝粤教育】国家开放大学2019年春季 2328仓储与配送管理 参考试题
  11. 研制埃博拉疫苗与科学家的奇思秒想
  12. 如何安装TFP(tensorflow概率编程)
  13. 蛋花花谈程序员怎样快速提升自己的专业能力
  14. WAV高清语音格式音频
  15. PTA 7-2 复数与基本类型的加减运算
  16. Eolink 征文活动- -后端研发需要的API文档工具
  17. js解决chrome浏览器无法自动播放音频
  18. 四层高速dsp开发板制作7——绘制等长线
  19. [Scapy]导入导出数据
  20. 停车场服务器系统,停车场系统设计方案.doc

热门文章

  1. 复选框样式圆圈html,css怎么美化复选框样式
  2. oracle设置临时表空间,oracle操作临时表空间
  3. BugKu_MISC_(3)
  4. 广东大学计算机基础教材,21世纪高等学校计算机公共基础课规划教材:大学计算机基础(第2版)...
  5. apache2.4.37无法解析php,编译安装apache2.4.37(Server version: Apache/2.4.37 )
  6. 金牛判势 精品起涨预警 主升浪起爆点指标 通达信指标公式
  7. iOS GPS定位减小精度误差的几种处理方法
  8. 华为HCIE-RS(数通)论述题(一)
  9. R语言之dpqr概率函数
  10. aspx repeate控件多级关联