证书文件解析Certificates file

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)

SSL通信的基础就是证书认证:通过认证完成信任关系建立;通过证书中携带的公钥,与持有的私钥,完成信息密钥交换,文件签名校验。

证书如此关键,但证书文件通过文本打开看的话,一般要么采用Der格式的二进制文件,也或Pem格式(base64加密Der格式后添加首位行标示的文件)。是无法看出什么有用的信息的。
那证书如何解析呢?
证书真实包含了那些信息,是否有隐藏的信息?
我们自己去写程序解析看看就能看出相关的真实情况。

证书Certificates file内容:

cert文件格式通常采用x.509 standard,包含公钥&加密算法,身份信息,证书机构签名或自签名。
An X.509 certificate contains a public key and an identity (a hostname, or an organization, or an individual), and is either signed by a certificate authority or self-signed. 

cert文件包含的信息内容格式:

  • Certificate
    • Version Number
    • Serial Number
    • Signature Algorithm ID
    • Issuer Name
    • Validity period
      • Not Before
      • Not After
    • Subject name
    • Subject Public Key Info
      • Public Key Algorithm
      • Subject Public Key
    • Issuer Unique Identifier (optional)
    • Subject Unique Identifier (optional)
    • Extensions (optional)
      • ...
  • Certificate Signature Algorithm
  • Certificate Signature

 

证书Certificates file存储格式:

证书存储格式,常见的两种格式:Der格式与Pem格式:
Der格式为二进制格式;
Pem格式为Base64编码的Der格式并添加"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"。

There are several commonly used filename extensions for X.509 certificates. 
.cer, .crt, .der – usually in binary DER form, but Base64-encoded certificates are common too (see .pem above)
.pem – (Privacy-enhanced Electronic Mail) Base64 encoded DER certificate, enclosed between "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----"

Der格式的全称为:Distinguished Encoding Rules,是著名的Asn.1(Abstract Syntax Notation One)编码规则之一,格式为:
二进制:类型,长度,数据,(可选存在的结束符)

The encoding of data does generally consist of four components which appear in the following order:

Identifier octets
Type
Length octets
Length
Contents octets
Value
End-of-contents octets

The End-of-contents octets are optional and only used if the indefinite length form is used. The Contents octet may also be omitted if there is no content to encode like in the NULL type.

length可能是1个字节,也可能是81+1字节,82+2字节,83+3字节,84+4字节,规则如下:

  • any length from 0 up to 0x7F is encoded as one byte in 00..7F;
  • any higher length up to 0xFF is encoded as prefix 81 and one byte;
  • any higher length up to 0xFFFF is encoded as prefix 82 and two bytes;
  • any higher length up to 0xFFFFFF is encoded as prefix 83 and three bytes;
  • any higher length up to 0xFFFFFFFF is encoded as prefix 84 and four bytes;

例如:下面四个字节编码字符的解析结果
13 02 43 4E
13 -- Type=PrintableString
02 -- Length = 2
43 4E -- Data = CN
 

证书Certificates file解析实现:

“人生苦短,也用Python”,也采用Python解析实现,借助python的ansi库,解析Der或Pem格式的证书文件:

代码如下:
cert文件中采用的asn1编码是一层一层进行编码的,asn1每次解析一个编码组,采用递归解析是一个不错的选择。
(下面代码做了适配,也支持der/pem格式的scr和key文件的解析)

#!/usr/bin/python
#(Owed by: http://blog.csdn.net/chunyexiyu)
import asn1
import sys
import base64
import re

if (len(sys.argv) != 3):
    print("Useage: {} certfile pem/der)".format(sys.argv[0]))
    sys.exit(1)

def getTagDesc(tag):
    if (tag.cls == 0x80):
        return asn1.Classes(tag.cls).name + "[" + str(tag.nr) + "]"
    try:
        return asn1.Numbers(tag.nr).name + str(tag)
    except:
        return asn1.Types(tag.typ).name + str(tag)

