引起:java.lang.SecurityException: 权限策略文件没有由预期的签名者签名!

问题描述

问题
我应该深入研究或解决似乎与 JCE 和 MongoDB 相关的问题有哪些可能的方法

简要
多年来,我一直在开发基于 Java 的项目。今天遇到一个貌似和MongoDB和JCE有关的问题。我通过 IntelliJ 使用 Maven 将项目编译成一个 uber jar,并尝试在我的 Mac Pro 上执行 uber jar。
jar 可以一直执行,直到它尝试调用可以查看其源代码com.mongodb.DBPort$ScramSha1Authenticator$ScramSha1SaslClient.Hi here

不同 MongoDB 版本的异常消息
MongoDB版

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>2.14.3</version>
</dependency>
Exception in thread "main" java.lang.ExceptionInInitializerError
    at javax.crypto.SecretKeyFactory.nextSpi(SecretKeyFactory.java:295)
    at javax.crypto.SecretKeyFactory.<init>(SecretKeyFactory.java:121)
    at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:160)
    at com.mongodb.DBPort$ScramSha1Authenticator$ScramSha1SaslClient.Hi(DBPort.java:839)
    at com.mongodb.DBPort$ScramSha1Authenticator$ScramSha1SaslClient.computeClientFinalMessage(DBPort.java:760)
    at com.mongodb.DBPort$ScramSha1Authenticator$ScramSha1SaslClient.evaluateChallenge(DBPort.java:694)
    at com.mongodb.DBPort$SaslAuthenticator.authenticate(DBPort.java:917)
    at com.mongodb.DBPort.authenticate(DBPort.java:445)
    at com.mongodb.DBPort.checkAuth(DBPort.java:456)
    at com.mongodb.DBTCPConnector.innerCall(DBTCPConnector.java:293)
    at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:273)
    at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:86)
    at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:68)
    at com.mongodb.DBCursor._check(DBCursor.java:498)
    at com.mongodb.DBCursor._hasNext(DBCursor.java:621)
    at com.mongodb.DBCursor.hasNext(DBCursor.java:657)
    .
    .
    .
Caused by: java.lang.SecurityException: Can not initialize cryptographic mechanism
    at javax.crypto.JceSecurity.<clinit>(JceSecurity.java:93)
    ... 20 more
Caused by: java.lang.SecurityException: The jurisdiction policy files are not signed by the expected signer! (Policy files are specific per major JDK release.Ensure the correct version is installed.)
    at javax.crypto.JarVerifier.verifyPolicySigned(JarVerifier.java:336)
    at javax.crypto.JceSecurity.loadPolicies(JceSecurity.java:378)
    at javax.crypto.JceSecurity.setupJurisdictionPolicies(JceSecurity.java:323)
    at javax.crypto.JceSecurity.access$000(JceSecurity.java:50)
    at javax.crypto.JceSecurity$1.run(JceSecurity.java:85)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.crypto.JceSecurity.<clinit>(JceSecurity.java:82)
    ... 20 more

MongoDB 版本

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.12.7</version>
</dependency>
    .
    .
    .
Exception in thread "main" java.lang.ExceptionInInitializerError
    at javax.crypto.Cipher.getInstance(Cipher.java:518)
    at sun.security.ssl.JsseJce.getCipher(JsseJce.java:189)
    at sun.security.ssl.SSLCipher.isTransformationAvailable(SSLCipher.java:483)
    at sun.security.ssl.SSLCipher.<init>(SSLCipher.java:472)
    at sun.security.ssl.SSLCipher.<clinit>(SSLCipher.java:81)
    at sun.security.ssl.CipherSuite.<clinit>(CipherSuite.java:67)
    at sun.security.ssl.SSLContextImpl.getApplicableSupportedCipherSuites(SSLContextImpl.java:345)
    at sun.security.ssl.SSLContextImpl.access$100(SSLContextImpl.java:46)
    at sun.security.ssl.SSLContextImpl$AbstractTLSContext.<clinit>(SSLContextImpl.java:577)
    at java.lang.class.forName0(Native Method)
    at java.lang.class.forName(Class.java:264)
    at java.security.Provider$Service.getImplClass(Provider.java:1728)
    at java.security.Provider$Service.newInstance(Provider.java:1686)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
    at javax.net.ssl.SSLContext.getInstance(SSLContext.java:156)
    at javax.net.ssl.SSLContext.getDefault(SSLContext.java:96)
    at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:122)
at com.mongodb.MongoClientOptions.<clinit>(MongoClientOptions.java:60)
    .
    .
    .
    .
    .
