这个解析程序使用C++写成,更多详细内容可参考GitHub项目。

X.509证书结构

Certificate ::= SEQUENCE {tbsCertificate       TBSCertificate,                      -- 证书主体signatureAlgorithm   AlgorithmIdentifier,                 -- 证书签名算法标识signatureValue       BIT STRING                           -- 证书签名值,是使用signatureAlgorithm部分指定的签名算法对tbsCertificate证书主题部分签名后的值.
}TBSCertificate ::= SEQUENCE {version         [0] EXPLICIT Version DEFAULT v1,          -- 证书版本号serialNumber         CertificateSerialNumber,             -- 证书序列号,对同一CA所颁发的证书,序列号唯一标识证书signature            AlgorithmIdentifier,                 -- 证书签名算法标识issuer               Name,                                -- 证书发行者名称validity             Validity,                            -- 证书有效期subject              Name,                                -- 证书主体名称subjectPublicKeyInfo SubjectPublicKeyInfo,                -- 证书公钥issuerUniqueID  [1] IMPLICIT UniqueIdentifier OPTIONAL,   -- 证书发行者ID(可选),只在证书版本2、3中才有subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,   -- 证书主体ID(可选),只在证书版本2、3中才有extensions      [3] EXPLICIT Extensions OPTIONAL          -- 证书扩展段(可选),只在证书版本3中才有
}Version ::= INTEGER { v1(0), v2(1), v3(2) }                   -- 版本号(v1,v2,v3)CertificateSerialNumber ::= INTEGER                           -- 证书序列号存储结构AlgorithmIdentifier ::= SEQUENCE {                            -- 签名算法标识存储结构algorithm               OBJECT IDENTIFIER,                -- 签名算法名称parameters              ANY DEFINED BY algorithm OPTIONAL -- 签名算法参数
}parameters:                                                   -- DSA(DSS)算法时的参数,RSA算法没有此参数Dss-Parms ::= SEQUENCE {p             INTEGER,q             INTEGER,g             INTEGER}signatureValue:                                              -- sha1DSA签名算法时,签名值存储结构Dss-Sig-Value ::= SEQUENCE { r       INTEGER,s       INTEGER}Name ::= CHOICE {                                             -- 证书发行者名称存储结构RDNSequence
}RDNSequence ::= SEQUENCE OF RelativeDistinguishedNameRelativeDistinguishedName ::= SET OF AttributeTypeAndValueAttributeTypeAndValue ::= SEQUENCE {type     AttributeType,value    AttributeValue
}AttributeType ::= OBJECT IDENTIFIERAttributeValue ::= ANY DEFINED BY AttributeTypeValidity ::= SEQUENCE {                                       -- 证书有效期存储结构notBefore      Time,                                      -- 证书有效期起始时间notAfter       Time                                       -- 证书有效期终止时间
}Time ::= CHOICE {utcTime        UTCTime,generalTime    GeneralizedTime
}UniqueIdentifier ::= BIT STRING                               -- 证书唯一标识存储结构SubjectPublicKeyInfo ::= SEQUENCE {                           -- 证书公钥存储结构algorithm            AlgorithmIdentifier,                 -- 公钥算法subjectPublicKey     BIT STRING                           -- 公钥值
}subjectPublicKey:                                             -- RSA算法时的公钥值RSAPublicKey ::= SEQUENCE { modulus            INTEGER,publicExponent     INTEGER}Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension            -- 拓展部分存储结构Extension ::= SEQUENCE {extnID      OBJECT IDENTIFIER,critical    BOOLEAN DEFAULT FALSE,extnValue   OCTET STRING}

输出效果

