Java安全性:密钥大小或默认参数非法?


409

我早些时候曾问过一个问题,但没有得到正确的回答,也无济于事。

因此,我澄清了有关该问题的一些细节,我真的很想听听您关于如何解决此问题或应该尝试的想法。

我在Linux服务器上安装了Java 1.6.0.12,下面的代码运行得很完美。

String key = "av45k1pfb024xa3bl359vsb4esortvks74sksr5oy4s5serondry84jsrryuhsr5ys49y5seri5shrdliheuirdygliurguiy5ru";
try {
    Cipher c = Cipher.getInstance("ARCFOUR");

    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "ARCFOUR");
    c.init(Cipher.DECRYPT_MODE, secretKeySpec);

    return new String(c.doFinal(Hex.decodeHex(data.toCharArray())), "UTF-8");

} catch (InvalidKeyException e) {
    throw new CryptoException(e);
}

今天,我在服务器用户上安装了Java 1.6.0.26,当我尝试运行应用程序时,出现以下异常。我的猜测是它与Java安装配置有关,因为它在第一个版本中有效,但在更高版本中不起作用。

Caused by: java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
    at my.package.Something.decode(RC4Decoder.java:25) ~[my.package.jar:na]
    ... 5 common frames omitted

第25行是: c.init(Cipher.DECRYPT_MODE, secretKeySpec);

注意:
*服务器1.6.0.12 java目录上的java.security 与1.6.0.26 java.security文件几乎完全匹配。第一个中没有其他提供程序。
*上一个问题在这里



4
这也可能引发错误:(Caused by: java.security.InvalidKeyException: Illegal key size没有“或默认参数”)在Java 8中
-hackajar,2016年

只需使用OpenJDK,它将起作用。
Rodrigo Asensio

@RodrigoAsensio:我正在使用OpenJDK,它不起作用。您必须安装无限的“强度辖区策略文件” jar文件。然后它将起作用。
anjanb

5
更新为@AniketThakur答案。由于Java 9和Java 8u151,因此不再需要下载和手动安装管辖区策略文件。要启用无限加密,可以使用新的crypto.policy Security属性。如果在java.security文件中设置了新的Security属性(crypto.policy),或者在初始化JCE框架之前通过使用Security.setProperty()调用来动态设置了新的Security属性,则将接受该设置。默认情况下,该属性是未定义的。
MarcinKłopotek'17

Answers:


722

您很可能现在没有安装无限强度文件。

您可能需要下载此文件:

Java密码术扩展(JCE)无限强度管辖权策略文件6

Java密码术扩展(JCE)无限强度管辖权策略文件7下载

Java密码术扩展(JCE)无限强度管辖权策略文件8下载(仅Java 8 u162之前的版本需要)

从zip中提取jar文件并将其保存在中${java.home}/jre/lib/security/


2
@JamesBlack -是的,并确保所有的基础覆盖我把JAR的下Java/jre/lib/securityJava/jdk/lib/securityJava/jdk/jre/lib/security。运行“ java -version”将返回预期的详细信息。
aroth 2012年


4
由于Java 9和Java 8u151,因此不再需要下载和手动安装管辖区策略文件。要启用无限加密,可以使用新的crypto.policy Security属性。如果在java.security文件中设置了新的Security属性(crypto.policy),或者在初始化JCE框架之前通过使用Security.setProperty()调用来动态设置了新的Security属性,则将接受该设置。默认情况下,该属性是未定义的。
MarcinKłopotek'17

4
因此,此投票的答案现在已过时,已弃用。我们如何提高或抑制该答案,以便stackoverflow.com/a/46857694/2808798成为“已接受”的答案?
杰西·阿德尔曼

3
@JesseAdelman-不幸的是,这已经快7年了,不能做很多事情。询问的任何人都需要更改它。
詹姆斯·布莱克

54

可以在以下位置找到JRE / JDK / Java 8管辖区文件:

Java密码术扩展(JCE)无限强度管辖权策略文件8下载

就像上面的詹姆斯所说:在中
安装文件${java.home}/jre/lib/security/


2
尝试使用6和7,但是它们没有用。不得不安装8。谢谢。
詹森·金

9
新版本的JDK 8u151具有“用于控制加密策略的新安全性”。现在是要切换的属性更改。最重要的是:从“ lib \ security \ java.security”中的“#crypto.policy = unlimited”行中删除“#”以启用使用256位密钥。oracle.com/technetwork/java/javase/8u151-relnotes-3850493.html
hemisphire

1
谢谢!由于这是一个安全属性,因此您也可以调用Security.setProperty(“ crypto.policy”,“ unlimited”)。来源:@hemisphire的链接:)
Fluf

42

对于JAVA 7,下载链接为jce-7-download

在Java \ jdk1.7.0_10 \ jre \ lib \ security中复制两个下载的jar

