基于python3 flet库的证书查看工具
前言
基于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库的证书查看工具的更多相关文章
- 基于Python3的漏洞检测工具 ( Python3 插件式框架 )
目录 Python3 漏洞检测工具 -- lance screenshot requirements 关键代码 usage documents Any advice or sugggestions P ...
- 7.Python3标准库--文件系统
''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...
- SSL证书在线工具
证书在线工具 如果您是第一次申请SSL证书,如果您对您的服务器如何使用SSL证书还不熟悉的话,我们推荐您使用本套工具,本套工具支持所有SSL服务器证书格式和各种WEB服务器.帮助您在线生成CSR文件, ...
- lucene 索引查看工具
luke 是 lucene 索引查看工具,基于 swing 开发的,是 lucene.solr.nutch 开发过程中不可或缺的工具.在测试搜索过程,进程出现搜不到东西或者搜到的东西不是想要的结果时, ...
- Python3 实现简易局域网视频聊天工具
Python3 实现简易局域网视频聊天工具 1.环境 操作系统为 Ubuntu 16.04 python 3.5opencv-python 3.4.1.15numpy 1.14.5PyAudio ...
- 8.Python3标准库--数据持久存储与交换
''' 持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区. 标准库包含很多模块可以处理不同情况下的这两个方面 有两个模块可以将对象转换为一 ...
- Python3 标准库
Python3标准库 更详尽:http://blog.csdn.net/jurbo/article/details/52334345 文本 string:通用字符串操作 re:正则表达式操作 diff ...
- Python 简易web日志查看工具&可改装为命令行工具
Python 简易web日志查看工具&可改装为命令行工具 效果图 原理 利用python的paramiko库模拟ssh登录操作,并执行tail命令 所需库 flask.paramiko.gev ...
- 登峰造极,师出造化,Pytorch人工智能AI图像增强框架ControlNet绘画实践,基于Python3.10
人工智能太疯狂,传统劳动力和内容创作平台被AI枪毙,弃尸尘埃.并非空穴来风,也不是危言耸听,人工智能AI图像增强框架ControlNet正在疯狂地改写绘画艺术的发展进程,你问我绘画行业未来的样子?我只 ...
- TinyWeb v1.0 正式完成第一个Release版本(功能基于 libuv 跨平台库)
使用方法很简单,很容易融入现有项目,使现有项目拥有Web网站功能和WebSocket,以及Socket直连! 并且包含了一个跨平台(windows/linux)工具集合; 嗯,也挺棒的^,^ 在项目中 ...
随机推荐
- 在IDEA中配置GitHub
目录 在IDEA中配置GitHub 安装GitHub插件 账号授权 方法一:点击Add Account... 添加账号 方法二:使用token登录 共享到GitHub 查看文件变更列表 add文件 移 ...
- golang计时器
timer 计时器 用于在指定的Duration类型时间后调用函数或计算表达式. 如果只是想指定时间之后执行,使用time.Sleep() 使用NewTimer(),可以返回的Timer类型在计时器到 ...
- elementui 时间戳和后台配合
保存时间 思路: 前端传时间戳, 后台表里的时间类型为timestamp, model结构体tag设置为 *time.Time json:"activationTime" gorm ...
- HDU 多校 2023 Round #5 题解
HDU 多校 2023 Round #5 题解 \(\text{By DaiRuiChen007}\) A. Typhoon Problem Link 题目大意 给一条 \(n\) 个点构成的折线,\ ...
- 【C#】预处理指令的学习 条件编译
预处理指令,我的理解是,编译器在编译过程中所做的指令,能根据用户定义的条件选择性的编译代码. 比如在debug下要打印些信息,然而release之后,不能出现debug的信息,这个时候就能用预处理指令 ...
- 莫烦tensorflow学习记录 (5)什么是过拟合 (Overfitting)
什么是过拟合 (Overfitting) 莫烦讲的非常通俗易懂可以看看https://mofanpy.com/tutorials/machine-learning/tensorflow/intro-o ...
- 微服务新体验之Aspire初体验
安装aspire 查看vs版本 我这的版本是17.9.7,不支持aspire,所以需要升级 更新VS 点击 帮助->检查更新 点击更新 静等安装升级 创建aspire项目 项目创建成功,如下图 ...
- 基于docker的cicd
基于docker的cicd 飞书链接: https://dlk2qiw7lh.feishu.cn/docs/doccnyu14HTaamVzASIXreCSNjf 相关软件 链接:https://pa ...
- Vue3.0+typescript+Vite+Pinia+Element-plus搭建vue3框架!
使用 Vite 快速搭建脚手架 命令行选项直接指定项目名称和想要使用的模板,Vite + Vue 项目,运行(推荐使用yarn) # npm 6.x npm init vite@latest my-v ...
- JavaSE什么是面向对象?
目录 重点!!!面向对象 面向过程与面向对象 面向过程的程序思想 面向对象程序思想 类和对象(面向对象的核心概念) 类: 类的结构 对象:(Everything is an object) 重点!!! ...