InvalidKeyException Illegal key size

64

我有一个测试在我的开发MacBook Pro上运行得很好,但在持续集成TeamCity服务器上无法运行。

错误信息如下:

java.security.InvalidKeyException: Illegal key size
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)

开发环境和TeamCity都使用Java 1.6,我需要使用BouncyCastle库进行特殊的AES加密。

下面是代码:

private byte[] aesEncryptedInfo(String info) throws UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidParameterSpecException, InvalidAlgorithmParameterException, NoSuchProviderException {
    Security.addProvider(new BouncyCastleProvider());
    SecretKey secret = new SecretKeySpec(CUSTOMLONGSECRETKEY.substring(0, 32).getBytes(), "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
    cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(VECTOR_SECRET_KEY.getBytes()));
    return cipher.doFinal(info.getBytes("UTF-8"));
}

更新

根据所选答案,看起来我需要修改我的TeamCity安装并可能会影响一些用户的安装 - 所以这不是一个好选择,我必须切换到另一个加密库来避免限制。所以很可能Bouncy Castle会有帮助。

更新2

实际上,我已经切换到使用Bouncy Castle来避免这种限制。请注意,这仅适用于直接使用自己的BC类,而不是BC提供程序。


或者,您可以使用更弱的密钥 :-) (128位仍被认为是安全的,您不需要安装该策略文件) - Peter Štibraný
顺便提一下,Bouncy Castle 也有同样的限制:http://www.bouncycastle.org/wiki/display/JA1/Frequently+Asked+Questions(第一个问题/答案) - Peter Štibraný
1
Bouncy Castle 提供了两个 API -- 你链接的 FAQ 是关于 Bouncy Castle Provider 的,它是一个 JCE 实现并且受到 JCE 限制;而 Bouncy Castle 特定的 API 则没有限制。 - Jules
6个回答

137

这个错误意味着你的Java虚拟机使用了一个策略,该策略仅允许受限密钥大小的加密,原因是美国出口法规。

Java 9及更高版本

Java 9中包含了无限制强度管辖区政策文件,并且默认情况下使用(请参见Java 9迁移指南中的安全更新)。

如果你在Java 9中遇到了这个错误,可能意味着策略配置已经更改为更严格的策略(limited),请参考迁移指南中的说明:

JCE Jurisdiction Policy File Default is Unlimited

如果你的应用程序以前需要Java加密扩展(JCE)无限制强度管辖区政策文件,则你不需要再下载或安装它们。它们已经包含在JDK中,并且默认情况下已激活。

如果你的国家或使用需要更严格的策略,则仍然可以使用有限的Java加密策略文件。

如果默认提供的任何策略文件都无法满足你的需求,则可以自定义这些策略文件以满足你的需求。

请参见<java-home>/conf/security/java.security文件中的crypto.policy安全属性,或Java平台标准版安全开发人员指南中的加密强度配置

Java 8及更早版本

Java 8 Update 161及更高版本

从Java 8 Update 161开始,Java 8默认使用无限制强度管辖区政策。如果你收到此错误消息,则可能表明配置已更改为limited。请参见下一节Java 8 Update 151,或上一节Java 9中的说明,以将其更改回unlimited

Java 8 Update 151及更高版本

从Java 8 Update 151开始,Java 8包含了无限制强度管辖区政策,但不是默认情况下使用。要启用它,你需要编辑<java_home>/jre/lib/security(对于JDK)或<java_home>/lib/security(对于JRE)中的java.security文件。取消注释(或包含)以下行:

crypto.policy=unlimited

请确保使用以管理员身份运行的编辑器编辑文件。

策略更改只有在重新启动JVM后才会生效(对于像Tomcat这样长时间运行的服务器进程尤为重要)。

为了向后兼容,按照下一节中所述的文档安装策略文件仍将奏效。

Java 8 Update 151之前

对于Java 8 Update 144及更早版本,您需要安装Java密码扩展(JCE)无限制强度司法管辖区政策文件(可在Oracle上获取)。

要安装这些文件(从下载的README.txt中):

  1. 下载无限制强度的JCE策略文件。

  2. 解压缩并提取已下载的文件。

    这将创建一个名为jce的子目录。 此目录包含以下文件:

    README.txt                   This file
    local_policy.jar             Unlimited strength local policy file
    US_export_policy.jar         Unlimited strength US export policy file
    
    安装无限强度策略JAR文件。如果您以后决定恢复到原始的“强”但有限的策略版本,请先复制原始的JCE策略文件(US_export_policy.jar和local_policy.jar)。然后用在上一步中提取的无限强度版本替换强策略文件。JCE司法管辖区政策JAR文件的标准位置是:
    <java-home>/lib/security           [Unix]
    <java-home>\lib\security           [Windows]
    
    对于JDK而言,它在jre/lib/security中。
    只有重启JVM之后新的策略文件才会生效(这对于像Tomcat这样长时间运行的服务器进程来说尤其重要)。

