因此,我的任务的第2部分是找到加密密钥的缺失字节。作为背景我不太熟悉这个,所以我不知道从哪里开始。我环顾四周,似乎找不到起点。我的信息是加密密钥是AES / ECB密钥:{'__''7e''15''16''28''ae''d2''a6''ab''f7''15' '88''09''cf''4f''3c'};
我尝试的是循环遍历ACII值(0-255),然后获取值的字节并将它们附加到密钥的字节数组。之后我会尝试正常解密文件并输出新文件以期查看图片。但是我没有看到任何东西。你能指点我出错的地方吗?
byte[] convertHexString = DatatypeConverter.parseHexBinary(key);
String newKey = new String(convertHexString);
byte[] keyByte = newKey.getBytes();
String[] asciiArray = new String[256];
FileInputStream file = new FileInputStream(path);
Cipher aesCipher = Cipher.getInstance(transformation);
for(int i = 0;i<256; i++){
arrayInts[i] = Character.toString((char)i);
byte[] b = asciiArray [i].getBytes();
byte[] result = new byte[b.length + keyByte.length];
System.arraycopy(b, 0, result, 0, b.length);
System.arraycopy(keyByte, 0, result, b.length, keyByte.length);
FileOutputStream out = new FileOutputStream("AESencrypt_view" + String.valueOf(i)+".jpg");
SecretKeySpec key1 = new SecretKeySpec(result,"AES");
aesCipher.init(Cipher.DECRYPT_MODE, key1);
CipherOutputStream outSt = new CipherOutputStream(out,aesCipher);
byte[] buf = new byte[1024];
int read;
while((read=file.read(buf))!=-1){
outSt.write(buf, 0, read);
}
//file.close();
out.flush();
outSt.flush();
}
答案 0 :(得分:2)
您的代码存在许多问题。
此
byte[] convertHexString = DatatypeConverter.parseHexBinary(key);
String newKey = new String(convertHexString);
byte[] keyByte = newKey.getBytes();
应该简化为
byte[] keyByte = DatatypeConverter.parseHexBinary(key);
此
String[] asciiArray = new String[256];
...
asciiArray[i].getBytes();
实际上是NullPointerException
,因为asciiArray[i]
从未初始化。创建非基本类型的数组时,始终使用所有null
值初始化数组。
FileInputStream
生成文件内容你有代码
FileInputStream file = new FileInputStream(path);
在循环之外,但是您正在读取循环内部的file
,直到它被完全读取。问题是这只适用于第一次迭代。在下一次迭代(i == 1
)中,没有要读取的数据,因此无需解密。
您应该在for循环之前将文件读入byte[]
,或者在for循环内初始化流,以便每次都能读取文件。
CipherInputStream
和CipherOutputStream
隐藏了一些例外情况。特别是,ECB模式是非流分组密码模式,因此它必须具有某种填充。通常,此填充来自PKCS#5(= PKCS#7)。您应该直接使用Cipher
及其update
方法。当您完成写入数据时,您可以调用doFinal
方法,如果密钥错误,您将获得一个异常,您可以捕获255 / 256th(大约1)的概率。
byte[] keyByte = DatatypeConverter.parseHexBinary("007e151628aed2a6abf7158809cf4f3c");
for(int i = 0; i < 256; i++){
keyByte[0] = (byte)i;
...
}
那就是它。您不需要更多来更改密钥的第一个字节。
一些示例代码:
byte[] keyByte = DatatypeConverter.parseHexBinary("007e151628aed2a6abf7158809cf4f3c");
Cipher aesCipher = Cipher.getInstance(transformation);
byte[] buf = new byte[1024];
for(int i = 0; i < 256; i++){
keyByte[0] = (byte)i;
FileInputStream inFileStream = new FileInputStream(path);
File outFile = new File("AESencrypt_view" + String.valueOf(i)+".jpg");
FileOutputStream outFileStream = new FileOutputStream(outFile);
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
aesCipher.init(Cipher.DECRYPT_MODE, keySpec);
int read;
while((read = inFileStream.read(buf)) != -1){
outFileStream.write(aesCipher.update(buf, 0, read));
}
inFileStream.close();
try {
outFileStream.write(aesCipher.doFinal());
outFileStream.close();
}
catch(BadPaddingException e) {
// obviously a wrong key or broken ciphertext
outFileStream.close();
outFile.delete();
}
}
如果文件很小,你不必在每次迭代中反复读取它,你可以在for循环之前读取它一次。
答案 1 :(得分:1)
这不是您希望迭代可能的256个byte
值的方式!例如,考虑i = 137
时发生的情况:您说Character.toString((char)137)
- 此输出是Unicode字符U+0089
。在此调用s.getBytes()
会为您提供字节数组[-62, -118]
。我们已经知道我们遇到了麻烦,因为这不应该是两个字节! (这是字符U+0089
,仅供参考的UTF-8解释。)
相反,为什么不迭代可能的字节值呢? for-loop没有理由迭代int
个值;您可以直接迭代字节值。 (注意:Java中的字节是有符号的,没有充分的理由,所以for循环看起来有点奇怪,但这是正确的方法):
for (byte b = -128; b<128; b++) {
byte[] result = new byte[keyByte.length +1];
result[0] = b;
System.arraycopy(keyByte, 0, result, 1, keyByte.length);
// yadda yadda yadda
}