对于JAVA 8,下载链接为jce-8-download
在Java \ jdk1.8.0_45 \ jre \ lib \ security中复制下载的jar文件。为确保安全,
请备份较旧的jar文件。


39

对于Java 9,Java 8u161Java 7u171Java 6u181,现在默认情况下禁用此限制。请参阅Java Bug数据库中的问题


Java 8u151开始,您可以以编程方式禁用该限制。

在较早的版本中,必须分别下载和安装JCE管辖区文件,以允许JDK使用无限的加密技术。不再需要下载和安装步骤。

相反,您现在可以在首次使用JCE类之前(即,最好在应用程序启动后立即)调用以下行:

Security.setProperty("crypto.policy", "unlimited");

在Android中呢?这些限制方法可以在哪个API级别上解决?
TheRealChx101 '19

31

这是仅代码解决方案。无需下载或弄乱配置文件。

这是基于反射的解决方案,已在Java 8上进行了测试

在程序的早期,一次调用此方法。

//导入

import javax.crypto.Cipher;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;

//方法

public static void fixKeyLength() {
    String errorString = "Failed manually overriding key-length permissions.";
    int newMaxKeyLength;
    try {
        if ((newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES")) < 256) {
            Class c = Class.forName("javax.crypto.CryptoAllPermissionCollection");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissionCollection = con.newInstance();
            Field f = c.getDeclaredField("all_allowed");
            f.setAccessible(true);
            f.setBoolean(allPermissionCollection, true);

            c = Class.forName("javax.crypto.CryptoPermissions");
            con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissions = con.newInstance();
            f = c.getDeclaredField("perms");
            f.setAccessible(true);
            ((Map) f.get(allPermissions)).put("*", allPermissionCollection);

            c = Class.forName("javax.crypto.JceSecurityManager");
            f = c.getDeclaredField("defaultPolicy");
            f.setAccessible(true);
            Field mf = Field.class.getDeclaredField("modifiers");
            mf.setAccessible(true);
            mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
            f.set(null, allPermissions);

            newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");
        }
    } catch (Exception e) {
        throw new RuntimeException(errorString, e);
    }
    if (newMaxKeyLength < 256)
        throw new RuntimeException(errorString); // hack failed
}

鸣谢:Delthas


4
请注意,这可能违反Java SE许可协议:D. JAVA技术限制。您不得创建,修改或更改以任何方式标识为“ java”,“ javax”,“”的类,接口或子程序包的行为,或授权被许可方创建,修改或更改其行为。 javafx“,” sun“,” oracle“或Oracle在任何命名约定名称中指定的类似约定。[...] 来源
SimMac,

非常感谢


16

使用Windows 7 x64,Eclipse和JDK 1.6.0_30时遇到了相同的错误。在JDK安装文件夹中,有一个jre文件夹。起初,这很让我失望,因为我将上述jar添加到JDK的lib / security文件夹中没有运气。完整路径:

C:\Program Files\Java\jdk1.6.0_30\jre\lib\security

下载此存档jce文件夹中包含的文件并将其解压缩到该文件夹​​中。


16

在Java中,默认情况下AES支持128位密钥,如果您计划使用192位或256位密钥,则Java编译器将抛出非法密钥大小异常,您将得到该异常。

该解决方案是根据victor&James的建议,您需要根据您的JRE版本(java6,java7或java8)下载JCE(Java密码学扩展)。

JCE压缩文件包含以下JAR:

  1. local_policy.jar
  2. US_export_policy.jar

您需要将这些罐子更换成您的<JAVA_HOME>/jre/lib/security。如果您使用的是Unix系统,则可能是指/home/urs/usr/lib/jvm/java-<version>-oracle/

有时仅替换安全文件夹中的local_policy.jar和US_export_policy.jar在Unix上不起作用,所以我建议先将安全文件夹复制到您的桌面,替换jar的@ Desktop / security文件夹,从/ jre / lib中删除安全文件夹/&将桌面安全文件夹移动到/ jre / lib /。

例如:: sudo mv security /usr/lib/jvm/java-7-oracle/jre/lib


5

还有的似乎是这个问题的一个简短的讨论在这里链接到的页面似乎已消失,但是您可能需要以下响应之一:

实际上,将US_export_policy.jar和local_policy.jar从core / lib / jce复制到$ JAVA_HOME / jre / lib / security很有帮助。谢谢。


谢谢,但我已经US_export_policy.jarlocal_policy.jar我的lib / security文件夹中已经有一次我安装了Java ..我不能在我的Java安装文件夹的方式找到核心/ lib中/ JCE。
Rihards

5

问题是如果安装JRE,则文件夹jre \ lib \ securitylocal_policy.jar中文件default_local.policy内容

// Some countries have import limits on crypto strength. This policy file
// is worldwide importable.

grant {
    permission javax.crypto.CryptoPermission "DES", 64;
    permission javax.crypto.CryptoPermission "DESede", *;
    permission javax.crypto.CryptoPermission "RC2", 128,
                                     "javax.crypto.spec.RC2ParameterSpec", 128;
    permission javax.crypto.CryptoPermission "RC4", 128;
    permission javax.crypto.CryptoPermission "RC5", 128,
          "javax.crypto.spec.RC5ParameterSpec", *, 12, *;
    permission javax.crypto.CryptoPermission "RSA", *;
    permission javax.crypto.CryptoPermission *, 128;
};

如果您不需要全球有效的设置,则只需编辑此文件并将内容更改为

// Country-specific policy file for countries with no limits on crypto strength.
grant {
    // There is no restriction to any algorithms.
    permission javax.crypto.CryptoAllPermission;
};

如果从Oracle下载JCE,这将得到什么。


4

我也遇到了问题,但是用从JCE下载的现有文件替换了现有文件后,一个文件解决了该问题。新的加密文件提供了无限的强度。


2

默认情况下,Java仅支持AES 128位(16字节)密钥大小进行加密。如果您不需要的仅是默认值,则可以在使用之前将密钥修整为适当的大小Cipher。有关默认的受支持密钥,请参见javadoc

这是生成无需修改策略文件即可在任何JVM版本上使用的密钥的示例。自行决定使用。

这是一篇关于AgileBits博客上密钥128到256密钥大小是否重要的​​好文章

SecretKeySpec getKey() {
    final pass = "47e7717f0f37ee72cb226278279aebef".getBytes("UTF-8");
    final sha = MessageDigest.getInstance("SHA-256");

    def key = sha.digest(pass);
    // use only first 128 bit (16 bytes). By default Java only supports AES 128 bit key sizes for encryption.
    // Updated jvm policies are required for 256 bit.
    key = Arrays.copyOf(key, 16);
    return new SecretKeySpec(key, AES);
}

密码类的文档指向有效的密钥长度为每个密码类型。
keaplogik

请参见Oracle文档Cipher(加密)算法 AES:NIST在FIPS 197中指定的高级加密标准。Joan Daemen和Vincent Rijmen也称为Rijndael算法,AES是一种128位块密码,支持128、192,和256位。
zaph

可能是这样,但是每个Java版本仅要求支持类文档中指定的128位。自己进行测试,您会发现您需要James Black的答案中的政策罐来做其他关键尺寸
keaplogik

任何不支持256位密钥的AES实现基本上都是无用的,因为它无法使用256位密钥解密大量的AES加密。
zaph

1
如果需要256位密钥,最好的解决方案(也许是唯一的解决方案)是在需要时安装策略文件,不要截断密钥,这可能会削弱安全性,并且在互操作性的情况下可能无法实现。
zaph


2

如果您将Linux发行版与apt一起使用并添加了webupd8 PPA,则只需运行以下命令

apt-get install oracle-java8-unlimited-jce-policy

其他更新:

  1. Java 9随附了无限强度管辖权策略文件,默认情况下使用
  2. Java 8 Update 161开始,Java 8默认为无限制强度管辖策略。
  3. Java 8 Update 151开始,Java 8附带了无限强度管辖策略,但默认情况下不使用。要启用它,您需要在<java_home>/jre/lib/security(对于JDK)或<java_home>/lib/security(对于JRE)中编辑java.security文件。取消注释(或包括)该行

    crypto.policy=unlimited

    确保使用以管理员身份运行的编辑器来编辑文件。策略更改仅在重新启动JVM后生效

Java 8 Update 151之前,其余答案仍然有效。下载JCE无限强度管辖权策略文件并替换。

有关更多详细信息,您可以参考下面我的个人博客文章- 如何安装Java密码学扩展(JCE)无限强度管辖权策略文件


1

有两种方法可以解决此问题

选项1:使用长度较短的证书RSA 2048

选项2:jre\lib\security 无论使用什么Java,您都将更新两个jars http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

或者使用IBM Websphere或使用其java的任何应用程序服务器。我面临的主要问题是我在最大长度上使用了认证,当我在Websphere上部署耳朵时,会抛出相同的异常

Java Security: Illegal key size or default parameters?

我用两个罐子更新了Websphere中的java intsalled文件夹 https://www14.software.ibm.com/webapp/iwm/web/reg/pick.do?source=jcesdk&lang=zh_CN

您可以在链接https://www-01.ibm.com/support/docview.wss?uid=swg21663373中查看参考



1

由于美国的限制,默认JDK仅通过128位密钥支持加密。因此,要支持256位长密钥的加密,我们必须将其替换local_policy.jarUS_export_policy.jars放在$JAVA_HOME/java-8-oracle/jre/lib/security文件夹中,否则它将提供:

java.security.InvalidKeyException:密钥大小非法或默认


0

你要去那边

/jdk1.8.0_152 | / jre | / lib | /安全| java.security和取消注释

#crypto.policy=unlimited

crypto.policy=unlimited
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.