基于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)工具集合; 嗯,也挺棒的^,^ 在项目中 ...
随机推荐
- SpringBoot-mybatis-plus 分页
前言: 想必数据分页对于每一个程序员并不陌生,针对分页查询功能代码实现上:肯定是代码简洁明了且能达到分页的效果会更好! 现在我将基于SpringBoot - mybatisPlus分页查询的方法总结如 ...
- 09. C语言内嵌汇编代码
C语言函数内可以自定义一段汇编代码,在GCC编译器中使用 asm 或 __asm__ 关键词定义一段汇编代码,并可选添加volatile关键字,表示不要让编译器优化这段汇编代码. 内嵌汇编代码格式如下 ...
- RustDesk 自建服务器部署和使用教程
RustDesk 是一个强大的开源远程桌面软件,是中国开发者的作品,它使用 Rust 编程语言构建,提供安全.高效.跨平台的远程访问体验.可以说是目前全球最火的开源远程桌面软件了,GitHub 星星数 ...
- 简易的 Linux 流量实时监控工具 watch+ifstat
非常简单小巧的流量实时监控工具,贵在不需要安装,Linux 操作系统自带,在不出外网的环境中很是实用. watch -d ifstat eth1 如果连 ifstat 都没有的环境中也可以使用 ifc ...
- 前后端分离项目(vue+springboot)集成pageoffice实现在线编辑office文件
前后端分离项目下使用PageOffice原理图 集成步骤 前端 vue 项目 在您Vue项目的根目录下index.html中引用后端项目根目录下pageoffice.js文件.例如: <scri ...
- 安装anaconda3卡在Unpacking payload ...
ananconda3在centos7虚拟机上,直接进行ananconda3安装但是始终卡在Unpacking payload ..., 虚拟机的核心数调到2或者2以上即可解决
- Redis 的简单介绍
Redis 特点 单线程 执行过程按顺序执行,不会同时执行多个操作,保证操作的原子性,省去了很多上下文切换线程的时间,不必考虑资源竞争和可能出现死锁. 为什么使用单线程 ? 官方FAQ表示:因为 Re ...
- Android 13 - Media框架(29)- MediaCodec(四)
关注公众号免费阅读全文,进入音视频开发技术分享群! 上一节我们了解了如何通过 onInputBufferAvailable 和 getInputBuffer 获取到 input buffer inde ...
- Android 13 - Media框架(24)- OMXNodeInstance(一)
关注公众号免费阅读全文,进入音视频开发技术分享群! 为了了解 ACodec 是如何与 OpenMAX 组件进行 buffer 流转的,我们有必要先来学习 OMXNodeInstance,在前面的章节中 ...
- 音视频学习--H264解析渲染
一.H264文件获取 下载一段MP4文件,通过FFMPEG转换成MP4 ffmpeg -i Gravity.mp4 -vcodec h264 out_2.264 二.通过解析H264成帧,然后刷新 这 ...