Reputation: 21
So part 2 of my assignment is to find the missing byte of an encryption key. As a background I am not too familiar with this so I have no clue on where to start. I have looked around and cannot seem to find a starting place. The information I have is that the encryption key is in AES/ECB key: {'__' '7e' '15' '16' '28' 'ae' 'd2' 'a6' 'ab' 'f7' '15' '88' '09' 'cf' '4f' '3c'};
What I did try is looping through ACII values (0-255) and then getting the byte of the values and appending them to the byte array of the key. After I would attempt to decrypt the file as normal and output the new file in hopes to see a picture. However I am not seeing anything. Can you please point me to where I am going wrong?
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();
}
Upvotes: 0
Views: 369
Reputation: 61952
You have many problems with your code.
This
byte[] convertHexString = DatatypeConverter.parseHexBinary(key);
String newKey = new String(convertHexString);
byte[] keyByte = newKey.getBytes();
should be reduced to
byte[] keyByte = DatatypeConverter.parseHexBinary(key);
This
String[] asciiArray = new String[256];
...
asciiArray[i].getBytes();
is actually a NullPointerException
, because asciiArray[i]
was never initialized. When you create an array of non-primitive types, the array is always initialized with all null
values.
FileInputStream
produces the file contents only onceYou have the code
FileInputStream file = new FileInputStream(path);
outside of the loop, but you're reading the file
inside of the loop until it is fully read. The problem is that this works only for the first iteration. In the next iteration (i == 1
), there is no data to be read, so nothing to decrypt.
You should either read the file into a byte[]
before the for-loop or initialize the stream inside of the for-loop in order to be able to read the file every time.
CipherInputStream
and CipherOutputStream
hide some exceptions. In particular, ECB mode is a non-streaming block cipher mode, so it must have some kind of padding. Usually, this padding is from PKCS#5 (= PKCS#7). You should use the Cipher
and it's update
method directly. When you're done writing data, then you can call the doFinal
method and if the key was wrong, you will get an exception that you can catch with a probability of 255/256th (approx. 1).
byte[] keyByte = DatatypeConverter.parseHexBinary("007e151628aed2a6abf7158809cf4f3c");
for(int i = 0; i < 256; i++){
keyByte[0] = (byte)i;
...
}
That's it. You don't need more to change the first byte of the key.
Some example code:
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();
}
}
If the file is small, you don't have to read it again and again in every iteration, you can read it once before the for-loop.
Upvotes: 2
Reputation: 7406
That's not the way you want to iterate through the possible 256 byte
values! Consider, for example, what happens when i = 137
: You say Character.toString((char)137)
- the output of this is the Unicode character U+0089
. Calling s.getBytes()
on this gives you the byte array [-62, -118]
. Already we know we are in trouble since this should not be two bytes! (This is the UTF-8 interpretation of the character U+0089
, FYI.)
Instead, why not just iterate through the possible byte values? There's no reason the for-loop has to iterate over int
values; you can iterate directly over byte values. (NB: bytes in Java are signed, for no good reason, so the for-loop looks a little odd, but this is the right way):
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
}
Upvotes: 1