前言


基于python3 flet库实现了证书信息的提取,留作自用,如有错误欢迎指正。

正文


程序架构:

主程序 main.py

证书解析程序 certHandle.py

运行 python main.py

main.py

# -*- coding:utf-8 -*-
import base64
import traceback
import json
import flet as ft
from certHandle import get_info_from_cert_pem def main(page: ft.Page):
page.title = "证书查看工具"
page.scroll = "auto" def btn_submit_clicked(e):
if not txt_cert_in.value:
txt_cert_in.error_text = "请粘贴证书字符串"
page.update()
return
else:
cert_in = txt_cert_in.value if not dropdown_timezone.value:
dlg = ft.AlertDialog(
title=ft.Text("Error"),
content=ft.Text("请选择时区")
)
page.dialog = dlg
dlg.open = True
page.update()
return timezone = dropdown_timezone.value
use_local_time = False
if timezone == "local":
use_local_time = True err_msg = None
cert_out = None
try:
cert_out = get_info_from_cert_pem(cert_in, use_local_time)
cert_out = json.loads(cert_out)
cert_out = json.dumps(cert_out, indent=4)
except Exception as e:
err_msg = traceback.format_exc() if cert_out is None or err_msg is not None:
txt_cert_out.error_text = "证书解析失败"
txt_cert_out.value = ""
page.update()
else:
txt_cert_out.value = cert_out
page.update() def btn_clean_clicked(e):
txt_cert_in.value = ""
txt_cert_out.value = ""
page.update() # 证书输入
txt_cert_in = ft.TextField(
label="请粘贴证书字符串"
) # 时间下拉框提示
txt_timezone = ft.Text("请选择时区")
# 时间下拉框
dropdown_timezone = ft.Dropdown(
width=130,
options=[
ft.dropdown.Option(key="org", text="原始时区"),
ft.dropdown.Option(key="local", text="本地时区"),
]
) # 确认按钮
btn_submit = ft.ElevatedButton(text="确认", on_click=btn_submit_clicked) # 清空按钮
btn_clean = ft.ElevatedButton(text="清空", on_click=btn_clean_clicked) # 证书输出
txt_cert_out = ft.TextField(
label="证书解析结果",
multiline=True,
height=400,
text_align=ft.TextAlign.LEFT
)
# txt_cert_out = ft.Text(selectable=True, text_align=ft.TextAlign.LEFT)
# txt_cert_out = ft.Markdown(
# selectable=True,
# extension_set=ft.MarkdownExtensionSet.GITHUB_WEB,
# on_tap_link=lambda e:page.launch_url(e.data)
# ) page.add(
# 输入证书内容
txt_cert_in,
# 时区选择
ft.Row(
[
txt_timezone,
dropdown_timezone
]
),
ft.Divider(),
# 解析结果
txt_cert_out,
# 按钮行
ft.Row(
[
btn_submit,
btn_clean
]
)
) if __name__ == "__main__":
ft.app(target=main)
# ft.app(target=main, view=ft.AppView.WEB_BROWSER)

certHandle.py