C++代码

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <cstdlib>using namespace std;struct Seg {int num;Seg(unsigned char s){num = (int)s;};Seg() {num = -1;}
};typedef struct Seg Seg;struct TLV {Seg type;vector<Seg> length;vector<Seg> value;
};typedef struct TLV TLV;struct SignatureAlgorithm {TLV algorithm;TLV parameters;
};struct subjectPublicKey {TLV algorithm;TLV parameters;TLV PKey;
};struct SignatureValue {TLV signatureValue;
};struct signatureArray {TLV s1, s2;
};typedef struct SignatureAlgorithm SignatureAlgorithm;
typedef struct subjectPublicKey subjectPublicKey;
typedef struct SignatureValue SignatureValue;
typedef struct signatureArray signatureArray;struct TbsCertificate{TLV version;TLV serialNumber;SignatureAlgorithm signature;vector<signatureArray> issuer_;vector<TLV> validity;vector<signatureArray> subject_;subjectPublicKey subjectPublicKeyInfo;TLV issuerUniqueID;TLV subjectUniqueID;vector<TLV> extensions;
};struct X509cer {struct TbsCertificate catb;struct SignatureAlgorithm casa;struct SignatureValue casv;
};class X509Reader {private:vector<Seg> segList;vector<TLV> tlvList;struct X509cer x509cert;map<string, string> OIDMap;
public:X509Reader() {OIDMap.insert(pair<string, string>("1.2.840.10040.4.1","DSA"));OIDMap.insert(pair<string, string>("1.2.840.10040.4.3","sha1DSA"));OIDMap.insert(pair<string, string>("1.2.840.113549.1.1.1","RSA"));OIDMap.insert(pair<string, string>("1.2.840.113549.1.1.2","md2RSA"));OIDMap.insert(pair<string, string>("1.2.840.113549.1.1.3","md4RSA"));OIDMap.insert(pair<string, string>("1.2.840.113549.1.1.4","md5RSA"));OIDMap.insert(pair<string, string>("1.2.840.113549.1.1.5","sha1RSA"));OIDMap.insert(pair<string, string>("1.2.840.113549.1.1.11","sha256RSA"));OIDMap.insert(pair<string, string>("1.2.840.10045.2.1","ECC"));OIDMap.insert(pair<string, string>("1.2.840.10045.3.1.7","ECDSA_P256"));OIDMap.insert(pair<string, string>("2.5.4.6","C"));OIDMap.insert(pair<string, string>("2.5.4.8","S"));OIDMap.insert(pair<string, string>("2.5.4.7","L"));OIDMap.insert(pair<string, string>("2.5.4.10","O"));OIDMap.insert(pair<string, string>("2.5.4.11","OU"));OIDMap.insert(pair<string, string>("2.5.4.3","CN"));}void loadFile(string filename) {std::ifstream file;file.open(filename.c_str(), ios::in|ios::binary);while(!file.eof()) {char first;file.read(&first, 1);segList.push_back(Seg((unsigned char)first));}file.close();}void compileContent() {for(int i = 0; i < segList.size(); ) {if(segList[i].num >> 6 == 2) {int n = segList[i].num & 0x1f;if(n == 3) {TLV t;t.type = segList[i];if(segList[i+1].num <= 0x7f) {t.length.push_back(segList[i+1]);i += 2;}else {int l = segList[i+1].num-0x80;int s = 0, base = 1;for(int j = i+2+l-1; j >= i+2; j--) {s += segList[j].num * base;base *= 256;}for(int j = i+1; j < i+2+l; j++) {t.length.push_back(segList[j]);}i += 2+l;}tlvList.push_back(t);}else {TLV t;t.type = segList[i];t.length.push_back(segList[i+1]);tlvList.push_back(t);i += 2;}}else {if(segList[i].num >> 5 == 1) {TLV t;t.type = segList[i];if(segList[i+1].num <= 0x7f) {t.length.push_back(segList[i+1]);i += 2;}else {int l = segList[i+1].num-0x80;int s = 0, base = 1;for(int j = i+2+l-1; j >= i+2; j--) {s += segList[j].num * base;base *= 256;}for(int j = i+1; j < i+2+l; j++) {t.length.push_back(segList[j]);}i += 2+l;}tlvList.push_back(t);}else {TLV t;t.type = segList[i];if(segList[i+1].num <= 0x7f) {t.length.push_back(segList[i+1]);for(int j = i+2; j < i+2+segList[i+1].num; j++) {t.value.push_back(segList[j]);}i += segList[i+1].num + 2;}else {int l = segList[i+1].num-0x80;int s = 0, base = 1;for(int j = i+2+l-1; j >= i+2; j--) {s += segList[j].num * base;base *= 256;}for(int j = i+1; j < i+2+l; j++) {t.length.push_back(segList[j]);}for(int j = i+2+l; j < i+2+l+s; j++) {t.value.push_back(segList[j]);}i += 2+l+s;}tlvList.push_back(t);}}}}void showX509() {int count = 0, extensionSize = 0;bool isExtension = false;bool isBlock31 = false;for(int i = 0; i < tlvList.size()-1; i++) {if(isExtension){extensionSize -= 1 + tlvList[i].length.size() +  tlvList[i].value.size();}if(tlvList[i].type.num == 0x31) {isBlock31 = true;continue;}else {if(tlvList[i].type.num == 0x30 && isBlock31 == false) {count++;continue;}else if(tlvList[i].type.num == 0x30 && isBlock31 == true) {isBlock31 = false;continue;}else if(tlvList[i].type.num == 0xa3) {count++;isExtension = true;int base = 1;for(int j = tlvList[i].length.size()-1; j >= 1; j--){extensionSize += tlvList[i].length[j].num * base;base *= 256;}continue;}}if(count == 2) {if(tlvList[i].type.num == 0xa0) {x509cert.catb.version = tlvList[i+1];i++;}else{x509cert.catb.serialNumber = tlvList[i];}}else if(count == 3) {if(tlvList[i].type.num == 0x06) {x509cert.catb.signature.algorithm = tlvList[i];}else {x509cert.catb.signature.parameters = tlvList[i];}}else if(count == 4) {signatureArray a;if(tlvList[i].type.num == 0x06) {a.s1 = tlvList[i];a.s2 = tlvList[i+1];x509cert.catb.issuer_.push_back(a);i+=1;}}else if(count == 5) {x509cert.catb.validity.push_back(tlvList[i]);x509cert.catb.validity.push_back(tlvList[i+1]);i+=1;}else if(count == 6) {signatureArray a;if(tlvList[i].type.num == 0x06) {a.s1 = tlvList[i];a.s2 = tlvList[i+1];x509cert.catb.subject_.push_back(a);i+=1;}}else if(count == 8) {if(tlvList[i].type.num == 0x06) {subjectPublicKey sbk;sbk.algorithm = tlvList[i];sbk.parameters = tlvList[i+1];sbk.PKey = tlvList[i+2];x509cert.catb.subjectPublicKeyInfo = sbk;i+=2;}}else if(count >= 9 && isExtension) {if(extensionSize >= 0) {x509cert.catb.extensions.push_back(tlvList[i]);}if(extensionSize == 0) {isExtension = false;}}else {if(tlvList[i].type.num == 0x06) {x509cert.casa.algorithm = tlvList[i];x509cert.casa.parameters = tlvList[i+1];x509cert.casv.signatureValue = tlvList[i+2];i += 2;}}}}string formatDate(TLV& p) {string result = "20";if(p.type.num == 0x17) {int count = 0;for(int i = 0; i < p.value.size()-1; i+=2){result = result + (char)p.value[i].num + (char)p.value[i+1].num;if(count <= 1){result += "/";}else if(count == 2) {result += " ";}else if(count <= 4){result += ":";}count++;}return result + " GMT";}else {return "";}}string formatOID(TLV& p) {string result = "";char num[9];vector<int> V;if(p.type.num == 0x06) {for(int i = 0; i < p.value.size(); i++){if(i == 0) {int v2 = p.value[i].num % 40;int v1 = (p.value[i].num -v2) / 40;V.push_back(v1);V.push_back(v2);}else {int j = i, res = 0;int base = 128;while(p.value[j].num >= 0x80){j++;}res = p.value[j].num;for(int k = j-1; k >= i; k--) {res += (p.value[k].num - 0x80) * base;base *= 128;}V.push_back(res);i = j;}}for(int i = 0; i < V.size(); i++) {sprintf(num, "%d",V[i]);result += num;if(i < V.size()-1){result += ".";}}return OIDMap[result];}else {return "";}}void displayOrigin() {int count = 0;for(int i = 0; i < segList.size(); i++) {printf("%02x ", segList[i].num);count++;if(count == 16){cout << endl;count = 0;}}}void displayTLVOrigin() {int count = 0;bool isBlock31 = false;for(int i = 0; i < tlvList.size(); i++) {if(tlvList[i].type.num == 0x31) {isBlock31 = true;}else {if(tlvList[i].type.num == 0x30 && isBlock31 == false) {count++;}else if(tlvList[i].type.num == 0x30 && isBlock31 == true) {isBlock31 = false;}else if(tlvList[i].type.num == 0xa3){count++;}}cout << "Count: " << count << endl;printf("type: %02x ", tlvList[i].type);printf("length: ");for(int j = 0; j < tlvList[i].length.size(); j++) {printf("%02x ", tlvList[i].length[j]);}printf("value(%02x): ", tlvList[i].value.size());for(int j = 0; j < tlvList[i].value.size(); j++) {printf("%02x ", tlvList[i].value[j]);}printf("\n");}}void printValue(TLV& p, int mode = 0) {if(p.value.size() == 0){printf("NULL");}else{for(int i = 0; i < p.value.size(); i++) {if(p.type.num == 0x03 && i == 0) continue;if(p.type.num == 0x13) {printf("%c", p.value[i].num);}else {if(mode == 0) {printf("%02x ", p.value[i].num);}else{printf("%02x", p.value[i].num);}}}if (p.type.num == 0x0c) {printf("(UTF-8)");}}printf("\n");}void displayResult() {printf("Version: V%d\n", x509cert.catb.version.value[0].num+1);printf("SerialNumber: ");printValue(x509cert.catb.serialNumber, 1);printf("SignatureAlgorithm:\n    Algorithm: ");cout << formatOID(x509cert.catb.signature.algorithm) << endl;printf("    Params: ");printValue(x509cert.catb.signature.parameters);printf("Issuer: \n");for(int i = 0; i < x509cert.catb.issuer_.size(); i++) {cout << "    " << formatOID(x509cert.catb.issuer_[i].s1);printf(" = ");printValue(x509cert.catb.issuer_[i].s2);}printf("Validity:\n    notBefore: ");cout << formatDate(x509cert.catb.validity[0]) << endl;printf("    notAfter: ");cout << formatDate(x509cert.catb.validity[1]) << endl;printf("Subject:\n");for(int i = 0; i < x509cert.catb.subject_.size(); i++) {cout << "    " << formatOID(x509cert.catb.subject_[i].s1);printf(" = ");printValue(x509cert.catb.subject_[i].s2);}printf("subjectPublicKeyInfo:\n");printf("    Algorithm: ");cout << formatOID(x509cert.catb.subjectPublicKeyInfo.algorithm) << endl;printf("        Params: ");printValue(x509cert.catb.subjectPublicKeyInfo.parameters);printf("        PKey: ");printValue(x509cert.catb.subjectPublicKeyInfo.PKey);printf("issuerUniqueID: ");printValue(x509cert.catb.issuerUniqueID);printf("subjectUniqueID: ");printValue(x509cert.catb.subjectUniqueID);printf("Extensions:\n");printf("    Other: ellipsis\n");/* 拓展部分不翻译for(int i = 0; i < x509cert.catb.extensions.size(); i++) {if(x509cert.catb.extensions[i].type.num == 0x01) {printf("    isCACertification: ");printValue(x509cert.catb.extensions[i]);printf("    Other: ellipsis\n");break;}}*/printf("SignatureAlgorithm:\n");printf("    Algorithm: ");cout << formatOID(x509cert.casa.algorithm) << endl;printf("    Params: ");printValue(x509cert.casa.parameters);printf("SignatureValue: ");printValue(x509cert.casv.signatureValue);}
};int main() {X509Reader reader;reader.loadFile("DER_x509.cer");//reader.displayOrigin();reader.compileContent();//reader.displayTLVOrigin();reader.showX509();reader.displayResult();return 0;
}

