S/MIME的技术流程

Dec 27, 2021 • kael


前言

近期在研究S/MIME协议,对于整个协议的大致流程网上有很多说明了,但是却很少有能够详细说明技术细节流程给技术实现提供指导方向的文章,因此在查阅大量文档后,我决定自己整理这样一篇文章来记录一下。

S/MIME协议

MIME协议是一个互联网标准,全称是多用途互联网邮件扩展(Multipurpose Internet Mail Extensions),它扩展了电子邮件标准,使其能够支撑更多形式的信息(如二进制,声音,图像等),而S/MIME则是在MIME的基础上支持签名和加密,他们的关系类似http和https的关系。

为什么要使用S/MIME协议

S/MIME主要提供两种安全服务:

  • 数字签名
  • 邮件加密

数字签名可以保证邮件内容不被篡改,从而保证邮件的发件人和发件内容不被伪造(这同时也保证可以邮件确实出自发件人,即可以用来作为发件人发件的证据), 邮件加密可以保证邮件内容不会泄露,只有邮件的接收人可以看到邮件的内容,从而保证邮件的安全性。

特别说明:S/MIME协议是端对端协议,也就是说,只有发送人和接收人都支持S/MIME协议,才可以使用S/MIME协议收发邮件,如果接收人不支持S/MIME协议,对方会收到一封只有附件的邮件,附件名为:smime.p7m。

S/MIME协议工作流程

S/MIME分发送方和接受方,发送方需要签名和加密:

发送方

  1. 捕获邮件。
  2. 检索用来唯一标识发件人的信息。
  3. 检索用来唯一标识收件人的信息。
  4. 使用发件人的唯一信息对邮件执行签名操作,以产生数字签名。
  5. 将数字签名附加到邮件中。
  6. 使用收件人的信息对邮件执行加密操作,以产生加密的邮件。
  7. 用加密后的邮件替换原始邮件。
  8. 发送邮件。

这里第2,3,7需要特殊说明一下。
2中,检索唯一标识发件人的信息,要求发件人要在发件客户端安装私钥,用于邮件签名。
3中,检索用来唯一标识收件人的信息,需要在发件客户端安装收件人证书,用于邮件加密。
7中,为了让接收方能够验证签名,需要在邮件中附上发送方的证书。

对于接受方,需要解密和验证签名:

接收方

  1. 接收邮件。
  2. 检索加密邮件。
  3. 检索用来唯一标识收件人的信息。
  4. 使用收件人的唯一信息对加密邮件执行解密操作,以产生未加密的邮件。
  5. 返回未加密的邮件。
  6. 将未加密的邮件返回给收件人。
  7. 从未加密的邮件中检索数字签名。
  8. 检索用来标识发件人的信息。
  9. 使用发件人的信息对未加密的邮件执行签名操作,以产生数字签名。
  10. 将邮件所附带的数字签名与收到邮件后所产生的数字签名进行比较。
  11. 如果数字签名匹配,则说明邮件有效。

这里4,9需要进行特殊说明。
4中,需要在接收端客户端安装接收人的私钥,用来给加密邮件进行解密,只有解密后的邮件才能进行签名校验。
9中,解密邮件后,可以拿到邮件签名和发送方证书,接收方需要对证书进行验证,验证有效后,即可利用证书的公钥对邮件的签名进行校验,校验通过则说明邮件没有被篡改,是可信的。

S/MIME证书

看了前面的收发信流程,你是否有如下问题?

  1. 如何保证加密结果只有收件人能解密?
  2. 使用发件人提供的证书校验签名,如何确认证书不是和邮件一起被篡改的?
  3. 如何确定证书是可信任的?

非对称加密

对于第一个问题,S/MIME协议如何保证邮件内容只有收件人可以解密呢?这里实际上采用的是非对称加密算法。

在S/MIME协议中,每一个人申请证书时,都会收到至少两个证书:公钥证书和私钥证书,公钥证书是可以公开的,私钥证书是需要自己保存并且不能泄露的。

在给收件人发送邮件时,需要先获取到收件人公钥,公钥可以先找收件人提供,或者通过服务器获取(协议中没有规定如何获取收件人公钥,因此获取方法也不是固定的)。

拿到公钥加密后,密文内容就只有收件人的私钥可以解密了,因此能看到密文内容的人,就只有持有收件人私钥的人了。

签名校验

我们知道,签名算法是私钥签名,公钥按照特定算法计算得到签名,然后比较私钥签名结果和公钥签名,相同即可确认签名有效。

从这个算法可以看出,当邮件内容签名可以用公钥验证时,至少可以保证邮件内容与私钥-公钥是对应的(如果公钥被篡改,原来的私钥校验肯定不通过),此时我们假设公钥是正确的,没有被篡改,说明邮件内容是可信的,没有被篡改。

