CipherInputStream never throws exception - java

I have a method like. It works fine but the problem is when I try to decrypt a file which is having wrong padding or even which is not encrypted at all. Usually I believe cipher.doFinal(..) usually throws some exception related to IllegalBlockSizeException,
BadPaddingException. I believe its due to masking of those exception as in here. My question is can I detect those exceptions cases?
public myDecryptMethod(byte[] sessionKey, FileInputStream encryptedFileStream) throws Exception{
....
SecretKeySpec symmKeySpec = new SecretKeySpec(sessionKey, "AES/CBC/PKCS5Padding");
Cipher symmCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
IvParameterSpec ivParameterSpec = new IvParameterSpec("0000000000000000".getBytes());
symmCipher.init(Cipher.DECRYPT_MODE, symmKeySpec, ivParameterSpec);
CipherInputStream cis = new CipherInputStream(encryptedFileStream, symmCipher);
byte[] inputByteArray = new byte[10240];
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
while (true) {
int length = cis.read(inputByteArray);
if (length < 0)
break;
outStream.write(inputByteArray, 0, length);
}
outStream.close();
byte[] data = outStream.toByteArray();
InputStream inStream = new ByteArrayInputStream(data);
cis.close();
return inStream;
}

There have been discussions about this in bouncycastle-dev and openjdk-security. Oracle thinks this is intended behavior and with JCE's ciphers which do not do the authentication check on close the consider it safe.
BC ciphers act differently as they allow to stream and (and release unauthenticated data).
Your option would be to use BCs stream org.bouncycastle.crypto.io.CipherInputStream instead. They fixed the stream (>1.50). Phillipp wrote a good blog about all that.

Related

AES Encryption in JAVA and InputStream

Sorry, JAVA beginner here. I was trying out some encryption decryption examples. My methods were supposed to be returning an InputStream and were also supposed to take in an Inputstream as a parameter.
The signature of the method looked like this,
public static InputStream encriptFile(InputStream inputFile).
I researched a bit, and wrote some code confidently, but i don't think the code is properly encrypting a sample file because when I decrypt it and convert into string, it still shows me gibberish. I really don't know what's going wrong with encrypting and decrypting the InputStreams. The Java class looks like this,
private static final String key = "aesEncryptionKey";
private static final String initVector = "encryptionIntVec";
/*
* Getting a 128 bit key and iv for encryption
*/
public static InputStream encriptFile(InputStream inputFile) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
byte[] nonEncryptedByteArray = IOUtils.toByteArray(inputFile);
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec secretkey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); //Cipher instance using AES encryption algorithm
cipher.init(Cipher.ENCRYPT_MODE, secretkey, iv);
byte[] encryptedByteArray = cipher.doFinal(nonEncryptedByteArray);
/*
* Used the cipher library to encrypt the stream to a byte array
*/
InputStream encryptedInputStream = new ByteArrayInputStream(encryptedByteArray);
/*
* Back to streams, but this time encrypted
*/
return encryptedInputStream;
}
public static InputStream decriptFile(InputStream inputFile) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
byte[] encrytToDecryptByteArray = IOUtils.toByteArray(inputFile);
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec secretkey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretkey, iv);
byte[] decryptedByteArray = cipher.doFinal(encrytToDecryptByteArray);
/*
* dencrypted the encrypted data
*/
InputStream decryptedInputStream = new ByteArrayInputStream(decryptedByteArray);
return decryptedInputStream;
}
The main method looks like this,
File file = new File("test.txt");
InputStream is = new FileInputStream(file);
InputStream eis = encriptFile(is);
StringWriter writer = new StringWriter();
IOUtils.copy(eis, writer, "UTF-8");
String theString = writer.toString();
System.out.print(theString);
The contents of the text file are "Hello, file to be encrypted. Let's see if this works.".
The output which should have printed out an encrypted output looks like this.
��T��� ���N�?]�7!2. When I go ahead and decrypt it, it still shows me gibberish. Sorry for the really long question, any help is appreciated.
You should not return input streams at all. And the way you are using the streams, you're not actually streaming. If you have to use a stream, use CipherInputStream. Personally I'd always use CipherOutputStream for encryption and CipherInputStream for decryption (you are not likely to do anything with the encrypted data, after all, other than exporting it from your application).
A cipher furthermore returns binary data. That's not the same as UTF-8, and no encoding should be necessary for files either, as they accept binary data directly. This is likely the current problem. Just use FileOutputStream / FileInputStream instead of writers or readers.
I tested your code and I think you are printing the encrypted value (so, gibberish) and not the decrypted.
If you update the main to:
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream(new File("test.txt"));
InputStream eis = encriptFile(is);
InputStream result = decriptFile(eis); // <-- Decryption here
StringWriter writer = new StringWriter();
IOUtils.copy(result, writer, "UTF-8");
String theString = writer.toString();
System.out.print(theString);
}
You should be fine.
I tested just by changing the decryptFile() method to:
public static InputStream decriptFile(InputStream inputFile) throws Exception {
byte[] encrytToDecryptByteArray = new byte[inputFile.available()];
inputFile.read(encrytToDecryptByteArray);
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8));
SecretKeySpec secretkey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES);
Cipher cipher = Cipher.getInstance(AES_CBC_PKCS_5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, secretkey, iv);
byte[] decryptedByteArray = cipher.doFinal(encrytToDecryptByteArray);
System.out.println(new String(decryptedByteArray));
return new ByteArrayInputStream(decryptedByteArray);
}
And calling it with the result from the encriptFile() and it worked properly.

