您当前的位置: 首页 >  Python

彭世瑜

暂无认证

  • 0浏览

    0关注

    2791博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Python:获取ssl证书信息和到期时间

彭世瑜 发布时间:2021-04-19 12:05:16 ,浏览量:0

目录
    • 1、通过openssl证书获取
    • 2、通过openssl域名获取
    • 3、通过脚本获取curl
    • 4、通过socket 获取域名ssl 证书信息
    • 5、通过pyOpenSSL获取证书信息

1、通过openssl证书获取
openssl x509 -in .pem -noout -dates
2、通过openssl域名获取
echo | openssl s_client -servername  -connect :443 2>/dev/null | openssl x509 -noout -dates
3、通过脚本获取curl
# coding: utf-8 
# 查询域名证书到期情况

import re
import subprocess
from datetime import datetime


def get_re_match_result(pattern, string):
    match = re.search(pattern, string)
    return match.group(1)


def parse_time(date_str):
    return datetime.strptime(date_str, "%b %d %H:%M:%S %Y GMT")


def format_time(date_time):
    return datetime.strftime(date_time, "%Y-%m-%d %H:%M:%S")


def get_cert_info(domain):
    """获取证书信息"""
    cmd = f"curl -Ivs https://{domain} --connect-timeout 10"

    exitcode, output = subprocess.getstatusoutput(cmd)

    # 正则匹配
    start_date = get_re_match_result('start date: (.*)', output)
    expire_date = get_re_match_result('expire date: (.*)', output)

    # 解析匹配结果
    start_date = parse_time(start_date)
    expire_date = parse_time(expire_date)

    return {
        'start_date': start_date,
        'expire_date': expire_date
    }


def get_cert_expire_date(domain):
    """获取证书剩余时间"""
    info = get_cert_info(domain)
    print(info)

    expire_date = info['expire_date']

    # 剩余天数
    return (expire_date - datetime.now()).days


if __name__ == "__main__":
    domain = 'www.baidu.com'
    expire_date = get_cert_expire_date(domain)
    print(expire_date)

参考 查看域名https证书到期时间 基于python检查SSL证书到期情况代码实例

4、通过socket 获取域名ssl 证书信息

核心代码

# -*- coding: utf-8 -*-

import socket
import ssl


def get_domain_cert(domain):
    """
    获取证书信息
    :param domain: str
    :return: dict
    """
    socket.setdefaulttimeout(5)

    cxt = ssl.create_default_context()
    skt = cxt.wrap_socket(socket.socket(), server_hostname=domain)

    skt.connect((domain, 443))
    cert = skt.getpeercert()

    skt.close()

    return cert


if __name__ == "__main__":
    print(get_domain_cert("www.baidu.com"))

输出

{
'subject': ((('countryName', 'CN'),), (('stateOrProvinceName', 'beijing'),), (('localityName', 'beijing'),), (('organizationalUnitName', 'service operation department'),), (('organizationName', 'Beijing Baidu Netcom Science Technology Co., Ltd'),), (('commonName', 'baidu.com'),)), 
'issuer': ((('countryName', 'BE'),), (('organizationName', 'GlobalSign nv-sa'),), (('commonName', 'GlobalSign RSA OV SSL CA 2018'),)), 
'version': 3, 
'serialNumber': '4417CE86EF82EC6921CC6F68', 
'notBefore': 'Jul  5 05:16:02 2022 GMT', 
'notAfter': 'Aug  6 05:16:01 2023 GMT', 
'subjectAltName': (('DNS', 'baidu.com'), ), 
'OCSP': ('http://ocsp.globalsign.com/gsrsaovsslca2018',), 
'caIssuers': ('http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt',), 
'crlDistributionPoints': ('http://crl.globalsign.com/gsrsaovsslca2018.crl',)
}

结构化输出内容后的完整代码

# -*- coding: utf-8 -*-

import socket
import ssl

from dateutil import parser

# requests.packages.urllib3.disable_warnings()

try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'

socket.setdefaulttimeout(5)


def get_domain_ip(domain):
    """
    获取ip地址
    :param domain: str
    :return: str
    """
    try:
        addrinfo = socket.getaddrinfo(domain, None)
        return addrinfo[0][-1][0]
    except Exception as e:
        pass

    return None


def get_domain_cert(domain):
    """
    获取证书信息
    :param domain: str
    :return: dict
    """
    cxt = ssl.create_default_context()
    skt = cxt.wrap_socket(socket.socket(), server_hostname=domain)

    skt.connect((domain, 443))
    cert = skt.getpeercert()
    skt.close()

    return cert


def get_cert_info(domain):
    """
    获取证书信息
    :param domain: str
    :return: dict
    """
    cert = get_domain_cert(domain)

    issuer = _tuple_to_dict(cert['issuer'])
    subject = _tuple_to_dict(cert['subject'])

    return {
        'domain': domain,
        'ip': get_domain_ip(domain),
        'subject': _name_convert(subject),
        'issuer': _name_convert(issuer),
        # 'version': cert['version'],
        # 'serial_number': cert['serialNumber'],
        'start_date': _parse_time(cert['notBefore']),
        'expire_date': _parse_time(cert['notAfter']),
    }


def _tuple_to_dict(cert_tuple):
    """
    cert证书 tuple转dict
    :param cert_tuple: tuple
    :return:
    """
    data = {}
    for item in cert_tuple:
        data[item[0][0]] = item[0][1]

    return data


def _name_convert(data):
    """
    名字转换
    :param data: dict
    :return: dict
    """
    name_map = {
        'C': 'countryName',
        'CN': 'commonName',
        'O': 'organizationName',
        'OU': 'organizationalUnitName',
        'L': 'localityName',
        'ST': 'stateOrProvinceName'
    }

    dct = {}
    for key, value in name_map.items():
        dct[key] = data.get(value, '')

    return dct


def _parse_time(time_str):
    """
    解析并格式化时间
    :param time_str: str
    :return: str
    """
    return parser.parse(time_str).astimezone().strftime(DATETIME_FORMAT)


if __name__ == "__main__":
    print(get_cert_info("www.baidu.com"))

输出

{
  "domain": "www.baidu.com",
  "ip": "39.156.66.14",
  "subject": {
    "C": "CN",
    "CN": "baidu.com",
    "O": "Beijing Baidu Netcom Science Technology Co., Ltd",
    "OU": "service operation department",
    "L": "beijing",
    "ST": "beijing"
  },
  "issuer": {
    "C": "BE",
    "CN": "GlobalSign RSA OV SSL CA 2018",
    "O": "GlobalSign nv-sa",
    "OU": "",
    "L": "",
    "ST": ""
  },
  "start_date": "2022-07-05 13:16:02",
  "expire_date": "2023-08-06 13:16:01"
}

参考: Python脚本批量检查SSL证书过期时间

5、通过pyOpenSSL获取证书信息

该方式,不校验证书合法性,只获取证书信息

文档:

  • https://pyopenssl.org/en/0.15.1/index.html#

依赖

pip install pyOpenSSL

示例

# -*- coding: utf-8 -*-

import ssl
import OpenSSL


def get_ssl_expire_date(host, port=443):
    cert = ssl.get_server_certificate((host, port))
    x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
    return x509.get_notAfter().decode()


if __name__ == '__main__':
    print(get_ssl_expire_date('www.baidu.com'))
    # 20230806051601Z

参考 使用Python检查ssl证书过期时间 使用Python Openssl库解析X509证书信息

关注
打赏
1665367115
查看更多评论
立即登录/注册

微信扫码登录

0.1656s