Caused by: java.lang.SecurityException: Can not initialize cryptographic mechanism
    at javax.crypto.JceSecurity.<clinit>(JceSecurity.java:93)
    ... 24 more
Caused by: java.lang.SecurityException: The jurisdiction policy files are not signed by the expected signer! (Policy files are specific per major JDK release.Ensure the correct version is installed.)
    at javax.crypto.JarVerifier.verifyPolicySigned(JarVerifier.java:336)
    at javax.crypto.JceSecurity.loadPolicies(JceSecurity.java:378)
    at javax.crypto.JceSecurity.setupJurisdictionPolicies(JceSecurity.java:323)
    at javax.crypto.JceSecurity.access$000(JceSecurity.java:50)
    at javax.crypto.JceSecurity$1.run(JceSecurity.java:85)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.crypto.JceSecurity.<clinit>(JceSecurity.java:82)
    ... 24 more

一些信息
Mac Pro 上的 Java

$ sw_vers
ProductName:    macOS
ProductVersion: 11.1
BuildVersion:   20C69

$ java -version
java version "1.8.0_281"
Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09,mixed mode)

Intellij 上的 Java

adopt-openjdk-1.8 (1.8.0_275)

来自 Oracle JDK 8u161 发行说明中的​​ a mention

JDK 使用 Java 加密扩展 (JCE) 权限策略文件来配置加密算法限制。以前,JDK 中的策略文件对各种算法进行了限制。此版本随附有限制和无限制的管辖权策略文件认为无限制。该行为可以通过 /lib/java.security 文件中的新“crypto.policy”安全属性进行控制。有关此属性的更多信息,请参阅该文件

来自 Oracle JDK 8u261 发行说明中的​​ a mention

自 2018 年 1 月(8u161、7u171)起,无限的 Java 加密扩展 (JCE) 权限策略文件已与 JDK 捆绑在一起并认启用(请参阅 JDK 加密路线图)。
旧的独立 jar 的证书已过期,如果使用,将看到以下异常:

Caused By: java.lang.SecurityException: The jurisdiction policy
files are not signed by the expected signer! 
(Policy files are specific per major JDK release.Ensure the correct version is installed.) 
at javax.crypto.JarVerifier.verifyPolicySigned(JarVerifier.java:336) 
at javax.crypto.JceSecurity.loadPolicies(JceSecurity.java:378) 
at javax.crypto.JceSecurity.setupJurisdictionPolicies(JceSecurity.java:323) 
at javax.crypto.JceSecurity.access$000(JceSecurity.java:50) 
at javax.crypto.JceSecurity$1.run(JceSecurity.java:85) 
at java.security.AccessController.doPrivileged(Native Method) 
at javax.crypto.JceSecurity.<clinit>(JceSecurity.java:82)

如果旧版本仍然需要重新签名的文件,请访问 https://www.oracle.com/java/technologies/oracle-java-archive-downloads.html

参考资料

  1. java.lang.SecurityException: The jurisdiction policy files are not signed by a trusted signer
  2. How to install unlimited strength JCE for Java 8 in OS X?
  3. Docs.microfocus.com。 2019. ITOM 从业者门户。 [在线] 可在:https://docs.microfocus.com/itom/Network_Operations_Management:2019.11/RemovalOfJCE [2021 年 1 月 22 日访问]。
  4. Oracle.com。 2018 年。Java™ SE 开发工具包 8,更新 161。 [在线] 可在:https://www.oracle.com/java/technologies/javase/8u161-relnotes.html#JDK-8170157 [2021 年 1 月 22 日访问]。
  5. Oracle.com。 2020 年。Java™ SE 开发工具包 8,更新 261 发行说明。 [在线] 可在:https://www.oracle.com/java/technologies/javase/8u261-relnotes.html#JDK-8245319 [2021 年 1 月 22 日访问]。

解决方法

这就是我最终解决的方法。

  1. here 下载 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。
    而且您需要注册成为 Oracle 会员,是的,没错!
  2. 备份原始策略文件。
    cd $JAVA_HOME/lib/security
    sudo cp US_export_policy.jar US_export_policy.jar.backup
    sudo cp local_policy.jar local_policy.jar.backup
    
  3. 在注册成为 Oracle 会员后放置您刚刚下载的策略文件。
    sudo cp ~/Download/UnlimitedJCEPolicyJDK8/*.jar $JAVA_HOME/lib/security/
    

我尝试用brew安装openjdk8,仍然出现该现象(异常信息)。