我能够构建一个Python脚本来完成你正在寻找的事情。该脚本采用一个参数,<PEM FILE>
并返回包含此证书内容的 JSON 对象。
$ ./pem2json.py <PEM FILE>
NOTE:该脚本可以选择采用第二个参数,-d
如果您想查看更多转换,它将打印出调试信息。
Example
您可以从此网站下载示例 TLS 证书 -用于测试和验证的 X509 证书示例 http://fm4dd.com/openssl/certexamples.htm。具体来说,我将使用这个 PEM 文件:
-
2048 RSA 证书 http://fm4dd.com/openssl/source/PEM/certs/2048b-rsa-example-cert.pemPEM 格式 1050 字节
下载后,我将其作为参数传递给 Python 脚本:
$ ./pem2json.py 2048b-dsa-example-cert.pem
{"notBefore": "Aug 22 07:27:22 2012 GMT", "serialNumber": "0E02", "notAfter": "Aug 21 07:27:22 2017 GMT", "version": 1, "subject": [[["countryName", "JP"]], [["stateOrProvinceName", "Tokyo"]], [["organizationName", "Frank4DD"]], [["commonName", "www.example.com"]]], "issuer": [[["countryName", "JP"]], [["stateOrProvinceName", "Tokyo"]], [["localityName", "Chuo-ku"]], [["organizationName", "Frank4DD"]], [["organizationalUnitName", "WebCert Support"]], [["commonName", "Frank4DD Web CA"]], [["emailAddress", "[email protected] /cdn-cgi/l/email-protection"]]]}
Code
$ cat pem2json.py
#!/usr/bin/python
import json
import os
import ssl
import sys
from collections import OrderedDict
from pprint import pprint as pp
def main():
debug = False
if len(sys.argv) == 3:
if sys.argv[2] == "-d":
debug = True
if debug:
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
print("cli arg1: {:s}\n".format(sys.argv[1]))
cert_file_name = os.path.join(os.path.dirname(__file__), sys.argv[1])
try:
ordered_dict = OrderedDict()
ordered_dict = ssl._ssl._test_decode_cert(cert_file_name)
if debug: pp(ordered_dict)
except Exception as e:
print("Error decoding certificate: {:s}\n".format(e))
print(json.dumps(ordered_dict))
if __name__ == "__main__":
main()
调试输出
$ ./pem2json.py 2048b-dsa-example-cert.pem -d
Python 2.7.5 (default, Jul 13 2018, 13:06:57)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
cli arg1: 2048b-dsa-example-cert.pem
{'issuer': ((('countryName', u'JP'),),
(('stateOrProvinceName', u'Tokyo'),),
(('localityName', u'Chuo-ku'),),
(('organizationName', u'Frank4DD'),),
(('organizationalUnitName', u'WebCert Support'),),
(('commonName', u'Frank4DD Web CA'),),
(('emailAddress', u'[email protected] /cdn-cgi/l/email-protection'),)),
'notAfter': 'Aug 21 07:27:22 2017 GMT',
'notBefore': u'Aug 22 07:27:22 2012 GMT',
'serialNumber': u'0E02',
'subject': ((('countryName', u'JP'),),
(('stateOrProvinceName', u'Tokyo'),),
(('organizationName', u'Frank4DD'),),
(('commonName', u'www.example.com'),)),
'version': 1L}
{"notBefore": "Aug 22 07:27:22 2012 GMT", "serialNumber": "0E02", "notAfter": "Aug 21 07:27:22 2017 GMT", "version": 1, "subject": [[["countryName", "JP"]], [["stateOrProvinceName", "Tokyo"]], [["organizationName", "Frank4DD"]], [["commonName", "www.example.com"]]], "issuer": [[["countryName", "JP"]], [["stateOrProvinceName", "Tokyo"]], [["localityName", "Chuo-ku"]], [["organizationName", "Frank4DD"]], [["organizationalUnitName", "WebCert Support"]], [["commonName", "Frank4DD Web CA"]], [["emailAddress", "[email protected] /cdn-cgi/l/email-protection"]]]}
参考
- 将 openssl 命令的输出转换为 JSON https://stackoverflow.com/questions/43506011/convert-the-output-of-openssl-command-to-json/43506654
- Python 中的有序字典 https://www.geeksforgeeks.org/ordereddict-in-python/
- 18.2. json — JSON 编码器和解码器 https://docs.python.org/2/library/json.html
- PyFormat - 使用 % 和 .format() 非常有用! https://pyformat.info/
- 解析命令行参数的最佳方法是什么? https://stackoverflow.com/questions/20063/whats-the-best-way-to-parse-command-line-arguments
- 如何使用 python 解码 SSL 证书? https://stackoverflow.com/questions/16899247/how-can-i-decode-a-ssl-certificate-using-python