背景
在 IL5 中,启用 FIPS 模式的 SSL是强制性要求。没有 FIPS,就没有 IL5!
关于 IL5 和 FIPS 详情请参阅上一篇
Keystore
KeyStore 是 安全证书(授权证书或公钥证书 )以及相应私钥的存储库,例如用于TLS 加密。只有BCFKS密钥库类型符合 FIPS 合规性. 这里要提一下 PKCS11, 这是 RedHat 系列都可以 support FIPS 的 keystore类型, 但由于 PKCS11 存储方式从 keystore 变为 NSS, 需要 application 做一些调整, 传统 application 都是默认使用 keystore, 所以本文不赘述关于 PKCS11 的配置.
FIPS
联邦信息处理标准 (FIPS) 140-2 是一项描述美国联邦政府对敏感但非机密用途的要求的标准。WebLogic Server 支持使用符合 RSA FIPS 标准的 (FIPS 140-2) 加密模块。
有关支持的 FIPS 版本,请参阅支持的 FIPS 标准和密码套件。
当与 RSA JSSE 和 RSA JCE 提供程序结合使用时,此加密模块提供符合 FIPS 规范 (FIPS 140-2) 的实现。
如何配置 FIPS(基于 java1.8 )
Prerequisite
安装 java 和 fips jar
我们需要安装 java 和 fips 的 jar.
$ yum install java-1.8.0
# 业内第三方支持 java fips 的公司是 bouncycastle.
# 下载 https://mvnrepository.com/artifact/org.bouncycastle/bc-fips/1.0.2.5
$ rpm -qa | grep java-1.8.0
java-1.8.0-openjdk-1.8.0.332.b09-1.el8_5.x86_64
java-1.8.0-openjdk-headless-1.8.0.332.b09-1.el8_5.x86_64
# 把下载下来的 jar 放到 ext 目录
$ ls -lh /usr/lib/jvm/jre/lib/ext/bc-fips-1.0.2.5.jar
-rw-r--r--. 1 root root 3.7M Jun 23 05:56 /usr/lib/jvm/jre/lib/ext/bc-fips-1.0.2.5.jar
# 确认 jar 包权限
$ chown root:root /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.312.b07-1.el8_4.x86_64/jre/lib/ext/bc-fips-1.0.2.1.jar
$ chmod 644 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.312.b07-1.el8_4.x86_64/jre/lib/ext/bc-fips-1.0.2.5.jar
配置 fapolicyd
RedHat8 开始, fapolicyd 默认打开并且需要配置每个文件权限
$ fapolicyd-cli --file add /usr/lib/jvm/jre/lib/ext/bc-fips-1.0.2.5.jar
$ fapolicyd-cli --update
$ systemctl restart fapolicyd
配置java.security
开发系统 FIPS(security.useSystemPropertiesFile=true)
这是系统默认打开, 我们可以确认下, 如果没有请设置为 True
$ grep security.useSystemPropertiesFile /usr/lib/jvm/jre/lib/security/java.security
security.useSystemPropertiesFile=true
配置 FIPS Providers
# 1. 添加 fips providers
# 2. 保证顺序
# Before
$ vim /usr/lib/jvm/jre/lib/security/java.security
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=sun.security.ec.SunEC
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
#security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg
fips.provider.1=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.fips.cfg
fips.provider.2=sun.security.provider.Sun
fips.provider.3=sun.security.ec.SunEC
fips.provider.4=com.sun.net.ssl.internal.ssl.Provider SunPKCS11-NSS-FIPS
#====================================================================================================#
# After
$ vim /usr/lib/jvm/jre/lib/security/java.security
security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
security.provider.2=com.sun.net.ssl.internal.ssl.Provider BCFIPS
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=sun.security.ec.SunEC
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
#security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg
fips.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
fips.provider.2=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.fips.cfg
fips.provider.3=sun.security.provider.Sun
fips.provider.4=sun.security.ec.SunEC
fips.provider.5=com.sun.net.ssl.internal.ssl.Provider BCFIPS
更新 Keystore Type
# Before
$ vim /usr/lib/jvm/jre/lib/security/java.security
# Default keystore type.
#
keystore.type=jks
#
# Default keystore type used when global crypto-policies are set to FIPS.
#
fips.keystore.type=PKCS11
#=====================================================================================#
# After
$ vim /usr/lib/jvm/jre/lib/security/java.security
# Default keystore type.
#
keystore.type=BCFKS
#
# Default keystore type used when global crypto-policies are set to FIPS.
#
fips.keystore.type=BCFKS
配置KeyStore and TrustStore
生成 Root CA Certificate and Key –> ca-cert, ca-key (生产环境请用第三方认证的 CA)
$ mkdir /opt/apache-tomcat/ssl
$ cd /opt/apache-tomcat/ssl
# all certificate files should locate in /opt/apache-tomcat/ssl
$ openssl req -new -newkey rsa:4096 -days 3650 -x509 -subj '/CN=OS-Security-CA' -sha384 -keyout ca-key -out ca-cert -nodes
Create Server unsigned Certificate with BCFKS KeyStore → os.server.keystore.bcfks
test.seveninfos.com
Create BCFKS TrustStore → os.server.truststore.bcfks, os.client.truststore.bcfks
##################################################################################################################################
# 1. use openssl to create keystore with type PSCK12
# $ openssl pkcs12 -export -name server-cert -in ca-cert -inkey ca-key -out os.keystore.p12
# 2. convert pkcs12 to bcfks format
# $ keytool -importkeystore -destkeystore os.keystore.bcfks -srckeystore os.keystore.p12 -srcstoretype pkcs12 -srcstorepass testfips -deststoretype BCFKS -deststorepass testfips -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS -alias server-cert
######################################################################################################################################################################################
# !!!!!!Above steps are no longer needed!!!!!
# 3. create server truststore
# 3.1 convert cacerts JKS store to BCFKS as the base one.
$ keytool -importkeystore -srckeystore /etc/pki/ca-trust/extracted/java/cacerts -srcstoretype JKS -srcstorepass changeit -destkeystore os.server.truststore.bcfks -deststoretype BCFKS -deststorepass testfips -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS
$ keytool -importkeystore -srckeystore /etc/pki/ca-trust/extracted/java/cacerts -srcstoretype JKS -srcstorepass changeit -destkeystore os.client.truststore.bcfks -deststoretype BCFKS -deststorepass testfips -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS
# 3.2 import CARoot to Server Truststore
$ keytool -keystore os.server.truststore.bcfks -storetype BCFKS -providername BCFIPS -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -storepass testfips -alias CARoot -importcert -file ca-cert
Certificate was added to keystore
# 3.3 import CARoot to Client Truststore
$ keytool -keystore os.client.truststore.bcfks -storetype BCFKS -providername BCFIPS -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -storepass testfips -alias CARoot -importcert -file ca-cert
Certificate was added to keystore
Sign the certificates → cert-signed
# 5. export unsigned certificate from keystore
$ keytool -keystore os.server.keystore.bcfks -storetype BCFKS -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS -storepass testfips -alias server-cert -certreq -file cert-file -dname CN=test.seveninfos.com -ext SAN=DNS:test.seveninfos.com
# use printcertreq to check if SAN and CN configurations are set correct
$ keytool -printcertreq -file cert-file -v PKCS
#10 Certificate Request (Version 1.0)
Subject: CN=test.seveninfos.com
Format: X.509
Public Key: 4096-bit RSA key
Signature algorithm: SHA256withRSA
Extension Request:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: test.seveninfos.com
]
#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: BE CD 48 B8 9B 0C 1D 1A F4 C6 FC AB D5 3C 9B DF ..H..........<..
0010: A7 FE 5F C7 .._.
]
]
# 6. sign cert-file with Root CA
$ openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 3600 -CAcreateserial -passin pass:testfips
Import signed certificate
# 7. import both CA Certificate and signed certificate to server keystore and cacerts
$ keytool -keystore os.server.keystore.bcfks -alias CARoot -storetype BCFKS -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS -storepass testfips -importcert -file ca-cert
$ keytool -keystore os.server.keystore.bcfks -alias server-cert -storetype BCFKS -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS -storepass testfips -importcert -file cert-signed
# 8. import signed certificate to Server/Client Truststore
$ keytool -keystore os.server.truststore.bcfks -alias server-cert -storetype BCFKS -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS -storepass testfips -importcert -file cert-signed
$ keytool -keystore os.client.truststore.bcfks -alias server-cert -storetype BCFKS -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providername BCFIPS -storepass testfips -importcert -file cert-signed
# 9. all files should be
$ ls -lh
-rw-------. 1 root root 1.8K Jun 30 08:39 ca-cert
-rw-------. 1 root root 41 Jun 30 08:45 ca-cert.srl
-rw-------. 1 root root 3.2K Jun 30 08:39 ca-key
-rw-------. 1 root root 985 Jun 30 08:45 cert-file
-rw-------. 1 root root 1.4K Jun 30 08:45 cert-signed
-rw-------. 1 root root 160K Jun 30 08:47 os.client.truststore.bcfks
-rw-------. 1 root root 5.4K Jun 30 08:47 os.server.keystore.bcfks
-rw-------. 1 root root 160K Jun 30 08:47 os.server.truststore.bcfks
设置Java Properties
# KeyStore trustStore configs
JAVA_OPTS="$JAVA_OPTS -Djavax.net.debug=all -Djavax.net.ssl.keyStore=/opt/apache-tomcat/ssl/os.server.keystore.bcfks -Djavax.net.ssl.keyStorePassword=testfips -Djavax.net.ssl.trustStore=/opt/apache-tomcat/ssl/os.server.truststore.bcfks -Djavax.net.ssl.trustStorePassword=testfips -Djavax.net.ssl.keyStoreType=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS "
# Pay attention to the truststore path, sometimes the folder must be the same as cacerts(/etc/pki/ca-trust/extracted/java/), so the config will be changed to the following one
# JAVA_OPTS="$JAVA_OPTS -Djavax.net.debug=all -Djavax.net.ssl.keyStore=/opt/apache-tomcat/ssl/os.server.keystore.bcfks -Djavax.net.ssl.keyStorePassword=testfips -Djavax.net.ssl.trustStore=/etc/pki/ca-trust/extracted/java/os.server.truststore.bcfks -Djavax.net.ssl.trustStorePassword=testfips -Djavax.net.ssl.keyStoreType=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS "
# KeyStore TrustStore Providers
JAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.keyStoreProvider=BCFIPS"
JAVA_OPTS="$JAVA_OPTS -Djavax.net.ssl.trustStoreProvider=BCFIPS"
# Normally keep cipherSuites default, set protocols to TLSv1.2.
JAVA_OPTS="$JAVA_OPTS -Djdk.tls.server.protocols=TLSv1.2"
# Optional, normallly below properties should not be changed.
JAVA_OPTS="$JAVA_OPTS -Djdk.tls.server.cipherSuites=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 -Djavax.net.ssl.SSLContext=TLS -Djdk.tls.server.SignatureSchemes=SHA384withRSA"
请设置 jdk.tls.server.protocols to TLSv1.2 目前. SSL, TLSv1, and TLSv1.1 are NOT ALLOWED! TLSv1.3 is not recommended.
FAQ
1. what are Cipher Suits?
for example, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 defines a key exchange algorithm, an encryption algorithm, and a Message Digest.
key exchange algorithm(PKC): ECDHE_RSA.
encryption algorithm(SKC): AES_128_GCM.
Message Digest(MD): SHA256, remember that SHA1 and MD5 are always not allowed in FIPS.
2. Which SSL/TLS Protocols can be used with FIPS?
SSL/TLS Protocols | Available |
---|---|
SSL 1.0 | NO |
SSL 2.0 | NO |
SSL 3.0 | NO |
TLS 1.0 | NO |
TLS 1.1 | NO |
TLS 1.2 | YES |
TLS 1.3 | Not Recommended |
3. Which MD Algorithms can be used with FIPS?
SHA-1: Federal agencies SHOULD stop using SHA-1 for generating digital signatures, generating time stamps, and for other applications that require collision resistance. Federal agencies may use SHA-1 for the following applications: verifying old digital signatures and time stamps, generating and verifying hash-based message authentication codes (HMACs), key derivation functions (KDFs), and random bit/number generation. Further guidance on the use of SHA-1 is provided in SP 800-131A.
SHA-2 (i.e., SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256): Federal agencies may use these hash functions for all applications that employ secure hash algorithms. NIST encourages application and protocol designers to implement SHA-256 at a minimum for any applications of hash functions requiring interoperability. Further guidance on the use of SHA-2 is provided in SP 800-57 Part 1, section 5.6.2 and SP 800-131A.
SHA-3 (i.e., SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, and SHAKE256): Federal agencies may use the four fixed-length SHA-3 algorithms—SHA3-224, SHA3-256, SHA3-384, and SHA3-512 for all applications that employ secure hash algorithms. The SHA-3 Extendable-Output Functions (XOFs), SHAKE128 and SHAKE256, can be specialized to hash functions, subject to additional security considerations. Guideline for using the XOFs will be provided in the future.Currently there is no need to transition applications from SHA-2 to SHA-3.
In a word: SHA-2 MD algorithms are RECOMMENDED which are SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256.
4. Which SKC can be used with FIPS?
DES was originally approved as FIPS 46 in January 1977. After several revisions, the final revision, [FIPS 46-3, Data Encryption Standard (DES)](FIPS 46-3, Data Encryption Standard (DES) | CSRC), was withdrawn in May 2005.
Triple-DES (3DES): A variant of DES that employs up to three 56-bit keys and makes three encryption/decryption passes over the block; 3DES is also described in FIPS PUB 46-3 and was an interim replacement to DES in the late-1990s and early-2000s.
Advanced Encryption Standard (AES): NIST initially selected Rijndael in October 2000 and formal adoption as the AES standard came in December 2001. FIPS PUB 197 describes a 128-bit block cipher employing a 128-, 192-, or 256-bit key. AES is also part of the NESSIE approved suite of protocols.
Rivest Ciphers (aka Ron's Code): Named for Ron Rivest, a series of SKC algorithms. Not Allowed.
In a word: AES is recommended with more than 128-bit to encrypt data.
5. which PKC can be used with FIPS?
Digital Signature Algorithm (DSA): The algorithm specified in NIST's Digital Signature Standard (DSS), provides the digital signature capability for the authentication of messages. Described in FIPS PUB 186-4.
FIPS 186 was first published in 1994 and specified a digital signature algorithm (DSA) to generate and verify digital signatures. Later revisions − FIPS 186-1 (1998) and FIPS 186-2 (2000) − adopted two additional algorithms: the Elliptic Curve Digital Signature Algorithm (ECDSA) and the RSA digital signature algorithm.
Public Key Cryptography Standards (PKCS): A set of interoperable standards and guidelines for public key cryptography, designed by RSA Data Security Inc. (These documents are no longer easily available; all links in this section are from archive.org.)
- PKCS #1: RSA Cryptography Standard (Also RFC 8017)
- PKCS #2: Incorporated into PKCS #1.
- PKCS #3: Diffie-Hellman Key-Agreement Standard
- PKCS #4: Incorporated into PKCS #1.
- PKCS #5: Password-Based Cryptography Standard (PKCS #5 V2.1 is also RFC 8018)
- PKCS #6: Extended-Certificate Syntax Standard (being phased out in favor of X.509v3)
- PKCS #7: Cryptographic Message Syntax Standard (Also RFC 2315)
- PKCS #8: Private-Key Information Syntax Standard (Also RFC 5958)
- PKCS #9: Selected Attribute Types (Also RFC 2985)
- PKCS #10: Certification Request Syntax Standard (Also RFC 2986)
- PKCS #11: Cryptographic Token Interface Standard
- PKCS #12: Personal Information Exchange Syntax Standard (Also RFC 7292)
- PKCS #13: Elliptic Curve Cryptography Standard
- PKCS #14: Pseudorandom Number Generation Standard is no longer available
- PKCS #15: Cryptographic Token Information Format Standard
In a word: RSA DSA and ECDSA are all Recommended.
6. What are crypto policies with JAVA?
|
7. What are crypto policies with OpenSSL?
|
8. java.net.SocketException: Broken pipe?
add additional memory
9. javax.net.ssl.SSLHandshakeException: Empty server certificate chain
This issue happens during SSLHandshake. On the client side, also need to config Keystore which stores signed certificates.
10. javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Option 1: check if your Truststore can be accessed. If not, please put your Truststore in the same folder as cacerts(/etc/pki/ca-trust/extracted/java/)
Option 2: You also need to add cacerts(/etc/pki/ca-trust/extracted/java/cacerts) to your Truststore.
11. keytool error: java.io.IOException: Invalid keystore format
You are trying to list BCFKS Keystore with JKS type.
12. keytool error: java.io.IOException: DER length more than 4 bytes: 109
You are trying to list JKS Keystore with BCFKS type.
13. keytool error: java.lang.IllegalArgumentException: Illegal object in getInstance: org.bouncycastle.asn1.DLSequence
You are trying to list BCFKS Keystore with PKCS12 type.
14. java.security.NoSuchAlgorithmException: SSL SSLContext not available
SSL SSLContext type is not allowed with FIPS mode. You should use TLS SSLContext.
15. javax.net.ssl|FINE|01|main|2022-06-30 07:45:46.442 GMT|TrustStoreManager.java:166|Inaccessible trust store: /path/to/yourtrsutstore
You should put your truststore to the java program folder or the same folder as cacerts(/etc/pki/ca-trust/extracted/java/cacerts).
16. keytool error: java.io.IOException: BCFKS KeyStore corrupted: MAC calculation failed.
You should specify '-storepass xxxx' with keytool command.
17. keytool error: java.lang.Exception: Failed to establish chain from reply
Root and/or Intermediate certificates have not been imported properly or in the correct order.
|
18 java.io.IOException: DER length more than 4 bytes: 109
|
Make sure your keystore type matches your truststore.