import base64
import hashlib
import traceback from OpenSSL.crypto import load_certificate, FILETYPE_PEM, dump_publickey, FILETYPE_ASN1
from cryptography import x509
from cryptography.hazmat.backends import default_backend from base64 import b64encode
from datetime import datetime
import pytz
import json from cryptography.hazmat.primitives import hashes def get_info_from_cert_pem(cert_str: str, use_local_time:bool = False) -> str | None:
"""
从证书获取详细信息
"""
cert_str = reformat_cert(cert_str)
info_dict = {}
try:
cert = load_certificate(FILETYPE_PEM, cert_str)
# 备用解析 - 另一种解析方式
cert_standby = x509.load_pem_x509_certificate(cert_str.encode(), default_backend()) # 签发者信息
issuer = cert.get_issuer()
issuer_info = analy_components(issuer.get_components())
issuer_hash = hex(issuer.hash()).replace("0x", "")
info_dict["issuer"] = {}
info_dict["issuer"]["info"] = issuer_info
info_dict["issuer"]["hash"] = issuer_hash # 主体信息
subject = cert.get_subject()
subject_info = analy_components(subject.get_components())
subject_hash = hex(subject.hash()).replace("0x", "") info_dict["subject"] = {}
info_dict["subject"]["info"] = subject_info
info_dict["subject"]["hash"] = subject_hash # 证书串号
serial_num = hex(cert.get_serial_number()).replace("0x", "")
info_dict["serial_num"] = serial_num # 有效期
valid_before = format_time(cert.get_notBefore(), to_local=use_local_time)
valid_after = format_time(cert.get_notAfter(), to_local=use_local_time)
info_dict["valid_before"] = valid_before
info_dict["valid_after"] = valid_after # 版本信息 -- 好像不准
# version = cert.get_version()
version = cert_standby.version info_dict["cert_version"] = version.name # 签名算法
algorithm = cert.get_signature_algorithm().decode() info_dict["cert_algorithm"] = algorithm # 证书指纹
cert_thumbprint_sha1 = cert.digest("SHA1").decode()
cert_thumbprint_sha256 = cert.digest("SHA256").decode()
cert_thumbprint_md5 = cert.digest("MD5").decode() info_dict["cert_thumbprint"] = {}
info_dict["cert_thumbprint"]["sha1"] = cert_thumbprint_sha1
info_dict["cert_thumbprint"]["sha256"] = cert_thumbprint_sha256
info_dict["cert_thumbprint"]["md5"] = cert_thumbprint_md5 # 证书主体指纹
cert_tbs_thumbprint_sha1 = hashlib.sha1(cert_standby.tbs_certificate_bytes).digest().hex()
cert_tbs_thumbprint_sha1_b64 = base64.b64encode(hashlib.sha1(cert_standby.tbs_certificate_bytes).digest()).decode() info_dict["cert_tbs_thumbprint"] = {}
info_dict["cert_tbs_thumbprint"]["sha1"] = cert_tbs_thumbprint_sha1
info_dict["cert_tbs_thumbprint"]["sha1_b64"] = cert_tbs_thumbprint_sha1_b64 # 公钥指纹
public_key = cert.get_pubkey()
public_key_pem = dump_publickey(FILETYPE_ASN1, public_key)
public_key_thumbprint_sha1 = hashlib.sha1(public_key_pem).digest().hex()
public_key_thumbprint_sha256 = hashlib.sha256(public_key_pem).digest().hex()
public_key_thumbprint_sha1_b64 = base64.b64encode(hashlib.sha1(public_key_pem).digest()).decode() info_dict["public_key_thumbprint"] = {}
info_dict["public_key_thumbprint"]["sha1"] = public_key_thumbprint_sha1
info_dict["public_key_thumbprint"]["sha256"] = public_key_thumbprint_sha256
info_dict["public_key_thumbprint"]["sha1_b64"] = public_key_thumbprint_sha1_b64 # 扩展信息 info_dict["extensions"] = {} extensions_cnt = cert.get_extension_count()
for i in range(extensions_cnt):
name = cert.get_extension(i).get_short_name().decode()
value = cert.get_extension(i) if name == "subjectKeyIdentifier":
thumbprint = cert_standby.extensions.get_extension_for_oid(x509.oid.ExtensionOID.SUBJECT_KEY_IDENTIFIER).value.digest
info_dict["extensions"][name] = {}
info_dict["extensions"][name]["value"] = "{0}".format(value)
info_dict["extensions"][name]["b64"] = base64.b64encode(thumbprint).decode()
else:
info_dict["extensions"][name] = "{0}".format(value) except Exception as e:
return traceback.format_exc()
info_str = json.dumps(info_dict)
return info_str def analy_components(components: list | None) -> str | None:
"""
解析 list[tuple(b'',b'')] 类型
:return:
"""
res = ""
try:
tmp_list = []
for i in components:
(k, v) = i
tmp_list.append("{0}={1}".format(k.decode(), v.decode()))
res = ",".join(tmp_list)
except Exception as e:
traceback.print_exc()
return res def format_time(time_org: bytes, to_local:bool = False)->str:
"""
将证书中得到的时间格式化
:param time_org: 原始时间字节串
:param to_local: 是否转换为本地时间
:return:
"""
time_str = time_org.decode("utf-8")
try: datetime_obj = datetime.strptime(time_str, "%Y%m%d%H%M%SZ")
# 上海时区
local_tz = pytz.timezone('Asia/Shanghai')
datetime_local = pytz.utc.localize(datetime_obj).astimezone(local_tz)
if to_local:
time_str = datetime_local.strftime("%Y-%m-%d %H:%M:%S")
else:
time_str = datetime_obj.strftime("%Y-%m-%d %H:%M:%S")
except Exception as e:
traceback.print_exc()
return time_str def reformat_cert(cert_in:str)->str|None:
"""
重新格式化证书
:param cert_in:证书字符串
:return:
"""
cert_out = None
cert_header = "-----BEGIN CERTIFICATE-----"
cert_tail = "-----END CERTIFICATE-----"
if cert_in:
if "\r" in cert_in:
cert_in = cert_in.replace("\r","")
if "\\n" in cert_in:
cert_in = cert_in.replace("\\n", "")
if "\n" in cert_in:
cert_in = cert_in.replace("\n", "")
cert_in = cert_in.replace(cert_header, "")
cert_in = cert_in.replace(cert_tail, "")
cert_body = base64.b64encode(base64.b64decode(cert_in.encode())).decode()
cert_out = "{0}\n{1}\n{2}".format(cert_header, cert_body, cert_tail)
return cert_out

