首页 > 编程语言 >基于python3 flet库的证书查看工具

基于python3 flet库的证书查看工具

时间:2024-01-22 17:44:42浏览次数:38  
标签:info sha1 ft 证书 flet cert dict thumbprint python3

前言


基于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

标签:info,sha1,ft,证书,flet,cert,dict,thumbprint,python3
From: https://www.cnblogs.com/brian-sun/p/17980583

相关文章

  • python3使用socket模块实现简易syslog服务器
    废话不多说直接上代码1importsocket2importtime345defsocket_bind(server_socket,host,port=514,max_retries=5):6retries=07whileretries<max_retries:8try:9server_socket.bind((host,port))10......
  • 从keystore中导出证书
    可以使用Java的keytool工具从keystore中导出证书。以下是一个基本的命令行示例来导出一个名为mycert的证书:keytool-export-aliasmycert-filemycert.crt-keystoremykeystore.jks在这个例子中,-export 表示你想要导出一个证书。-aliasmycert 是你在keystore中为该证书指定的......
  • 在vue2中使用leaflet.AnimatedMarker来移动某个目标
    需求是:点击某个按钮后让扫描仪沿着某条线移动进行扫描效果:  扫描仪是沿着河流移动的,河流的生成方式通过geojson数据生成,geojson里包含了河流的一些点位的经纬度,扫描仪根据经纬度来移动leaflet:1.9.4 leaflet.AnimatedMarker:1.0.0 1.引入 importLfrom'leaf......
  • acme.sh 签发证书如果提示 Error creating new account 试试这个解决方法
    24年1月18日用 acme.sh命令签发ssl证书,使用的--issue参数。acme.sh--issue--dnsdns_dp-dxxx.com-dwww.xxx.com--force会提示错误:Error,cannotgetdomaintoken"type":"dns-01","url":"https://acme.zerossl.com/v2/DV90/chall/-qe......
  • 自签证书
    #CAopensslgenrsa-outcacert.key2048opensslreq-x509-new-nodes-keycacert.key-sha256-days3650-subj"/CN=MyCA"-outcacert.pem#Serveropensslgenrsa-outkey.pem2048opensslreq-new-key./key.pem-outcert.csr-subj"/CN=x.xx.com......
  • Uni-app 之安卓证书申请和查询
    一、安装环境可从Oracle官方下载jre安装包:https://www.oracle.com/java/technologies/downloads/#java8将jre命令添加到临时环境变量中二、生成证书keytool-genkey-aliastestalias-keyalgRSA-keysize2048-validity36500-keystoretest.keystoretestalias是证书别......
  • nginx的https证书自动续期
    nginx的https证书自动续期本文讲述nginx的https证书如何自动续期。顺便讲述如何手动续期,如何方便地管理所有域名证书。有很多实现方案,包括收费方案和免费方案,本文采用的是acme.sh方案。1.安装acme客户端需要将系统环境切换到root用户下执行,否则安装证书时可能会失败......
  • python3之多进程线程
    本文内容参考https://www.liaoxuefeng.com/wiki/1016959663602400/1017628290184064 多进程os模块的fork()多进程(multiprocessing):Unix/Linux操作系统提供了一个fork()函数,fork()函数调用时,操作系统自动把当前进程(父进程)复制了一份(子进程),然后分别在父进程和子进程内返回。......
  • charles添加了证书但请求都为unknow?
    charles添加了证书,但请求都为unknown,要看下证书有没有设为可信任,如果是系统默认值是不被信任的,那请求抓到就都是unknown。 此时可以看到抓包变正常了。 ......
  • Mac M2 KETTLE 请求HTTPS接口 SSL 证书错误
    获取证书安装证书sudo/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/jre/bin/keytool-import-aliascarpooling-keystore"/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/jre/lib/security/cacerts"-file/Users/jimog......