有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JAVA安全InvalidKeyException:安卓中的密钥大小或默认参数非法

我犯了以下错误,有点卡住了: 线程“main”中出现异常

java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011)
                at javax.crypto.Cipher.implInit(Cipher.java:786)
                at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
                at javax.crypto.Cipher.init(Cipher.java:1213)
                at javax.crypto.Cipher.init(Cipher.java:1153)
                at net.nakou.indie.wtext.engineClass.Session.cryptString(Session.java:52)

我被卡住了,因为我找到的所有答案都是关于Java加密扩展(JCE),它通常包含在安卓 SDK中。所以我想我的问题不是这个

我一定忘了什么,但我找不到什么。也许我的代码错了(这是我在Java中第一次使用加密技术,我不是专家,下面的代码主要是一些教程的复制粘贴)

我使用以下代码对字符串进行加密和解密:

public String cryptString(String s) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException {
    byte[] KeyData = this.cryptKey.getBytes();
    SecretKeySpec KS = new SecretKeySpec(KeyData, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, KS);
    String ret = new String(cipher.doFinal(s.getBytes("UTF-8")));
    return ret;
}

public String decryptString(byte[] s) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] KeyData = this.cryptKey.getBytes();
    SecretKeySpec KS = new SecretKeySpec(KeyData, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.DECRYPT_MODE, KS);
    String ret = new String(cipher.doFinal(s));
    return ret;
}

以及以下关键点:

private String cryptKey = "qkjll5@2md3gs5Q@FDFqf";

谢谢你们


共 (5) 个答案

  1. # 3 楼答案

    自Java 8/9以来一直有更新

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

      crypto.policy=unlimited

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

    Java 8 Update 151之前,您必须下载JCE Unlimited Strength辖区策略文件并替换

    有关更多详细信息,请参见How to install Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files

    注:以上链接指向我的个人博客,其中包含更多详细信息

  2. # 4 楼答案

    由于美国的限制,默认JDK仅支持通过128位密钥进行加密。因此,为了支持256位长密钥的加密,我们必须替换本地_策略。jar和美国的出口政策。jars位于$JAVA_HOME/JAVA-8-oracle/jre/lib/security文件夹中,否则它将提供JAVA。安全InvalidKeyException:密钥大小非法或默认

  3. # 5 楼答案

    这是一个只使用代码的解决方案。无需下载或处理配置文件

    这是一个基于反射的解决方案,在Java8上进行了测试

    在程序早期或应用程序启动时调用此方法一次

    //进口

    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
    }