X.509证书解析程序(C++版)相关推荐

  1. X.509证书解析和验签

    实现了ASN.1语法,对数字证书进行解析,并对RSA WITH SHA256的证书进行验签.使用.net core c#编写. ASN.1语法解析代码 using System; using Syst ...

  2. php x.509,php – 解析X509证书

    我想在php中解析X.509证书. 证书采用DER编码的X.509格式. 我尝试在php中使用openssl_x509_parse方法,但它不起作用. 证书数据是在mdm中为CertificateLi ...

  3. 什么是X.509证书?X.509证书工作原理及应用?

    X.509是公钥基础设施(PKI)的标准格式.X.509证书就是基于国际电信联盟(ITU)制定的X.509标准的数字证书.X.509证书主要用于识别互联网通信和计算机网络中的身份,保护数据传输安全.X ...

  4. rfc 5280 X.509 PKI 解析

    本文以博客园的证书为例讲解,不包含对CRL部分的翻译,如没有对第5章节以及6.3小节进行翻译 3.2. Certification Paths and Trust 下面简单介绍了Public-Key ...

  5. Hyperledger Fabric 1.0 实战开发系列 第⑤课 fabric 证书解析

    通过cryptogen生成所有证书文件后,以peerOrgannizations的第一个组织树org1为例,每个目录和对应文件的功能如下: ca: 存放组织的根证书和对应的私钥文件,默认采用EC算法, ...

  6. 【转】x.509证书在WCF中的应用(CS篇)

    [转自]x.509证书在WCF中的应用(CS篇) 为什么要用x.509证书? WCF的服务端和客户端之间,如 果不作任何安全处理(即服务端的<security mode="None&q ...

  7. textarea支持a标签_微慕小程序开源版A标签优化说明

    微慕WordPress小程序所有版本里,对于文章详情里文字内容的解析,都是通过开源组件:wxParse:不过这个组件已经停止维护,微慕小程序在这个组件上做了一些优化,让文章里文字在小程序显示更加完美. ...

  8. 实现中英文对接翻译小程序—最终版

    实现中英文对接翻译小程序-最终版 在原有界面上增加了新的标签和按钮 #encoding=utf-8 import json import requests import sys from tkinte ...

  9. X.509证书DN之详解

    X.509使用DN(Distinct Name)来唯一标识一个实体,其功能类似我们平常使用的ID,不过不同的是,DN不再是类似 123456 这样得数字标识,而是采用多个字段来标识一个实体,例如&qu ...

最新文章

  1. 日益谨慎的谷歌AI,会在自我限制中越走越慢吗?
  2. hdu4169_Wealthy Family_树形DP(2011美国区域赛)
  3. 百练OJ:2943:小白鼠排队
  4. 通信 / 各种协议默认端口汇总
  5. 【Android】Android Service 服务
  6. [JavaWeb-JavaScript]JavaScript_Global全局对象
  7. HAProxy+Hive构建高可用数据挖掘集群
  8. rtcp webrtc 接收_WebRTC RTP/RTCP 源码分析(四):RTCP 的接收和解析
  9. 变量unset与null的区别
  10. 固定资产中计算机软件类型,固定资产国标分类1.doc
  11. matlab读取图片亮度,Matlab读取BMP位图并显示亮度值三维图
  12. (自适应动态规划综述)
  13. MFC入门基础(十)静态文本框()、编辑框(Edit Control)
  14. C语言进阶第23式:#error和#line的使用分析
  15. Qt学习之界面UI编程应用
  16. C语言char类型的存储
  17. 《操作系统》第十二章习题加解析(重点学习内容)
  18. windows:将网络共享文件夹映射为网络硬盘
  19. Windows10常用快捷键汇总
  20. java字典初始化_在Java中用一组特定的数据初始化字典

热门文章

  1. 一文带你了解 AAVE,并实操
  2. 【C#/WPF】Bitmap、BitmapImage、ImageSource 、byte[]转换问题
  3. Java的宝贝——反射
  4. 八进制和十六进制表示
  5. 四月单向历——你是人间四月天
  6. 淘宝/天猫、拼多多、1688产品详情页API、SKU信息获取展示
  7. R语言使用ggplot2可视化甜甜圈图(Donut chart)
  8. 金蝶kis记账王凭证过账要不要要审核
  9. 关键帧提取——帧差法提取关键帧(2)
  10. 一些手机测试的英文缩写