最近在工作过程中,遇到一些客户对自己的设备安全提出了更高要求,希望我们给出一些合理的解决方案。在此,我记录一种基于x509整数的设备认证方案并对其做一些解释,以便大家明白为什么能起到设备认证的作用。
可能有些小伙伴对安全和证书不太了解,这里先简单介绍一些前置知识以帮助大家理解
设备需要做什么准备
每一台设备,都有一对属于自己的非对称密钥(如RSA公私钥)。公钥的内容是可以对外公开的,我们将它写入到设备专属的证书中。私钥内容是机密的,设备需要采用某种安全手段对其进行保护,确保只有自己可以使用它(对于有高安全需求的设备,一般会采用安全芯片或者带安全芯片功能的其他芯片,以提供物理层级的安全存储保障。安全要求稍低的可以采用类似白盒加密等软安全存储或保护的方式)。一旦私钥泄露,则安全基础已经被毁坏,就需要考虑其他的补救措施
什么是证书
我们所提到的证书,实际上是一段包含各类信息的字符串,可以先简单认为是一个文本文件。这个文本文件中包含两个部分:
1.TBS内容:上一条提到的设备公钥、设备的相关信息(取决于实际签发时需要有哪些信息)、证书的有效期以及证书签发者的信息等各种有关证书或证书所有者的信息
2.签名:对TBS内容进行某种神秘运算得到的乱码(实际不是,不过正常人无法看懂其中奥妙)
什么是证书链
证书链,顾名思义就是一串证书组成的链条。但是这个链条并不是随便组成,他们必须有严格的“父子”关系。比如A签发了B,B签发了C,ABC就可以组成一条证书链。如果B还签发了D,ABD同样可以组成一条证书链。但是ABCD我们就不认为这是一条证书链。或者AC,因为中间缺了一级,我们通常也不认为这是一条证书链。
非对称密钥怎么用
非对称密钥的常规使用,一是数据加密,二是数据签名。
数据加密就是使用公钥对一串明文内容加密,让它变成一段乱码。而乱码发送给持有私钥的人或设备,使用私钥就可以将乱码恢复为明文。没有私钥的人,即时通过某种手段拿到这一串乱码,由于看不懂,也不能做任何坏事。这里有很多小伙伴会有疑问,可以使用公钥加密数据,私钥解密数据,那能不能用私钥加密数据,公钥解密数据呢?
听起来好像很合理,因为我们的通信是双向的,如果只能公钥加密私钥解密,则返回的信息不是要使用其他方式保护了,好麻烦。但是不幸的是,确实不能使用私钥加密公钥解密。因为如之前提到的,在整套体系中,大家认为公钥是一个可以公开,可以被任何人获取的东西。如果使用私钥加密公钥解密,则意味着任何一个拿到密文的人(比如抓包),都可以再通过合法渠道下载到公钥,并解密你的密文内容获得明文。所以,数据加密通常只使用公钥加密数据,私钥解密数据。
突然感觉私钥很没用,居然只能被动。。。其实并不是,这就得提到非对称密钥的另一大功能,数据签名与验签。其主要功能是用来让公钥持有者确认,私钥持有者发出来的数据没有被中间人篡改。
什么是数据签名?比如我有一段明文数据,我先对它使用数字摘要算法进行计算(比如SHA-1,SHA-256)得到一串数字摘要。然后我再对数字摘要进行一顿计算(计算过程中需要使用私钥),最后得到了一串乱码(数字摘要就看起来是乱码了,汗,乱上加乱。。。)。这一串乱码,就叫做我们使用私钥,对明文做的数据签名。在发送数据的时候,将明文数据和签名一起发送给公钥持有人。
那公钥持有者怎么知道数据没有被篡改呢?公钥持有人拿到数据后,先对明文数据进行同样的数字摘要计算,得到hash1。然后使用自己的公钥对签名记性你逆运算(类似对签名进行解密),逆运算结果为hash2.对比hash1与hash2,如果相同,则代表数据没有被篡改。因为如果存在中间人篡改了明文,则逆运算出来的签名和篡改后明文的摘要值肯定是对不上的。
那中间人能否篡改数据后,再对篡改后数据做签名,将篡改后的明文和签名都发给公钥持有者呢?可以。但是这种场景下,只有中间人私钥对应的公钥才能对签名做逆运算,而我们持有的并不是中间人的公钥,所以我们的验签也会失败,这样我们就知道我们接受的数据出问题了。
如何认证证书
实际上,我们所谓的认证证书,大部分时候是一个认证证书链的过程。对端通常会传给我们它使用的证书以及证书往上的一整条证书链。关于如何认证证书链,通俗一些来讲,可以认为分为三步:1.认证证书本身字段合法性 2.认证证书是否真的是其上级签发 3.循环
何为认证证书本身字段的合法性?如上文所提到的,证书中会包含当前证书的有效期。我们需要校验证书是否在有效期内;有些证书会包含CRL信息,我们可以去查看证书证书是否被吊销;还有些比较特殊的场景会有特定的校验条件,如HTTPS证书,我们通常会校验证书中所包含的站点URL信息和我们所访问的URL是否一致。
第二步就是验证证书是否真的是其上级签发。如何认证呢?这个时候就要用到数据验签的功能了。我们从证书信息中找到谁是要验证的证书的上级证书,然后从上级证书中取出上级证书公钥。验证证书的签名部分是否真的是上级证书私钥所签。如果是,则可以证明该证书确实是上级证书签发的,如果不是,则说明证书有问题,可以认为验证失败。
当然,完成这两步以后并不是就万事大吉了,我们还要以同样方式验证这个上级证书。验证完上级,再验证上上级。。。依次类推。这个令人绝望的验证循环通常在两种情况下终止:
1.某个证书被内置在我们的信任域中,即我们事先已经把这个证书放在了我们本地,看到有一样的,直接无条件信任,不用再继续往上验证。
2.当前证书没有上级了。这一类证书我们叫做自签发证书,就是自己签发自己,也叫根证书。如果我们一路验证到根证书都没有看到我们信任的证书,那我们也认为这次证书验证失败,这个证书不可信。
到此,前置知识就了解完成了。接下来我们就可以开始看看解决方案。
(未完待续,不定期更新。。。)