如果我在Mac或Linux中有实际的文件和Bash shell,我如何查询证书文件何时到期?不是网站,实际上是证书文件本身,假设我有csr、key、pem和chain文件。


当前回答

下面是我的bash命令行,按到期顺序列出多个证书,最近到期的是第一个。

for pem in /etc/ssl/certs/*.pem; do 
   printf '%s: %s\n' \
      "$(date --date="$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" --iso-8601)" \
      "$pem"
done | sort

样例输出:

2015-12-16: /etc/ssl/certs/Staat_der_Nederlanden_Root_CA.pem
2016-03-22: /etc/ssl/certs/CA_Disig.pem
2016-08-14: /etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_S.pem

其他回答

下面是我的bash命令行,按到期顺序列出多个证书,最近到期的是第一个。

for pem in /etc/ssl/certs/*.pem; do 
   printf '%s: %s\n' \
      "$(date --date="$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" --iso-8601)" \
      "$pem"
done | sort

样例输出:

2015-12-16: /etc/ssl/certs/Staat_der_Nederlanden_Root_CA.pem
2016-03-22: /etc/ssl/certs/CA_Disig.pem
2016-08-14: /etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_S.pem

与接受的答案相同,但请注意,它甚至适用于。crt文件,而不仅仅是。pem文件,以防万一,如果你无法找到。pem文件的位置。

openssl x509 -enddate -noout -in e71c8ea7fa97ad6c.crt

结果:

notAfter=Mar 29 06:15:00 2020 GMT

变成bash变量

由于这个问题被标记为bash,我经常使用UNIX EPOCH来存储日期,这对于计算$EPOCHSECONDS剩余的时间很有用,并通过printf '%(dateFmt)T bashism格式化输出:

{ read -r certStart;read -r certEnd;}< <(date -f <(cut -d = -f 2 <(
    openssl x509 -dates -noout -in "$file")) +%s)

Then

printf '%-6s %(%a %d %b %Y, %H %Z)T\n' start $certStart end $certEnd
start  Mon 01 Nov 2004, 17 UTC
end    Mon 01 Jan 2035, 05 UTC

示例,列出/etc/ssl/certs的内容并计算剩余天数:

for file in /etc/ssl/certs/*pem;do
    { read -r certStart;read -r certEnd;}< <(
        date -f <(cut -d = -f 2 <(
            openssl x509 -dates -noout -in "$file")) +%s)
    printf "%(%d %b %Y %T)T - %(%d %b %Y %T)T: %6d %s\n" \
        $certStart $certEnd $(( (certEnd - EPOCHSECONDS)/86400 )) ${file##*/}
done
05 May 2011 09:37:37 - 31 Dec 2030 09:37:37:   3034 ACCVRAIZ1.pem
26 Oct 2010 08:38:03 - 26 Oct 2040 08:38:03:   6620 Buypass_Class_2_Root_CA.pem
19 Jan 2010 00:00:00 - 18 Jan 2038 23:59:59:   5609 COMODO_RSA_Certification_Authority.pem
13 Nov 2012 00:00:00 - 19 Jan 2038 03:14:07:   5609 GlobalSign_ECC_Root_CA_-_R4.pem
06 Apr 2001 07:29:40 - 06 Apr 2021 07:29:40:   -522 Sonera_Class_2_Root_CA.pem
29 Jun 2004 17:39:16 - 29 Jun 2034 17:39:16:   4310 Starfield_Class_2_CA.pem
04 Feb 2016 12:32:16 - 31 Dec 2029 17:23:16:   2669 TrustCor_RootCert_CA-1.pem
01 Nov 2004 17:14:04 - 01 Jan 2035 05:37:19:   4495 XRamp_Global_CA_Root.pem
...

更完整的bash x509阅读:

