Java AES/CBC 解密后的初始字节不正确 [英] Initial bytes incorrect after Java AES/CBC decryption
问题描述
下面的例子有什么问题?
问题是解密后的字符串的第一部分是废话.不过,其他的都还好,我明白了……
<块引用>结果:`£eB6O geS 我是你吗?祝你今天过得愉快.
@Test公共无效测试加密(){尝试 {String s = "你好.你好吗?祝你有美好的一天.";//生成密钥KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128);SecretKey aesKey = kgen.generateKey();//加密密码Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);//加密ByteArrayOutputStream outputStream = new ByteArrayOutputStream();CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);cipherOutputStream.write(s.getBytes());cipherOutputStream.flush();cipherOutputStream.close();byte[] encryptedBytes = outputStream.toByteArray();//解密密码密码解密密码 = Cipher.getInstance("AES/CBC/PKCS5Padding");IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());解密密码.init(密码.DECRYPT_MODE, aesKey, ivParameterSpec);//解密outputStream = new ByteArrayOutputStream();ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);CipherInputStream cipherInputStream = new CipherInputStream(inStream,decryptCipher);字节[] buf = 新字节[1024];int 字节读取;而 ((bytesRead = cipherInputStream.read(buf)) >= 0) {outputStream.write(buf, 0, bytesRead);}System.out.println("结果:" + new String(outputStream.toByteArray()));}捕获(异常前){ex.printStackTrace();}}
由于缺少一些信息,例如忘记转换为 Base64、初始化向量、字符集等,包括我自己在内的很多人在完成这项工作时面临很多问题. 所以我想制作一个功能齐全的代码.
希望对大家有用:要编译,您需要额外的 Apache Commons Codec jar,可在此处获得:http://commons.apache.org/proper/commons-codec/download_codec.cgi
import javax.crypto.Cipher;导入 javax.crypto.spec.IvParameterSpec;导入 javax.crypto.spec.SecretKeySpec;导入 org.apache.commons.codec.binary.Base64;公共类加密器{公共静态字符串加密(字符串密钥,字符串初始化向量,字符串值){尝试 {IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);字节 [] 加密 = cipher.doFinal(value.getBytes());System.out.println("加密字符串:"+ Base64.encodeBase64String(加密));返回 Base64.encodeBase64String(加密);} 捕捉(异常前){ex.printStackTrace();}返回空;}公共静态字符串解密(字符串密钥,字符串初始化向量,字符串加密){尝试 {IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));返回新字符串(原始);} 捕捉(异常前){ex.printStackTrace();}返回空;}公共静态无效主(字符串 [] args){String key = "Bar12345Bar12345";//128 位密钥String initVector = "RandomInitVector";//16 字节 IVSystem.out.println(decrypt(key, initVector,encrypt(key, initVector, "Hello World")));}}
What's wrong with the following example?
The problem is that the first part of the decrypted string is nonsense. However, the rest is fine, I get...
Result: `£eB6O�geS��i are you? Have a nice day.
@Test
public void testEncrypt() {
try {
String s = "Hello there. How are you? Have a nice day.";
// Generate key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey aesKey = kgen.generateKey();
// Encrypt cipher
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
// Encrypt
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
cipherOutputStream.write(s.getBytes());
cipherOutputStream.flush();
cipherOutputStream.close();
byte[] encryptedBytes = outputStream.toByteArray();
// Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt
outputStream = new ByteArrayOutputStream();
ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
outputStream.write(buf, 0, bytesRead);
}
System.out.println("Result: " + new String(outputStream.toByteArray()));
}
catch (Exception ex) {
ex.printStackTrace();
}
}
Lot of people including myself face lot of issues in making this work due to missing some information like, forgetting to convert to Base64, initialization vectors, character set, etc. So I thought of making a fully functional code.
Hope this will be useful to you all: To compile you need additional Apache Commons Codec jar, which is available here: http://commons.apache.org/proper/commons-codec/download_codec.cgi
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class Encryptor {
public static String encrypt(String key, String initVector, String value) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string: "
+ Base64.encodeBase64String(encrypted));
return Base64.encodeBase64String(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String key, String initVector, String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String key = "Bar12345Bar12345"; // 128 bit key
String initVector = "RandomInitVector"; // 16 bytes IV
System.out.println(decrypt(key, initVector,
encrypt(key, initVector, "Hello World")));
}
}
这篇关于Java AES/CBC 解密后的初始字节不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!