您好,stackoverflow的人们,
我目前正在我的应用程序中开发/实施安全措施,并且在某些数据的加密和解密方面遇到了一些问题。
事实上,昨天我能够加密一条消息,然后使用该类的相同实例解密该加密的消息-但反之亦然。这就是我今天要发布的(关于此问题)-
从我工作过的linux系统中推送最新更改并尝试继续在Windows pc上工作后,抛出了以下错误:
java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1026)
at javax.crypto.Cipher.implInit(Cipher.java:801)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1249)
at javax.crypto.Cipher.init(Cipher.java:1186)
at com.x.backend.security.Decrypter.encrypt(Decrypter.java:43)
at crypto.CryptoTest.main(CryptoTest.java:11)
java.lang.NullPointerException
at javax.crypto.spec.IvParameterSpec.<init>(IvParameterSpec.java:53)
at com.x.backend.security.Decrypter.decrypt(Decrypter.java:54)
at crypto.CryptoTest.main(CryptoTest.java:12)
所以我尝试找到一种解决方案,但没有找到任何解决方案,所以这是我到目前为止尝试过的:
升级到JDK 9/10/11对我来说不是一个选择,我尝试了一下,我惨败了,如果我想升级,那就太适应了(这不值得)到目前为止的努力)
我已经阅读了有关Java密码学扩展(JCE)的内容,但这不适用于我,因为我正在运行JDK版本 1.8.66 (从1.8.55开始)不再需要在Java目录中安装任何类型的文件)
无效的缓存(IntelliJ)+重新启动我的PC
将项目状态重置为初始提交(git硬重置)
我的课:
public class Decrypter {
private static Decrypter instance;
private Cipher cipher;
private byte[] IV;
private SecretKeySpec secretKeySpec;
private Decrypter() {
initialize();
}
private void initialize() {
try {
final byte[] salt = "@1jq3#-o1_uHvaL:".getBytes();
final String key = "hehexd";
final int iterationCount = 12;
final int keyStrength = 256;
this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
this.secretKeySpec = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(new PBEKeySpec(key.toCharArray(), salt, iterationCount, keyStrength)).getEncoded(), "AES");
} catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
}
public final String encrypt(String data) {
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
IV = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public final String decrypt(String base64EncryptedData) {
try {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(IV));
byte[] decryptedData = Base64.getDecoder().decode(base64EncryptedData);
byte[] utf8 = cipher.doFinal(decryptedData);
return new String(utf8, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static Decrypter getInstance() {
return instance == null ? instance = new Decrypter() : instance;
}
}
我的考试班:
public class CryptoTest {
public static void main(String[] args) {
String encrypted = Decrypter.getInstance().encrypt("lol");
String decrypted = Decrypter.getInstance().decrypt(encrypted);
System.out.println("Verification: PLAINTEXT -> ENCRYPT: " + encrypted);
System.out.println("Verification: ENCRYPT -> DECRYPT: " + decrypted);
}
}
请不要介意任何常规的错误/错误做法,在密码学方面,我是新来的人(目前正在读懂我的方法)
任何帮助或投入将不胜感激!
编辑:
感谢您的即时答复!
很不幸,我遇到了另一个错误。 完整输出:
Verification: PLAINTEXT -> ENCRYPT:
java.security.InvalidKeyException: Illegal key size
Verification: PLAINTEXT -> DECRYPT:
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.x.backend.security.Decrypter.encrypt(Decrypter.java:48)
at crypto.CryptoTest.main(CryptoTest.java:11)
java.security.InvalidKeyException: No installed provider supports this key: javax.crypto.spec.SecretKeySpec
at javax.crypto.Cipher.chooseProvider(Cipher.java:893)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.x.backend.security.Decrypter.decrypt(Decrypter.java:58)
at crypto.CryptoTest.main(CryptoTest.java:12)
更改代码:
public final String encrypt(String data) {
try {
IV = new IvParameterSpec("testtesttesttest".getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, IV);
return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
答案 0 :(得分:2)
我不知道您从何处获得有关JDK 1.8.66具有无限强度JCE的信息。美国境外情况并非如此。
您仍然需要从Oracle下载并安装无限强度的JCE JAR。
如果您确定 拥有无限的JCE实力,请尝试添加到jre/lib/security/java.security
:
crypto.policy=unlimited
默认情况下,仅从Java SE 8u161开始才启用无限强度。因此,这里不需要此设置。
另一方面,可以改善您的错误处理。最好将e.printStackTrace()
替换为throw new RuntimeException(e)
,以将所有这些初始化错误都视为致命错误(在那个阶段,它们 会破坏交易)。
答案 1 :(得分:0)
结果是,对最新JDK的更新修复了所有已发生的问题。现在,我可以轻松地独立解密和加密内容了!
感谢所有参与寻找解决方案的人!