X.509 证书结构描述
常见的X.509证书格式包括:
对于常见的https证书 一般是用crt或者pem来保存, http证书可电器网页前的锁按钮得到, 并且进行导出.
证书数据结构
此证书结构来着白皮书
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) }
CertificateSerialNumber ::= INTEGER
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL }
parameters:
Dss-Parms ::= SEQUENCE { -- parameters ,DSA(DSS)算法时的parameters,
RSA算法没有此参数
p INTEGER,
q INTEGER,
g INTEGER }
signatureValue:
Dss-Sig-Value ::= SEQUENCE { -- sha1DSA签名算法时,签名值
r INTEGER,
s INTEGER }
Name ::= CHOICE {
RDNSequence }
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
RelativeDistinguishedName ::=
SET OF AttributeTypeAndValue
AttributeTypeAndValue ::= SEQUENCE {
type AttributeType,
value AttributeValue }
AttributeType ::= OBJECT IDENTIFIER
AttributeValue ::= ANY DEFINED BY AttributeType
Validity ::= SEQUENCE {
notBefore Time, -- 证书有效期起始时间
notAfter Time -- 证书有效期终止时间
}
Time ::= CHOICE {
utcTime UTCTime,
generalTime GeneralizedTime }
UniqueIdentifier ::= BIT STRING
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier, -- 公钥算法
subjectPublicKey BIT STRING -- 公钥值
}
subjectPublicKey:
RSAPublicKey ::= SEQUENCE { -- RSA算法时的公钥值
modulus INTEGER, -- n
publicExponent INTEGER -- e -- }
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING }
源码
这里利用的是python3 的 Openssl 库进行解析, 此库的说明文档如下,
https://pyopenssl.org/en/0.15.1/api/crypto.html#x509name-objects
通过阅读说明文档, 可以轻松读取证书相关信息
代码如下
import OpenSSL
import time
from dateutil import parser
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open("test.cer").read())
certIssue = cert.get_issuer()
print ("证书版本: ",cert.get_version() + 1)
print ("证书序列号: ",hex(cert.get_serial_number()))
print ("证书中使用的签名算法: ",cert.get_signature_algorithm().decode("UTF-8"))
print ("颁发者: ",certIssue.commonName)
datetime_struct = parser.parse(cert.get_notBefore().decode("UTF-8"))
print ("有效期从: ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))
datetime_struct = parser.parse(cert.get_notAfter().decode("UTF-8"))
print ("到: ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))
print ("证书是否已经过期: ",cert.has_expired())
print("公钥长度" ,cert.get_pubkey().bits())
print("公钥:\n" ,OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, cert.get_pubkey()).decode("utf-8"))
print("主体信息:")
print("CN : 通用名称 OU : 机构单元名称")
print("O : 机构名 L : 地理位置")
print("S : 州/省名 C : 国名")
for item in certIssue.get_components():
print(item[0].decode("utf-8"), " —— ",item[1].decode("utf-8"))
print(cert.get_extension_count())
编译运行输出结果
参考文献
- https://blog.csdn.net/qq874455953/article/details/85041415