der = "" 
if (len(sys.argv) == 3 and sys.argv[2] == 'der'):
    fd = open(sys.argv[1], 'rb')
    der = fd.read()
    fd.close()
else:
    fd = open(sys.argv[1])
    pem = fd.read()
    fd.close()
    pem = re.sub('[-]+[A-Z ]+[-]+\n','',pem) 
    der = base64.b64decode(pem)

def analyseAsn1(der, tab=''):
    decoder = asn1.Decoder()
    decoder.start(der)
    while(True):
        if (decoder.eof()):
            break;
        
        tag = decoder.peek()
        if (tag.cls == 0x80): #context to octstring 
            tag = asn1.Tag(4, tag.typ, tag.cls)
            tagReal, value = decoder.read(tag.nr)
        else:
            tagReal, value = decoder.read()

        if (tag is None):
            break;

        print('\n{}{}:'.format(tab, getTagDesc(tagReal)), end='')
        isSubDecode = False;
        if (tag.typ != asn1.Types.Primitive.value):     #constructed
            isSubDecode = analyseAsn1(value, tab + "    ")
        elif (tag.cls == 0):        #Universal
            if (tag.nr == 4 and value[0] == 0x30):      #ocstring
                isSubDecode = analyseAsn1(value, tab + "    ")
            elif (tag.nr == 3 and value[0:2] == b'\x00\x30'):     #binary string
                isSubDecode = analyseAsn1(value[1:], tab + "    ")

        if (not isSubDecode):
            if (tag.nr in (3,4)):   #binarystring, octstring or big integer
                print('0x{}'.format(value.hex()), end='')
            elif (tag.nr == 2 and value.bit_length() > 64): #int 
                print('0x{}'.format(asn1.Encoder._encode_integer(value).hex()), end='')
            elif (tag.nr == 0x1e):  #unicodestring
                print(value.decode('utf8'), end='')
            elif (tag.nr == 0):
                print('0x{}'.format(value.hex()), end='')
            else:
                print(value if (value) else '', end='')
    return True;

analyseAsn1(der)
print("")

解析效果形如:

SequenceTag(nr=16, typ=32, cls=0):
    SequenceTag(nr=16, typ=32, cls=0):
        IntegerTag(nr=2, typ=0, cls=0):9912317898791003722
        SequenceTag(nr=16, typ=32, cls=0):
            ObjectIdentifierTag(nr=6, typ=0, cls=0):1.2.840.113549.1.1.11
            NullTag(nr=5, typ=0, cls=0):
        SequenceTag(nr=16, typ=32, cls=0):
            SetTag(nr=17, typ=32, cls=0):
                SequenceTag(nr=16, typ=32, cls=0):
                    ObjectIdentifierTag(nr=6, typ=0, cls=0):2.5.4.6
                    PrintableStringTag(nr=19, typ=0, cls=0):CN
...

  

其它解析实现:

如果不关注证书内部细节的话,也可以通过已有的工具来解析证书,查看证书中的内容:如下

通过openssl可以解析cert pem文件:
例如:openssl x509 -in cert.pem -noout -text

一些网站也提供了解析pem的实现,和自己实现效果类似:
例如:https://lapo.it/asn1js/

另外可以参考以下的这些文档,进一步对证书文件加深理解。

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)

参考:https://docs.python.org/3/library/ssl.html
参考:https://media.readthedocs.org/pdf/python-asn1/latest/python-asn1.pdf
参考:https://stackoverflow.com/questions/16899247/how-can-i-decode-a-ssl-certificate-using-python
参考:https://pypi.org/project/asn1/
参考:https://en.wikipedia.org/wiki/Certificate_authority
参考:https://en.wikipedia.org/wiki/X.509
参考:https://github.com/andrivet/python-asn1/blob/master/src/asn1.py
参考:https://en.wikipedia.org/wiki/X.690#DER_encoding
参考:https://crypto.stackexchange.com/questions/21102/what-is-the-ssl-private-key-file-format

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春夜喜雨

稀罕你的喜欢!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值