浅谈 Java 中的FIPS 模式

首先, 我们来聊一聊 FIPS 是啥. 我相信 90%的互联网公司一辈子都不会和他沾边, 这个话题比较小众, 我先引入一篇微软的文章.

Department of Defense (DoD) Impact Level 5 (IL5)

https://learn.microsoft.com/en-us/compliance/regulatory/offering-dod-il5

这篇文章提到的两个概念 DoD(美国国防部) 和 IL5. 一般来说, 我们的 service 需要上线会满足不同的Impact Level, 1 - 6 递增. 大家可能还是没概念, 我举个例子, 我们熟悉的开源产品Ubuntu, 其实还有付费版, 购买 license 后, Ubuntu上可以使用一个ubuntu-advantage-tools的工具, 这个工具可以给我们打一个叫做 CIS-Benchmark的补丁, 这是一个安全标准. CIS-Benchmark 里面有Level 1 和 Level 2的安全要求. 而我们熟悉又厌恶的 Selinux 是Level 1的一项. 这么对比, 相信大家知道 IL5 是一个多么高高在上的标准了.


而在 IL5 中, FIPS(Federal Information Processing Standards) 是必须满足的要求. 对于FIPS, 可能大多数朋友都没用过, 但是你一定见过. 我给大家再举个例子, 就拿 OpenJDK 1.8 来说.

$ rpm -qa |grep ^java-1.8.0java-1.8.0-openjdk-headless-1.8.0.352.b08-2.el8_6.x86_64java-1.8.0-openjdk-1.8.0.352.b08-2.el8_6.x86_64
# 我们装完Java后, 会有一个java.security文件$ ls /usr/lib/jvm/jre/lib/security/java.security/usr/lib/jvm/jre/lib/security/java.security
# 我们过滤一下security.useSystemPropertiesFile 这个参数$ grep security.useSystemPropertiesFile /usr/lib/jvm/jre/lib/security/java.securitysecurity.useSystemPropertiesFile=true# 这个参数默认就是true, 而这个参数的意义就是开启Java的FIPS.

有人会问, 说了这么多, 这不都默认开启了嘛, 还要配置啥?

这就是 Java 复杂的地方, 或者说 FIPS 复杂的地方. 没错, Java 开启FIPS, 只是让 Java 有了这个能力, 但这种能力不是强制的, 也就是说程序在跑的时候是可以不遵守的, 所以要让Java 程序符合 FIPS 要求, 那就离不开两个概念, 一个是Keystore, 另一个则是Provider.

Keystore

顾名思义, 存放 key 的地方, 这里的 key 指的是什么, 证书和私钥. 在 https 握手的时候, 需要认证服务端和客户端证书的合法性, 确保不是自签名的证书.  怎么确保不是自签名的证书呢? 那就需要权威机构的 CA 证书.  这些 CA 证书就存放在 Truststore里. Truststore 默认用的是文件, 这个文件我相信大家也很熟悉就是/etc/pki/ca-trust/extracted/java/cacerts. 

Keystore 解决了我们证书的合规性.


其实这里我简化了证书本身, 其实制作证书时需要加密算法, 而加密算法 FIPS 对其也是有要求的. 下面就让我们简单聊一聊加密算法吧. 加密算法分为两大类, 对称加密和非对称加密.

对称加密简单理解就是用同一个 Secret 加密和解密, 很明显不安全, 因为这个Secret需要在 server 端和 client 端都存在, 那有没有办法优化下呢,?可以, 使用流密码, 流密码一次对单个位(字节或计算机字)进行操作,并实施某种形式的反馈机制,以便密钥不断变化. 举几个典型的算法, DES, 3DES 和 AES. 如果大家倒腾过 openssl 或者 openssh 的配置, 一定见过这几个.

非对称加密也叫公钥加密, 听到公钥第一时间你会联想到 ssh, 没错, ssh 的秘钥登录的秘钥对就是公钥加密的典型, 也就是说其实在非对称加密中是有 2 把 key, 一个是保存在自己这(私钥), 一个可以随便放(公钥).  而你用ssh-keygen生成的ssh 秘钥对默认的名字一般都是 id_rsa和 id_rsa.pub. 因为ssh-keygen默认用的是 RSA算法, 2048位. RSA是我们最常见使用最广的非对称加密算法, 还有一些像ECC,PKCS 等等都比 RSA 更安全.

而在证书认证过程中还有用到 HASH 算法.

HASH 算法, 区别于加密算法, HASH算法是不可逆的, 其实就是计算某个文件的 HASH 值, 在文件传输前后确保文件没有损坏. 对于 HASH(哈希)大家肯定耳熟能详, 最常见的就是查看 MD5, MD5是 MD 算法的第 5 代产品了. MD5 最大的特点就是慢, 计算一个 1G的文件就需要几十秒. 所以有更好的 HASH 算法 SHA, 如果大家使用过 docker, 你用 docker images查看 的image id就是 SHA2 算法生成的.

以上和大家简单聊了聊算法, 其实算法本身很复杂的, 并且还有专门的学科去研究, 本文提及的连皮毛都不算, 都是一些常识, 共勉而已.

最后关于算法我还想补充一点, 在 https 建立连接的过程中上述三种算法都有用到, 所以并没有好坏之分, 只是应用场景不同. 如果大家有兴趣, 可以去研究下证书的内容和 CA 证书来佐证.


Provider

现在我们回到 Provider, Provider其实就是提供算法的具体 Java类, 因为我们需要使用符合 FIPS 的算法来制作证书和存储证书, 当然我们需要这些算法. 

这里得先解释下Keystore的两种形式, 

第一种就是默认最普遍的文件形式, Keytool通过某种算法把证书加密后保存在文件中. 第二种是用数据库, Keytool加密证书后放在数据库里. 

要想使 keystore 的加密算法符合 FIPS 要求, Java默认提供PKCS11 Keystore类型, 但加密后的数据只能存在数据库中.

如果大家有类似 JMX 的需求, 那就不能使用数据库, 因为 JMX 配置的Keystore必须是一个文件. 这里有一个第三方公司Bouncy Castle提供的 bc-fips.jar包里面包含了BCFIPS 的Provider, 并提供了BCFKS 的Keystore类型是可以存在文件中的. 这也是业内比较主流 FIPS 的解决方案.

介绍到这, 就差不多就是 Java 怎么打开 FIPS 的过程. 总结下, 首先你需要一种符合 FIPS 的算法来制作证书, 其次需要使用符合 FIPS 的算法(Provider提供)来保存这些证书(Keystore). 当然你还需要 block 哪些是 FIPS 不允许的算法, 这部分在 java.security 里也是可以配置的. 

最后, 因为 https 是一个双向认证的过程, 在认证的时候会用 server 端和client 端定义的Ciphers, 所以Ciphers的配置也会影响 FIPS. 

Cipher 是有固定格式的, 比如:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256.

当然还包括 TLS 的版本, 一般都是要 TLSv1.2 以上.  (如果有朋友有需求, 可以留言, 我会专门做一期关于加密的干货.)

写在最后, 其实 FIPS 只是一个很高级的 Https而已, Https大家都非常熟悉, 任何 WebServer 只需要配置下证书就可以. 之所以以前大家没有遇到过这么多关于加密的概念, 并不是加密不存在, 而是WebServer的默认配置就够了. 

本文提及内容如果有技术上的错误麻烦通知更正,同时欢迎各种技术探讨☕️

如果喜欢小编写的文章,记得点点关注哦🌹🌹🌹

转载请注明出处!

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值