使用Python Openssl庫解析X509證書信息


X.509 證書結構描述

常見的X.509證書格式包括:

后綴 作用
cer/crt 用於存放證書,它是2進制形式存放的,不含私鑰
pem 以Ascii來表示,可以用於存放證書或私鑰。
pfx/p12 用於存放個人證書/私鑰,他通常包含保護密碼,2進制方式。
p10 證書請求
p7r CA對證書請求的回復,只用於導入
p7b 以樹狀展示證書鏈(certificate chain),同時也支持單個證書,不含私鑰。

對於常見的https證書 一般是用crt或者pem來保存, http證書可電器網頁前的鎖按鈕得到, 並且進行導出

在這里插入圖片描述

證書數據結構

此證書結構來着白皮書
https://tools.ietf.org/html/rfc2459#section-4.1

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(可選),只在證書版本23中才有

        subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,

                             -- 證書主體ID(可選),只在證書版本23中才有

        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 }

參考博客:
https://blog.csdn.net/xy010902100449/article/details/52145009

源代碼

這里利用的是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())

編譯運行輸出結果

在這里插入圖片描述

windows 自帶的解析結果對比

在這里插入圖片描述

是完全相同的. 讀取成功


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM