如何根据PEM编码的证书确定SSL CERT到期日期



如果我有实际文件和Mac或linux中的bash shell,我该如何查询证书文件的过期?不是一个网站,而是实际上证书文件本身,假设我有CSR,密钥,PEM和链条文件。

with openssl

openssl x509 -enddate -noout -in file.pem

输出在表单上:

notAfter=Nov  3 22:23:50 2014 GMT

还请参见Mikew的答案,以了解如何轻松检查证书是否已过期,或者是否会在一定时间段内,而无需分析上述日期。

如果您只想知道证书是否已过期(或在接下来的N秒内进行),则-checkend <seconds>的CC_2选项将告诉您:

if openssl x509 -checkend 86400 -noout -in file.pem
then
  echo "Certificate is good for another day!"
else
  echo "Certificate has expired or will do so within 24 hours!"
  echo "(or is invalid/not found)"
fi

这节省了自己进行日期/时间比较。

openssl如果证书尚未过期,则在接下来的86400秒内(在上面的示例中)将返回0(零)的退出代码(零)。如果证书已过期或已经发生过 - 或其他错误(例如无效/不存在文件) - 返回代码为 1

(当然,它假定正确设置了时间/日期)

请注意,OpenSSL的较旧版本具有错误,这意味着如果checkend中指定的时间太大,则始终返回0(https://github.com/openssl/openssl/openssl/openssl/issues/6180). .

这是我的bash命令行,按照其到期顺序列出多个证书,最近首先到期。

for pem in /etc/ssl/certs/*.pem; do 
   printf '%s: %sn' 
      "$(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

命令:

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

结果:

notAfter=Dec  7 04:03:32 2023 GMT

这是一个bash函数,假设您使用DNS圆形旋翼蛋白,可以检查所有服务器。请注意,这需要GNU日期,并且在Mac OS

上不起作用
function check_certs () {
  if [ -z "$1" ]
  then
    echo "domain name missing"
    exit 1
  fi
  name="$1"
  shift
  now_epoch=$( date +%s )
  dig +noall +answer $name | while read _ _ _ _ ip;
  do
    echo -n "$ip:"
    expiry_date=$( echo | openssl s_client -showcerts -servername $name -connect $ip:443 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2 )
    echo -n " $expiry_date";
    expiry_epoch=$( date -d "$expiry_date" +%s )
    expiry_days="$(( ($expiry_epoch - $now_epoch) / (3600 * 24) ))"
    echo "    $expiry_days days"
  done
}

输出示例:

$ check_certs stackoverflow.com
151.101.1.69: Aug 14 12:00:00 2019 GMT    603 days
151.101.65.69: Aug 14 12:00:00 2019 GMT    603 days
151.101.129.69: Aug 14 12:00:00 2019 GMT    603 days
151.101.193.69: Aug 14 12:00:00 2019 GMT    603 days

与接受的答案相同,但请注意,即使在.crt文件中也可以使用.pem文件,以防万一您无法找到.pem文件位置。

openssl x509 -enddate -noout -in e71c8ea7fa97ad6c.crt

结果:

notAfter=Mar 29 06:15:00 2020 GMT

一行在true/false上检查是否在一段时间内过期(例如15天):

openssl x509 -checkend $(( 24*3600*15 )) -noout -in <(openssl s_client -showcerts -connect my.domain.com:443 </dev/null 2>/dev/null | openssl x509 -outform PEM)
if [ $? -eq 0 ]; then
  echo 'good'
else
  echo 'bad'
fi

openssl字段存储到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)

然后

printf '%-6s %(%a %d %b %Y, %H %Z)Tn' 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 %sn" 
        $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: %sn" 
        ${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 字段。为此,我通过将CN字段设置为文件名来初始化$Subj数组: declare -A Subj='([CN]="${file##*/}")'

完整的bash脚本

在此处共享一个完整的bash脚本,显示了命令行参数的所有证书,可以通过 file domain name IPv4 address 。将过去几天左右替代域的数量:

#!/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 %sn" 
        "${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 %2sn' 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.0rnr' 2> /dev/null)
    else
        echo "Unknown argument: '$arg'."
    fi
done

解释

  • 函数showCert创建数组变量 $x590 with dates objection 和objective 和 alt name em>。
  • 使用mapfile和(仅1个叉子到)date转换 start end date dates dates << 。/li>
  • 创建 cossociative数组变量 $Subj 用于解析主题 string(3rd Line: ${x509[2]}
  • split 替代名称 array $alts
  • 使用openssl x5090格式化并打印每个显示的证书
    • 开始日期
    • 结束日期
    • 左日
    • 几天
    • 通用名称
    • 替代名称的数量
    • 替代名称

用法样本:

./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

对于Mac OSX(El Capitan),尼古拉斯示例的修改对我有用。

for pem in /path/to/certs/*.pem; do
    printf '%s: %sn' 
        "$(date -jf "%b %e %H:%M:%S %Y %Z" "$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" +"%Y-%m-%d")" 
    "$pem";
done | sort

样本输出:

2014-12-19: /path/to/certs/MDM_Certificate.pem
2015-11-13: /path/to/certs/MDM_AirWatch_Certificate.pem

MacOS不喜欢我系统上的--date=--iso-8601标志。

如果(出于某种原因)您要在Linux中使用GUI应用程序,请使用gcr-viewer(在大多数分布中,它是由软件包gcr安装的(否则在软件包gcr-viewer中))

gcr-viewer file.pem
# or
gcr-viewer file.crt

我做了一个与该脚本相关的bash脚本,以检查证书是否过期。您可以在需要时使用相同的。

脚本

https://github.com/zeeshanjamal16/usefulscripts/blob/master/ssslcertificateatificateatificateateexpirecheck.sh

readme

https://github.com/zeeshanjamal16/usefulscripts/blob/master/readme.md

相关内容

  • 没有找到相关文章

最新更新