Bea*_*956 2 java encryption nullpointerexception
所以我想在一个方法来解密消息,但它不工作,因为我需要做cipher.init(Cipher.ENCRYPT_MODE, secret)之前,我尝试添加new IvParameterSpec(iv)到cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));.否则,它只返回一个NullPointerException我想知道是否可以在方法中执行此操作而不是一直写入它.我真的不能想到一个解决方案,这就是为什么我在这里.加密工作正常但不解密.
项目运行: JRE 7
加密代码:
public static String encrypt(String str) {
try {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(str.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret); //<--- Need to do this before writing IvPerameterSpec,
// But I think that it's not possible if I have it in another method.
byte[] encryptedText = cipher.doFinal(str.getBytes("UTF-8"));
return new String(encryptedText);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
解密代码:
public static String decrypt(String str) {
try {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(str.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
// ^^^ Returns NullPointerException
byte[] ciphertext = cipher.doFinal(str.getBytes("UTF-8"));
String decryptedText = new String(cipher.doFinal(ciphertext), "UTF-8");
return new String(decryptedText);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
例外:
java.lang.NullPointerException
at me.Sansanvi.Encryption.api.ComputerAPI.decrypt(ComputerAPI.java:149)
at me.Sansanvi.Encryption.EncryptionMain.initializeFiles(EncryptionMain.java:46)
at me.Sansanvi.Encryption.EncryptionMain.<init>(EncryptionMain.java:36)
at me.Sansanvi.Encryption.EncryptionMain$1.run(EncryptionMain.java:23)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Run Code Online (Sandbox Code Playgroud)
我将方法更改为以下内容并且它们有效:
private static final String ALGORITHM = "AES";
public static byte[] encrypt(byte[] str) {
try {
SecretKeySpec secretKey = new SecretKeySpec("MZygpewJsCpRrfOr".getBytes(StandardCharsets.UTF_8), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(str);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] decrypt(byte[] str) {
try {
SecretKeySpec secretKey = new SecretKeySpec("MZygpewJsCpRrfOr".getBytes(StandardCharsets.UTF_8), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(str);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
我不再得到任何错误/异常,但是当我关闭我的应用程序时,我在控制台中得到了这个:
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
[0x7FFC837C7430] ANOMALY: use of REX.w is meaningless (default operand size is 64)
Run Code Online (Sandbox Code Playgroud)
你至少有四个问题而且你只发现其中一个问题.
期间产生IV 烯 cryption和使用.完全相同的IV需要期间使用德 cryption.IV不应该是秘密的.您可以简单地将其与密文一起发送/存储.通常,IV存储在密文的前面并在解密之前切掉.
对于CBC模式,它只需要是不可预测的(读取:随机).对于CTR模式,它需要是唯一的(当使用相同的密钥时).
随机盐需要以与IV完全相同的方式处理:它不是秘密的,可以写在密文之前.
String不是二进制数据的容器.当你使用时new String(encryptedText),你可能会丢失一些不可打印的字节,这会破坏你的密文并使明文无法恢复.您需要使用Base64或Hex编码之类的东西来将二进制数据表示为可打印文本.
如果加密某些东西,则需要两件事:明文和密码(用于密钥派生).解密过程中还需要两件事:密文和密码(密钥).您在加密期间使用相同的字符串值.然后,密文会被破坏,使得在解密期间需要原始字符串值.这将首先打败加密它的目的.您的加密方法基本上是一个哈希函数.
感谢wittyameta指出这一点.
因此,生成的代码看起来类似于:
public static String encrypt(String str, String password) {
try {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedText = cipher.doFinal(str.getBytes("UTF-8"));
// concatenate salt + iv + ciphertext
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(salt);
outputStream.write(iv);
outputStream.write(encryptedText);
// properly encode the complete ciphertext
return DatatypeConverter.printBase64Binary(outputStream.toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt(String str, String password) {
try {
byte[] ciphertext = DatatypeConverter.parseBase64Binary(str);
if (ciphertext.length < 48) {
return null;
}
byte[] salt = Arrays.copyOfRange(ciphertext, 0, 16);
byte[] iv = Arrays.copyOfRange(ciphertext, 16, 32);
byte[] ct = Arrays.copyOfRange(ciphertext, 32, ciphertext.length);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] plaintext = cipher.doFinal(ct);
return new String(plaintext, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
我已经将它用于兼容Java 7的Base64编码/解码.
| 归档时间: |
|
| 查看次数: |
6021 次 |
| 最近记录: |