如何确定证书是可信的

在签名校验的环节,我们假设了证书是可靠的,没有被篡改,因此得出邮件内容是可靠的,没有被篡改,那么如何用验证证书是可靠的这个假设呢?

这里就涉及证书校验的知识了。

严格来说,证书没有可靠和不可靠的说法,只有信任和不信任,什么样的证书是受信任的,什么样的证书是不受信任的,这里就不仅仅涉及技术问题了,也有一些约定的关系。

证书链

事实上,每一个证书都不是单独存在的,它是在证书链上的叶子结点,打开百度,我们可以看到百度的证书链如下:

百度证书链

这里我们可以看到三个证书:

  • baidu.com
  • GlobalSign Organization Validation CA - SHA256 - G2
  • GlobalSign Root CA

这个就是百度的证书链,其中,baidu.com我们叫最终证书(end-user certificates),GlobalSign Organization Validation CA - SHA256 - G2我们叫中间证书(intermediates certificates), GlobalSign Root CA我们叫根证书(Root certificates),在一个证书链里,通常可以有一个活着多个中间证书(多层级)。

实际上,证书的信任是通过这个证书链传递的,当我们检查是否信任一个证书时,会逐步往上层找中间证书,一直找到根证书,如果信任根证书,则可以信任最初的最终证书。

证书链校验

那根证书怎么来的?我们为什么要信任根证书?

这里实际上是一些约定关系了,全球有几个特定的厂商,即根证书厂商,所有的根证书都出自这几个厂商(暂且称为根证书厂商),相当于全球约定信任这几个厂商,每个厂商使用自己的根证书去签发中间证书,再由中间证书签发最终证书,最终产生各种各种的证书。

全球所有的根证书厂商的根证书,都是要预先存储在计算机或者浏览器(firefox)中的,因此在校验证书的过程,只要一层一层往上找,最终找到根证书,只要计算机在根证书库中能找到对应的根证书,则说明该根证书可信,进而证明原来的最终证书可信。

目前,全球受信根证书企业大致有如下几家:

Digicert

DigiCert(原Symantec)是全球首屈一指的网络安全品牌,也是互联网上最受认可和信任的CA机构,其邮件安全证书功能强大、稳定性好,可以提供企业版的S/MIME证书,深受金融、银行、医疗药业等企业的喜爱。

Sectigo

Sectigo(原Comodo)是全球数字证书市场占有率最高的CA,可提供个人版和企业版的邮件证书,最重要的一点是Sectigo是国际品牌中性价比最高的邮件安全证书品牌,其个人版邮件证书只需148元/年。企业版的S/MIME证书适合中小企业的邮件系统使用。

GlobalSign

GlobalSign也是信息安全领域的佼佼者,在中国深受各大企业欢迎,尤其是电商行业和互联网企业。目前常用的有个人版、部门版和企业版三种邮件安全证书,可以满足不同用户需求。GlobalSign的S/MIME证书价格跟DigiCert差不多,主要服务中高端用户群体。

中间证书

现在我们知道,如果想知道最终证书是否可信,只要找到可信的根证书即可,那么如何找到根证书呢?在多层级的证书链中,我们只有最终证书,需要逐层网上寻找中间证书进行验证,一般来说,应用在校验证书时会有两种方式处理缺失的中间证书:

  1. 根据证书信息中提供的上一级中间证书查找并下载中间证书,然后递归寻找直到找到根证书
  2. 直接提醒中间证书丢失,让用户自己安装

对于 自动查找并下载中间证书的方式,应用可以在证书中找到上级签发证书的下载地址:

自动下载中间证书

证书分发

现在我们知道S/MIME完整的签名加密-解密校验流程了,那么用户如何获取到自己的证书呢?

通常来说,用户如果需要一个全球信任的证书,就需要去前面提到的几个根证书厂商申请,当然,国内也有很多中间证书厂商可以申请个人证书,大部分情况下都是要收费的(看证书类型,一般DV证书不收费,OV和EV收费)。

个人申请证书之后,如何分发自己的公钥?

这是一个比较麻烦的问题,S/MIME并没有给出证书分发的过程,因此为了方便用户使用,我们通常需要一个证书和密钥的管理分发系统,称为电子密钥管理系统(Electronic Key Management System, EKMS)。

目前业内并没有规范指导证书分发的方式,因此各个邮件服务商都是自己开发的证书交换服务来简化用户分发证书的过程。

S/MIME常用的方式是先由第一个用户发送一封只有签名,没有加密的邮件给第二个用户,第二个用户就可以通过这封邮件拿到第一个用户的证书了,然后就可以给第一个用户发送加密邮件了,第一个用户收到第二个用户的加密邮件后,用自己的私钥解密就可以拿到第二个用户的证书了。