基于python3 flet库的证书查看工具的更多相关文章

  1. 基于Python3的漏洞检测工具 ( Python3 插件式框架 )

    目录 Python3 漏洞检测工具 -- lance screenshot requirements 关键代码 usage documents Any advice or sugggestions P ...

  2. 7.Python3标准库--文件系统

    ''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...

  3. SSL证书在线工具

    证书在线工具 如果您是第一次申请SSL证书,如果您对您的服务器如何使用SSL证书还不熟悉的话,我们推荐您使用本套工具,本套工具支持所有SSL服务器证书格式和各种WEB服务器.帮助您在线生成CSR文件, ...

  4. lucene 索引查看工具

    luke 是 lucene 索引查看工具,基于 swing 开发的,是 lucene.solr.nutch 开发过程中不可或缺的工具.在测试搜索过程,进程出现搜不到东西或者搜到的东西不是想要的结果时, ...

  5. Python3 实现简易局域网视频聊天工具

    Python3 实现简易局域网视频聊天工具   1.环境 操作系统为 Ubuntu 16.04 python 3.5opencv-python 3.4.1.15numpy 1.14.5PyAudio ...

  6. 8.Python3标准库--数据持久存储与交换

    ''' 持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区. 标准库包含很多模块可以处理不同情况下的这两个方面 有两个模块可以将对象转换为一 ...

  7. Python3 标准库

    Python3标准库 更详尽:http://blog.csdn.net/jurbo/article/details/52334345 文本 string:通用字符串操作 re:正则表达式操作 diff ...

  8. Python 简易web日志查看工具&可改装为命令行工具

    Python 简易web日志查看工具&可改装为命令行工具 效果图 原理 利用python的paramiko库模拟ssh登录操作,并执行tail命令 所需库 flask.paramiko.gev ...

  9. 登峰造极,师出造化,Pytorch人工智能AI图像增强框架ControlNet绘画实践,基于Python3.10

    人工智能太疯狂,传统劳动力和内容创作平台被AI枪毙,弃尸尘埃.并非空穴来风,也不是危言耸听,人工智能AI图像增强框架ControlNet正在疯狂地改写绘画艺术的发展进程,你问我绘画行业未来的样子?我只 ...

  10. TinyWeb v1.0 正式完成第一个Release版本(功能基于 libuv 跨平台库)

    使用方法很简单,很容易融入现有项目,使现有项目拥有Web网站功能和WebSocket,以及Socket直连! 并且包含了一个跨平台(windows/linux)工具集合; 嗯,也挺棒的^,^ 在项目中 ...

随机推荐

  1. ElasticView 是一款用来监控elasticsearch状态和操作elasticsearch索引的web可视化工具。

    ElasticView 是一款用来监控elasticsearch状态和操作elasticsearch索引的web可视化工具. 它由golang开发而成,具有部署方便,占用内存小等优点 es连接树管理( ...

  2. 联想G470安装黑苹果

    macos10136 黑苹果usb无线网卡 1.系统下载: 下面是我自制的带clover 4596版本的u盘镜像: 链接: https://pan.baidu.com/s/1wRdVddwkei7bf ...

  3. 深度学习框架火焰图pprof和CUDA Nsys配置指南

    注:如下是在做深度学习框架开发时,用到的火焰图pprof和 CUDA Nsys 配置指南,可能对大家有一些帮助,就此分享.一些是基于飞桨的Docker镜像配置的. 一.环境 & 工具配置 0. ...

  4. grads读取netcdf文件,报错SDF file has no discernable X coordinate解决办法

    1.netcdf文件格式说明 netCDF数据格式在气象中有广泛的应用,这种格式有一定的复杂性.作为数据的使用者可以不用对数据格式了解得很详细,不过大致的了解还是有必要的.netCDF是自描述的二进制 ...

  5. C语言:实现数组的删除和增加

    /*      删除方法:     如:12  32  56  84  95     用覆盖的方法     若删除第三个,则第四个要覆盖第三个,第五个要覆盖第四个     覆盖完:12  32  84 ...

  6. AIRIOT物联网低代码平台如何配置http客户端?

    AIRIOT物联网低代码平台一直保持和市场脉搏同频,支持市面上95%以上驱动,驱动能力夯实,大大满足任意数据采集需求.AIRIOT支持分布式部署,数据采集能力强,解决海量数据采集一台服务器采集困难的问 ...

  7. 生物医学顶刊论文(JBHI-2024):TransFOL:药物相互作用中复杂关系推理的逻辑查询模型

    (2024.5.17)JBHI-TransFOL:药物相互作用中复杂关系推理的逻辑查询模型 论文题目:TransFOL: A Logical Query Model for Complex Relat ...

  8. 表单设计——《HTML5 CSS3从入门到精通》

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. json 编码后导致数字变为科学计数,从而导致解码后签名与编码前签名不正确的解决办法。

    docoder := json.NewDecoder(strings.NewReader(string(originData))) docoder.UseNumber() _ = docoder.De ...

  10. 微信小程序预约视频号直播

    一.概述 微信小程序提供了可以唤起预约视频号直播弹窗的接口 reserveChannelsLive,该接口接收一个参数 noticeId,通过 getChannelsLiveNoticeInfo 接口 ...