【问题标题】:configure tomcat/hibernate to have a cryptographic provider supporting 1.2.840.113549.1.5.13将 tomcat/hibernate 配置为具有支持 1.2.840.113549.1.5.13 的加密提供程序
【发布时间】:2019-10-21 14:44:49
【问题描述】:

在配置带有 jndi 数据源的 tomcat 以使用 ssl 身份验证连接到 postgres 服务器时(请参阅providing certificates to tomcat jndi connection to postgresql),我遇到以下错误:

[main] WARN org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata : Cannot create PoolableConnectionFactory (Could not find a java cryptographic algorithm: Cannot find any provider supporting 1.2.840.113549.1.5.13.)

(这是初始化时的警告,但当我实际尝试使用连接时,我看到的与阻止访问数据库的错误相同)。

基于此答案:Reading PKCS8 in PEM format: Cannot find provider 我已尝试通过添加org.bouncycastle.jce.provider.BouncyCastleProvider 作为第一个安全提供程序来修改/usr/lib/jvm/java-11-openjdk-amd64/conf/security/java.security。我还尝试将 jar bcprov-jdk15on-1.64.jar 添加到 /usr/lib/jvm/java-11-openjdk-amd64/lib 和 /usr/share/java(任何地方都没有 lib/ext 目录)。

问题依然存在。

我应该如何告诉将 Bouncy Castle 安全提供程序用于 java 运行时、tomcat 或休眠?

更新: 也尝试安装libbcprov-java并在java.security中设置安全提供程序,但没有成功。

【问题讨论】:

  • 该异常消息没有说明它想要什么对象 (API)。正如我在您链接的 A 中所说,该 OID 是 PBES2 的“外部”(通用)OID。它不是一个实际的方案,也不是由标准提供者 或 Bouncy 实现的方案,但标准 SunJCE (not Bouncy) 确实实现了它(作为 @ 的别名987654329@)为AlgorithmParameters(参数化实际方案)。您是否或能否获得完整的堆栈跟踪,或者至少是前 10 名左右?如果它被休眠吞没,请尝试一个独立的程序,它只连接相同的驱动程序和连接字符串。 ...
  • ... 或者作为一种解决方法,您可以将密钥更改为单级方案;原来的 PKCS5v1 方案都被破坏了,但是 PKCS12 方案 pbeWithSHA1And3-KeyTripleDES-CBC 仍然可以接受,甚至相当普遍。最后,是的,lib/ext 从 java 9 开始被删除;现在您可以在类路径中放置一个像 bcprov 这样的附加组件,或者如果您真的想要在 JRE 中使用它,请使用 jlink 创建一个“定制的”JRE。
  • 您可以在此处找到完整的堆栈跟踪:github.com/pgjdbc/pgjdbc/issues/1585 据我了解,SunJCE 确实实现了它,但不知道 oid,而 Bouncy 实现了它。如果我能理解如何修改密钥,我会的。我已经将它转换为 pkcs-8,但它没有帮助。

标签: java hibernate ssl tomcat


【解决方案1】:

我认为答案的信息已经足够了,这比 cmets 更具可读性。更安全。

SunJCE 和 bcprov 都为多个 PBES2 系列密码(以及 PBKDF2 作为一个组件)实现了Cipher 实例,但都没有为 PBES2 实现Cipher,无论是按名称还是 OID,因为 PBES2 不是一个密码,这是他们的一个(大)家庭。正如我所指出的,SunJCE 确实通过 OID 和名称为 PBES2 实现了AlgorithmParameters。 (Bouncy 当然在内部实现了 PBES2 参数,在我看来它们可以在直接或“轻量级”API 中使用,但它不会通过提供者 SPI 公开它们。)

您的密钥文件是 PKCS8 加密格式;问题是 PKCS8 加密可以使用许多加密方案(密码),包括不是由一个 OID 标识的 PBES2 系列(如 PKCS5v1 和 PKCS12 中较旧/较简单的),而是三个:“外部”PBES2、PBKDF2(带有派生参数)和底层对称密码(带有加密参数)。

假设 https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/java/org/postgresql/ssl/LazyKeyManager.java 是正确的代码(第 205 行确实与您的堆栈跟踪匹配),这显然不是为处理两级 (PBES2) 情况而设计的。但是,它确实首先尝试unencrypted PKCS8,并且只有在失败时才尝试encrypted PKCS8 使用由一个OID 标识的方案。因此,如果您的环境中有一个未加密的密钥文件是可以接受的,那应该可以工作,我建议使用使用 PKCS12 的 pbeWithSHAAnd3-KeyTripleDES-CBC 等单级方案加密的 PKCS8 的建议也应该如此——在检查时我看到 SunJCE 实际上命名为 PBEWithSHA1AndDESede 但是使用正确的 OID 1.2.840.113549.1.12.1.3,这在这里很重要。 (bcprov 使用标准名称,但大写除外——JCA 不区分大小写。)

根据创建密钥文件的软件或进程,可以对其进行调整以生成所需的格式。如果没有,并且您拥有或获得 OpenSSL,它可以处理许多(大多数)PKCS8 选项:

# we need an intermediate PEM file; for safety (PB)encrypt it
openssl pkey <p8unusable.der -inform d -aes256 >temp.pem

# to unencrypted PKCS8
openssl pkcs8 -topk8 <temp.pem -outform d -nocrypt >p8unenc.der

# to encrypted PKCS8 using single-level PKCS12 scheme
openssl pkcs8 -topk8 <temp.pem -outform d -v1 pbeWithSHA1And3-KeyTripleDES-CBC >p8encone.der
# note OpenSSL spells SHA1 where PKCS12 had SHA (which was technically wrong)
# OTOH OpenSSL implies this is PKCS5v1 which it isn't. Bleah.

rm temp.pem # or erase or whatever

【讨论】:

  • 解决方案是为 openssl pkcs8 提供 -v1 PBE-MD5-DES 选项。正如我所见,您的解决方案基本相同,但经过更多研究。所以我接受了。
  • PBE-MD5-DES 的缺点是单 DES 已经可以破解 20 年了,今天很容易破解——上次我看了大约 50 美元——所以它实际上并不安全,但只是看了一眼就发现它已加密的人可能会认为它是加密的。
猜你喜欢
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
  • 2023-03-22
  • 2018-10-19
  • 2016-11-04
  • 2012-06-21
  • 2014-10-10
  • 2015-07-01
相关资源
最近更新 更多