ssl - BouncyCaSTLe JSSE 和 BCTLS 密码没有凭证

标签 ssl bouncycastle jce fips jsse

为我的服务器应用程序使用 BouncyCaSTLe FIPS JSSE 和 TLS 提供程序。

<dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-fips</artifactId>
        <version>1.0.3</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bc-fips</artifactId>
        <version>1.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bctls-fips</artifactId>
        <version>1.0.10</version>
    </dependency>

在应用程序中配置 FIPS 和 JSSE 提供程序,如下所示。

Security.insertProviderAt(new BouncyCastleFipsProvider(), 1);
Security.insertProviderAt(new BouncyCastleJsseProvider("fips:BCFIPS"), 2);
Security.setProperty("keystore.type", "BCFKS");

SSL证书配置如下:

Server Cert - Public Key: RSA 2048 bit, Sign Algorithm: SHA256WithRSA
Issuing CA - Public Key: RSA 2048 bit, Sign Algorithm: SHA256WithRSA
Root CA - Public Key: RSA 2048 bit, Sign Algorithm: SHA1WithRSA

使用 Zulu OpenJDK JRE 11。以下是与 TLS 相关的其他系统属性

-Djdk.tls.disabledAlgorithms="MD5, RC4, TLSv1, SSLv2Hello, SSLv3, DSA, DESede, DES, 3DES, DES40_CBC, RC4_40, MD5withRSA, DH, 3DES_EDE_CBC, DHE, DH keySize < 1024, EC keySize < 224" -Djdk.tls.ephemeralDHKeySize=2048 -Djdk.tls.rejectClientInitiatedRenegotiation=true -Djava.security.egd=file:/dev/./urandom -Dorg.bouncycastle.rsa.allow_multi_use=true

支持的协议(protocol)是 TLSv1.2。

期望:

我希望服务器支持 TLS_ECDHE_RSA 类型的密码。当使用具有相同配置(减去上面的 BC 库)的相同应用程序和 Sun JSSE 时,这些密码被启用。

实际:

问题是在 SSL 扫描中仅显示下面列出的 TLS_RSA 类型的密码:

TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA

在 bouncycaSTLe 调试日志中,我看到以下条目

[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[o.b.j.p.ProvTlsServer] - Server found no credentials for cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

这是什么意思?我没有从谷歌搜索中找到任何有用的信息。有人可以帮助解决这个问题。

提前致谢。

可能的类似问题:DHE ciphers not exposed by BouncyCastle provider


Update-1

这是将 ssl.KeyManagerFactory.algorithmssl.TrustManagerFactory.algorithm 设置为 PKIX 后的更新,如以下答案中所建议。

感谢您建议该配置。现在 TLS_ECDHE_RSA* 密码出现在 SSL 扫描中。

但是有一个问题。支持的密码列表还包括 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(请参阅屏幕截图),根据本文档(附录 B),它在 FIPS 模式下不受支持:https://downloads.bouncycastle.org/fips-java/BC-FJA-(D)TLSUserGuide-1.0.10.pdf .

我设置了系统属性-Dorg.bouncycaSTLe.fips.approved_only=true,但没有发现任何区别。

我不确定这是否符合预期。对此有什么想法吗?

supported-cipher-suites

额外观察: 一旦我按照上面的建议配置了 PKIX 算法,我很快就开始收到错误 org.bouncycaSTLe.crypto.IllegalKeyException: Attempt to sign/verify with RSA modulus already used for encrypt/decrypt. 在 SSL 扫描之后。此错误阻止了与我的应用程序的所有后续 TLS 连接。为此,我尝试了以下两种方法。

  1. 设置 -Dorg.bouncycaSTLe.jsse.fips.allowRSAKeyExchange=falsethis forum 所述.但是,这会禁用所有 TLS_RSA 密码。

  2. 配置系统属性-Dorg.bouncycaSTLe.rsa.allow_multi_use=true。有了这个,我可以同时使用 TLS_RSA 和 TLS_ECDHE_RSA 密码。

最佳答案

那些日志条目(“服务器未找到凭据...”意味着服务器配置为支持上述算法,但无法通过 X509KeyManager 找到合适的凭据( key 加证书)SSLContext 已初始化.

BCJSSE(尤其是 FIPS)不与其他提供商的 KeyManagerFactory 或 TrustManagerFactory 互操作,因此请检查您是否已将默认算法配置为 PKIX(在 java.security 中)以使用 BCJSSE:

ssl.KeyManagerFactory.algorithm=PKIX
ssl.TrustManagerFactory.algorithm=PKIX

否则:KeyManagerFactory 没有正确初始化(KeyStore 有问题),或者 chooseServer... 方法调用未能找到任何适合 RSA 签名的凭证,或者它们已经过期,或者具有不兼容的 KeyUsage 或 ExtendedKeyUsage,或其他一些细节。在某些情况下,我们确实有比 SunJSSE 更严格的条件。如果您可以将日志记录级别降低到 FINEST,您应该会看到更多与失败查找相关的条目(为此可能需要升级到 bctls-fips 的 1.0.11)。

我们为 bctls-fips 提供了一个源 jar,因此如果您能够在调试器中查看 X509KeyManager 调用,您可以找出找不到可接受凭据的具体原因。否则我们需要查看证书的更多详细信息。在这种情况下,在 our GitHub 提出问题可能会更好。 .


TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:我相信这是允许的,所以这是文档中的错误。


如果您处于批准模式,则不能使用单个 RSA key 进行签名/验证和加密/解密。 TLS_RSA_* 密码套件将使用 key 在服务器上解密,而 TLS_ECDHE_RSA_* 密码套件将使用 key 进行签名。为了启用两者,您需要为每种情况提供单独的 RSA 凭据,一个使用 KeyUsage 'digitalSignature',另一个使用 KeyUsage 'keyEncipherment'(这样 KeyManager 知道在每种情况下使用哪个)。 org.bouncycaSTLe.rsa.allow_multi_use 可以让它用于调试目的,但它不符合 FIPS 以允许在批准模式下多次使用。 org.bouncycaSTLe.jsse.fips.allowRSAKeyExchange 可用于禁用 TLS_RSA_*,推荐这样做,因为这些都是过时的密码套件。

关于ssl - BouncyCaSTLe JSSE 和 BCTLS 密码没有凭证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66316317/

相关文章:

java - 将自定义 SSL 证书添加到信任库但保留 Java 8+ 中的默认 cacerts?

java - ReSTLet 发送客户端证书

java - 如何使用 Bouncy CaSTLe ElGamal 和 javax.crypto.Cipher 显式加密 (c1, c2) 元组

java - 获取 JCE KeyGenerators 所有可能的 key 大小

wcf - 在 Azure 上的 WCF 中通过 SSL 配置 webHTTP 和 NetHTTP 绑定(bind)

ssl - AWS S3.NET 开发工具包

java - 未在 Java 中使用 ECDH KeyAgreement 生成正确的 AES key 大小

java - JSCEP-第三个参数类型错误。发现 : 'org.spongycaSTLe.pkcs.PKCS10CertificationRequest' , 需要: 'org.bouncycaSTLe.pkcs.PKCS10CertificationRequest'

java - AES-256 和 PKCS7Padding 在 Java 中失败

java - 优化 Java 中的文件加密