File Encryption And Decryption In Java, doesn't work decryption

Hi guys I have to do this and I can encrypt file according to the des algorithm but I can not decyrpt again file ,I recieve error messaje like that :
javax.crypto.BadPaddingException Given final block not properly padded
I can not decrypt file I couldnt find why. Can u help me please
Thank you guys.
JAVA CODE :
public class Sifreleme {
public static void encrypt(){
try {
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
FileOutputStream fosKey = new FileOutputStream("..\\KEY");
SecretKeyFactory keyfac = SecretKeyFactory.getInstance("DES");
DESKeySpec keyspec = (DESKeySpec) keyfac.getKeySpec(key, DESKeySpec.class);
fosKey.write(keyspec.getKey());
fosKey.close();
Cipher crypt = Cipher.getInstance("DES");
crypt.init(Cipher.ENCRYPT_MODE, key);
FileInputStream fis = new FileInputStream("C:\\Users\\akif\\Desktop\\zilsesi.mp3");
FileOutputStream fos = new FileOutputStream("C:\\Users\\akif\\Desktop\\sifrelenenzilsesi.mp3");
byte[] arrayBytes = new byte[8];
int bytesReads;
while ((bytesReads = fis.read(arrayBytes)) != -1) {
fos.write(crypt.doFinal(arrayBytes), 0, bytesReads);
}
fis.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void decrypt(){
try {
FileInputStream fisKey = new FileInputStream("..\\KEY");
byte[] arrayKey = new byte[fisKey.available()];
fisKey.read(arrayKey);
SecretKey key = new SecretKeySpec(arrayKey, "DES");
Cipher decrypt = Cipher.getInstance("DES");
decrypt.init(Cipher.DECRYPT_MODE, key);
FileInputStream fis = new FileInputStream("C:\\Users\\akif\\Desktop\\sifrelenenzilsesi.mp3");
byte[] encText = new byte[16];
int bytesReads;
while ((bytesReads = fis.read(encText)) != -1) {
fis.read(decrypt.doFinal(encText), 0, bytesReads);
}
fis.close();
System.out.println(new String(encText));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String []args) throws IOException{
encrypt();
decrypt();
}
Your code here:
while ((bytesReads = fis.read(encText)) != -1) {
fis.read(decrypt.doFinal(encText), 0, bytesReads);
}
Is rather obviously wrong: you need to write the plaintext generated by calling decrypt.doFinal just like you do during encryption. Currently you are overwriting the generated plaintext by the next block(s) of ciphertext because you call read twice in the loop.
Furthermore, depending on your DES Cipher implementation, you forgot about the IV.
A lot of other things are wrong as well, including:
the stream handling using getAvailable();
the use of the 56 bit DES cipher;
the use of ECB mode;
the repeated calls to doFinal (which results in a very large overhead and insecure code);
not using the CipherInputStream and CipherOutputStream (etcetera);
using a string as the key;
forgetting to close your streams when an exception occurs (use the try with resources);
the printStackTracke() exception handling;
the use of static fields as variables.
Using the platform encoding within new String(encText) is only likely wrong.
Note that using the wrong key / ciphertext combination will likely also result in this error.

Increase speed of encryption AES android

I develop an android application for encrypt files on the phone. By searching, i found this topic : How to encrypt file from SD card using AES in Android?
The method works fine but it is very slow to encrypt files...
At this line : byte[] d = new byte[8]; why only 8 bytes ? can't we set an higher value ?
Also, do you know a way to encrypt files fastly ? I heard of crypto++ for native code implementation but how can I implement JNI on my application ?
Thank you,
EDIT : Encryption function
public void encrypt (String RSAPrivateKey, String Key, byte[] iv, String zipname, ZipEncryptAsyncTask task) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
{
FileInputStream fis = new FileInputStream (zipname + ".temp");
FileOutputStream fos = new FileOutputStream (zipname);
SecretKeySpec sks = new SecretKeySpec (Base64.decode(Key, Base64.DEFAULT), "AES");
IvParameterSpec ivspec = new IvParameterSpec (iv);
Cipher cipher = Cipher.getInstance ("AES/CBC/PKCS5Padding");
fos.write(String.valueOf(RSAPrivateKey.getBytes().length).getBytes());
fos.write(RSAPrivateKey.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, sks, ivspec);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
long size = 0;
byte[] d = new byte[8];
for(int b; (b = fis.read(d)) != -1; )
{
cos.write(d, 0, b);
task.doProgress((size += 8));
}
cos.flush();
cos.close();
fis.close();
new File(zipname + ".temp").delete();
}
As an alternative, you could consider changing the cypher mode you are using. CBC mode must be used serially, block by block. Counter mode (CTR) can be run in parallel with different blocks being encrypted simultaneously. Of course there are overheads to parallel processing, and you will need to rework your code, but if buffer resizing does not give you enough speed gains, then it might be the next option to try.
as #CodesInChaos said, a way to do this, is to increase the size of the buffer.
Now I do a benchmark which determines the best size for the buffer and I use the optimal value.

Java Cryptography Extension (JCE) Unlimited Strength failing randomly

I'm facing a rather strange behavior about decrypting in Java. Using the code below
public void decrypt(File file, String output_file_path) throws FileNotFoundException, IOException, GeneralSecurityException {
String hex_enc_key = "346a23652a46392b4d73257c67317e352e3372482177652c";
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(HexParser.fromHexString(hex_enc_key), "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
CipherOutputStream cos = new CipherOutputStream(new FileOutputStream(new File(output_file_path)), cipher);
FileInputStream fis = new FileInputStream(file);
doCopy(fis, cos);
}
I get random exceptions
java.security.InvalidKeyException: Illegal key size or default parameters
I googled the issue and found out about JCE unlimited strength, but I can't understand why I get those random exceptions even if I'm always using the same key (sometimes it works and sometimes not, based on the input file I need to decrypt).
For the sake of clarity I'm using
Cipher.getMaxAllowedKeyLength("AES")
to check for JCE limitations, and have no issue whatsoever encrypting with the same settings:
public void encrypt(File file, String output_file_path) throws FileNotFoundException, IOException, GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(HexParser.fromHexString(db_enc_key), "AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
CipherInputStream cis = new CipherInputStream(new FileInputStream(file), cipher);
FileOutputStream os = new FileOutputStream(new File(output_file_path));
doCopy(cis, os);
cis.close();
os.close();
}
Can anyone point me in the right direction?
Thanks a lot, nicola

Encryption of image files on Android -- Cipher(Output|Input)Stream problems

I'm trying to encrypt image files on Android with password based encryption. To save the encrypted image I just do this:
FileOutputStream fos = new FileOutputStream(thumbnailFile);
CipherOutputStream cos = new CipherOutputStream(fos, encryptCipher);
Bitmap thumbnail = Bitmap.createScaledBitmap(bm2, 140, 140, true);
thumbnail.compress(Bitmap.CompressFormat.JPEG, 80, cos);
and to read it, this:
FileInputStream fis = new FileInputStream(f);
CipherInputStream cis = new CipherInputStream(fis, decryptCipher);
Bitmap b = BitmapFactory.decodeStream(cis);
but the Bitmap ends up as null. The code works when I bypass the encryption; that is when I use the File(Input|Output)Streams rather than the Cipher(Input|Output)streams.
My Ciphers are created as follows:
public void initCiphers(char password[]) {
PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;
byte[] salt = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
int count = 20;
pbeParamSpec = new PBEParameterSpec(salt, count);
pbeKeySpec = new PBEKeySpec(password);
try {
keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
encryptCipher = Cipher.getInstance("PBEWithMD5AndDES");
decryptCipher = Cipher.getInstance("PBEWithMD5AndDES");
encryptCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
decryptCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
} catch (Exception e) {
Log.v("tag", e.toString());
}
I don't get any exceptions.
There is obviously some problem with using Cipher(Output|Input)Streams with the android functions for encoding and/or decoding images, but since those functions are opaque and there are no exceptions, its hard to know what it is. I suspect it has to do with padding or flushing. Any assistance would be gratefully appreciated.
When writing to a CipherOutputStream, make sure you close() the stream after writing the data (and not closing the underlying stream before it). Closing makes sure the right padding is added. A flush() alone is not enough here.
Also, I would advise to not use DES for new protocols - preferred nowadays is AES.
You could subclass CipherOutputStream or even just OutputStream, and just override the flush() method to do nothing.

Categories

Resources