當秘鑰長度超過128位(即16字符時),會加密失敗,報“java.security.InvalidKeyException: Illegal key size or default parameters”的異常,因此需要去掉該限制
處理的方法由三種,分別是直接替換或是自定義classloader加載放開限制的jar或者通過反射移除限制
1.直接替換
比如java8的話,去orcle官網http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip下載,加載后解壓將其中的“local_policy.jar ”和“US_export_policy.jar”兩個文件替換掉自己%JAVE_HOME%\jre\lib\security文件夾下對應的原文件(%JAVE_HOME%是自己電腦的Java路徑)
但現在一般是打包成鏡像,部署在docker上,因此可以在dockerfile中加入下列配置來替換jar包
RUN yum install -y unzip zip RUN curl -q -L -C - -b "oraclelicense=accept-securebackup-cookie" -o /tmp/jce_policy-8.zip -O http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip \ && unzip -oj -d /opt/tuniu/jdk18/jre/lib/security /tmp/jce_policy-8.zip \*/\*.jar \ && rm /tmp/jce_policy-8.zip
2.通過反射移除限制
在stackoverflow上看到解決方案,在加密前可以調用該方法
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 }
3.自定義classloader
加密前只用自定義的classloader加載方法1中的jar包替換掉相應jar包