如何从PEM编码的证书确定SSL证书的到期日期?


326

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

Answers:


628

openssl

openssl x509 -enddate -noout -in file.pem

输出形式为:

notAfter=Nov  3 22:23:50 2014 GMT

另请参阅MikeW的答案,以了解如何轻松地检查证书是否已过期,或者证书是否将在一定时间段内,而不必解析上述日期。


19
您还具有内置在实用程序中的-startdate-enddate选项x509。他们会为您省钱grep
jww 2014年

2
如果文件不是pem格式,这也适用。对于server.crt可以正常工作
请看

163

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

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

这样可以省去自己进行日期/时间比较的麻烦。

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

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


8
要确定证书当前是否过期,请使用零秒的持续时间。省略-noout使用单个命令即可查看有用消息的选项,而无需额外的逻辑。例如,openssl x509 -checkend 0 -in file.pem将给出输出“证书将过期”或“证书将不过期”的输出,指示证书是否将在零秒内过期。
LS

1
谢谢!这正是我所需要的!使用退出代码,它将使程序更小/更干净。
Lon Kaut

24

这是我的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

非常好!这就是我所追求的。现在,我对必须尽快续签的证书进行了概述。将其另存为我的主文件夹中的checkcerts.sh,这样我就可以定期对其进行检查。下一步将是每月进行一次CRON作业检查,并通过电子邮件将需要更新的证书发送给他们。
皮特

3
非常有用。我使用此cronjob0 7 * * 1 /path/to/cert.sh | mail -s "certbot" my@email.com
Matthieu

10

这是一个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

出乎意料的是,osx 10.13.4可以运行您的Shell正常(不要判断我,我今天只在osx上将应用程序推送到应用程序商店...不久
后又

1
@ScottStensland我们正在判断:-P。我经常使用Mac,但Linux确实更好。
迈克Q

非常感谢您提供的代码片段!多么烦人的任务:),我希望openssl有一个unixtime时间戳标记。
user1279741

1
对于使用高山linux容器的用户,您的expiry_date值将需要从其末尾删除时区名称。cut在管道的末尾添加一个附加内容,以执行以下操作:| cut -d ' ' -f 1-4
Droogans

5

一行检查真/假,如果域证书将在一段时间(例如15天)后过期:

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

2

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

for pem in /path/to/certs/*.pem; do
    printf '%s: %s\n' \
        "$(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标志。


如果您没有制作.pem文件,而只是.cer从Apple Dev站点制作并下载了证书,您将如何做?
亚历克斯·萨瓦通

1

与已接受的答案相同,但是请注意,即使您找不到文件位置,它也适用于.crt文件,而不仅仅是.pem文件.pem

openssl x509 -enddate -noout -in e71c8ea7fa97ad6c.crt

结果:

notAfter=Mar 29 06:15:00 2020 GMT

0

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

gcr-viewer file.pem
# or
gcr-viewer file.crt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.