【发布时间】:2018-10-30 03:50:46
【问题描述】:
你好,亲爱的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 Cryptography Extension (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 "";
}
【问题讨论】:
标签: java encryption