for file in /etc/ssl/certs/*pem;do
    mapfile -t x509 < <(openssl x509 -noout -dates -subject -in "$file")
    x509=("${x509[@]#*=}")
    mapfile -t dates < <(IFS=$'\n';date -f - <<<"${x509[*]::2}" +%s) 
    str="${x509[-1]}"
    declare -A Subj='([CN]="${file##*/}")'
    while [[ "$str" ]] ;do
        lhs=${str%%=*} rhs=${str#$lhs= } rhs=${rhs%% = *} rhs=${rhs%, *}
        Subj[${lhs// }]="$rhs"
        str=${str#"$lhs= $rhs"} str=${str#, }
    done
    printf "%(%d %b %Y %T)T - %(%d %b %Y %T)T: %s\n" \
        ${dates[@]} "${Subj[CN]}"
done
05 May 2011 09:37:37 - 31 Dec 2030 09:37:37:   3034 ACCVRAIZ1
26 Oct 2010 08:38:03 - 26 Oct 2040 08:38:03:   6620 Buypass Class 2 Root CA
19 Jan 2010 00:00:00 - 18 Jan 2038 23:59:59:   5609 COMODO RSA Certification Authority
13 Nov 2012 00:00:00 - 19 Jan 2038 03:14:07:   5609 GlobalSign
06 Apr 2001 07:29:40 - 06 Apr 2021 07:29:40:   -522 Sonera Class2 CA
29 Jun 2004 17:39:16 - 29 Jun 2034 17:39:16:   4310 Starfield_Class_2_CA.pem
04 Feb 2016 12:32:16 - 31 Dec 2029 17:23:16:   2669 TrustCor RootCert CA-1
01 Nov 2004 17:14:04 - 01 Jan 2035 05:37:19:   4495 XRamp Global Certification Authority
...

注意:有些证书在主题中没有CN字段。对于这个,我已经初始化$Subj数组通过设置CN字段filename: declare -A Subj='([CN]="${file##*/}")'

完整bash脚本

这里共享一个完整的bash脚本,显示所有来自命令行参数的证书,可以通过文件,域名或IPv4地址。将在一行中输出过去的天数,剩余天数,替代域的数量和所有alt:

#!/bin/bash

showCert() {
    local x509 dates lhs rhs str alts
    mapfile -t x509 < <(
        openssl x509 -noout -dates -subject -ext subjectAltName -in "$1")
    x509=("${x509[@]#*=}")
    mapfile -t dates < <(IFS=$'\n';date -f - <<<"${x509[*]::2}" +%s)
    str="${x509[2]}"
    local -A Subj;Subj[CN]="${file##*/}"
    while [[ -n "$str" ]]; do
        lhs=${str%%=*} rhs=${str#$lhs= } rhs=${rhs%% = *} rhs=${rhs%, *}
        Subj[${lhs// }]="$rhs"
        str=${str#"$lhs= $rhs"} str=${str#, }
    done
    read -ra alts <<<"${x509[4]//,}"
    alts=("${alts[@]#*:}")
    printf "  %(%d %b %Y %H:%M)T %(%d %b %Y %H:%M)T %6d %6d %-30s %3d %s\n" \
        "${dates[@]}" $(((dates[1]-EPOCHSECONDS)/86400)) $(((EPOCHSECONDS-
          dates[0])/86400)) "${Subj[CN]}" "${#alts[@]}" "${alts[*]}" 
}
checkIsIpv4() { # throw an error if not valid IPv4
    local _iPointer _i _a _vareq=()
    for _i ;do
        case $_i in *[^0-9.]* ) return 1 ;; esac
        read -ra _a <<<"${_i//./ }"
        [ ${#_a[@]} -eq 4 ] || return 1
        for _iPointer in "${_a[@]}" ;do
            (( _iPointer == ( _iPointer & 255 ) ))  || return 2
        done
    done
}
checkIsLabel() {
    ((${#1}<4 || ${#1}>253)) && return 1
    [[ -z ${1//[a-zA-Z0-9.-]} ]] || return 2
    [[ -z ${1//.} ]] && return 3
    set -- ${1//./ }
    (($#<2 )) && return 4
    :
}
printf '  %-17s %-17s %6s %6s %-30s %2s\n' Not\ before Not\ after left \
       past Common\ Name Alt 

for arg ;do
    if [ -f "$arg" ] ;then
        showCert "$arg"
    elif checkIsLabel "$arg" || checkIsIpv4 "$arg" ;then
        showCert <(openssl s_client -ign_eof -connect "$arg:443" \
                           <<<$'HEAD / HTTP/1.0\r\n\r' 2> /dev/null)
    else
        echo "Unknown argument: '$arg'."
    fi
done

使用示例:

./certShow.sh /etc/ssl/certs/ssl-cert-snakeoil.pem www.example.com
  Not before        Not after           left   past Common Name                    Alt
  08 Sep 2021 16:49 06 Sep 2031 16:49   3277    372 hostname.local                   1 hostname.local
  14 Mar 2022 00:00 14 Mar 2023 23:59    179    186 www.example.org                  8 www.example.org example.net example.edu example.com example.org www.example.com www.example.edu www.example.net

命令:

# cat {key_name} | openssl x509 -noout -enddate
Example: # cat tower.cert | openssl x509 -noout -enddate

结果:

notAfter=Dec  7 04:03:32 2023 GMT

我已经做了一个与此相关的bash脚本来检查证书是否过期。如果需要,您可以使用相同的方法。

脚本

https://github.com/zeeshanjamal16/usefulScripts/blob/master/sslCertificateExpireCheck.sh

自述

https://github.com/zeeshanjamal16/usefulScripts/blob/master/README.md