我没有特别在我的开发电脑上安装JCE USJ,但它可以在那里正常工作。 - Vladimir
你认为它可以默认安装在那里,而不是安装在服务器上吗? - Vladimir
@弗拉基米尔:我无法找到苹果是否捆绑了无限强度策略文件,但这些文件未捆绑在Oracle(或之前的Sun)提供的JVM中。如果您的TeamCity运行在Linux / Windows上,则需要自行在构建服务器上安装无限强度策略文件。 - Peter Štibraný
Hooked on Phonics 对我很有帮助!我的意思是,USJ 策略文件。 - stannius
4
请注意,在安装新的策略文件后,您可能需要重新启动运行在 JVM 中的任何内容。例如,我不得不在 Web 应用程序成功应用更改之前重新启动 Tomcat。 - user
1
晚了一点但: 这个问题适用于Java包中的JCE接口,这些包现在属于Sun-now-Oracle。我看到的大多数Linux发行版都从OpenJDK源构建自己的软件包,这些'openjdk'软件包通常没有最大128位策略。 - dave_thompson_085

8

我曾经遇到过类似的问题,但在我的情况下是路径错误。

JAVA_HOME 是 jdk1.6.0_18,所以我把这两个 jar 文件放到了 jdk1.6.0_18/lib/security 目录下,但实际上在 jdk1.6.0_18 目录下还有一个 jre 目录。这两个文件应该被放在 jdk1.6.0_18/jre/lib/security 目录下。


1
接受的答案假设您拥有管理员权限以作为管理员修改文件和文件夹。
如果不是这种情况,对于Java 8 Update 151及更高版本,您可以执行以下操作:
- 创建一个本地文件,其中包含一行`crypto.policy=unlimited`。 - 在您的Java命令中添加`-Djava.security.properties=`,其中``是您创建的本地文件。
除非明确禁用(默认启用)`security.overridePropertiesFile`,否则此方法应该有效。
参考:`/jre/lib/security/java.security`。
#
# This is the "master security properties file".
#
# An alternate java.security properties file may be specified
# from the command line via the system property
#
#    -Djava.security.properties=<URL>
#
# This properties file appends to the master security properties file.
# If both properties files specify values for the same key, the value
# from the command-line properties file is selected, as it is the last
# one loaded.
#
# Also, if you specify
#
#    -Djava.security.properties==<URL> (2 equals),
#
# then that properties file completely overrides the master security
# properties file.
#
# To disable the ability to specify an additional properties file from
# the command line, set the key security.overridePropertiesFile
# to false in the master security properties file. It is set to true
# by default.
...

1
除了安装策略文件之外,还要确保CUSTOMLONGSECRETKEY...getBytes()确实生成32字节的数组。我会使用CUSTOMLONGSECRETKEY.getBytes(某种编码)并从中获取前32个字节。更好的方法是使用整个密钥来派生AES密钥,以获得所需的大小。

1
CUSTOMLONGSECRETKEY是常量=“3C7C6086-CF22-4972-9616-F294DAF77092”,对于两次运行都是如此。我想知道它会如何影响TeamCity。 - Vladimir
1
@Vladimir:我想指出你应该使用明确编码的getBytes,但这似乎不是你的密钥问题。我建议你尝试安装策略文件。如果你不这样做,AES加密将被限制在128位密钥上。 - Peter Štibraný

1

我曾经遇到过与jdk 1.8.0_151-相关的相同问题。

对于此版本及以上版本,您不需要下载与安全相关的jar文件。因为,local_policy.jar和US_export_policy.jar已经包含在这些版本中,路径为- \jre\lib\security\policy(JAVA_HOME指的是您当前的java安装文件夹) 您唯一需要做的更改是在java.security文件中进行修改,该文件位于/jre/lib/security - 取消注释以下行 - crypto.policy=unlimited


这对我来说在1.8.0_181版本中有效。 - user3182536

0

确保您知道IDE使用的JAVA_HOME路径,以便复制到正确的路径。

在我的情况下,我使用IntelliJ: /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/jre/lib/security

与在控制台中显示$JAVA_HOME不同。 /Users/myuser/.sdkman/candidates/java/current/jre/lib/security


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接