Size file is not equal after encrypt and decrypt - java

My file is 1 MB . And after i encrypt and decrypt it with AES-128, It is only 960 kB. Is it problem with my code?
KeyGenerator keyGenerator = new KeyGenerator();
byte[] key = keyGenerator.generateKey(password, 16);
System.out.println("Key :::::::" + Arrays.toString(key));
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
`
and next :
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(cipherModel, keySpec, ivSpec);
System.out.println("cipher init done");
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] inputBytes = new byte[64];
int count;
while ((count = inputStream.read(inputBytes)) > 0) {
byte[] output = cipher.update(inputBytes, 0, count);
if (output != null)
outputStream.write(output);
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null)
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();`

Related

File Encryption/Decryption Java

I'm trying to encrypt a file using AES and Java Crypto Library. But this is the error Which happens while I'm decrypting the file: "Error while decrypting: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption."
This is my code so far:
public static void encrypt(File input, String key, File output) {
try
{
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(key.toCharArray(), key.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
FileInputStream inputStream = new FileInputStream(input);
byte[] inputBytes = new byte[(int) input.length()];
int count;
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(output);
while ((count = inputStream.read(inputBytes, 0, inputBytes.length)) > 0)
{
outputStream.write(inputBytes, 0, count);
}
inputStream.close();
outputStream.close();
}
catch (Exception e)
{
System.out.println("Error while encrypting: " + e.toString());
}
}
public static void decrypt(File input, String key, File output)
{
try
{
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(key.toCharArray(), key.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
FileInputStream inputStream = new FileInputStream(input);
byte[] inputBytes = new byte[(int) input.length()];
int count;
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(output);
while ((count = inputStream.read(inputBytes, 0, inputBytes.length)) > 0)
{
outputStream.write(inputBytes, 0, count);
}
inputStream.close();
outputStream.close();
}
catch (Exception e)
{
System.out.println("Error while decrypting: " + e.toString());
}
}
What could be the problem?
Thanks in advance!

Java String not equal String?

I want to decrypt a String. Here my Decryption and Encryption methods.
public String encrypt(String message) throws Exception {
byte[] messageInBytes = message.getBytes();
encryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
encryptionCipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = encryptionCipher.doFinal(messageInBytes);
return encode(encryptedBytes);
}
public String decrypt(String encryptedMessage) throws Exception {
byte[] messageInBytes = decode(encryptedMessage);
Cipher decryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(T_LEN , encryptionCipher.getIV());
decryptionCipher.init(Cipher.DECRYPT_MODE, key, spec);
byte[] decryptedBytes = decryptionCipher.doFinal(messageInBytes);
return new String(decryptedBytes);
}
Here the main:
public static void main(String[] args) {
try {
AES aes = new AES();
aes.convertStringKeyToSecretKey();
String encryptedMessage = aes.encrypt("Peter");
String decryptedMessage = aes.decrypt(encryptedMessage);
System.err.println("Encrypted Message : " + encryptedMessage);
System.err.println("Decrypted Message : " + decryptedMessage);
} catch (Exception ignored) {
}
}
When I change encryptedMessage to a own String like:
String decryptedMessage = aes.decrypt("xDFzl9HsenqKspdEbL/m9I5X6dqn");
It does nothing
I hope you can help me.
Best Regards
Christian
public static String encryptAES(String toEncrypt, final String key1, final String key2) throws Exception {
try {
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec keySpec = new PBEKeySpec(key1.toCharArray(), key2.getBytes(), 65536, 256);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return Base64.getEncoder().encodeToString(cipher.doFinal(toEncrypt.getBytes(StandardCharsets.UTF_8)));
} catch (Exception ex) {
throw new Exception(ex);
}
}
public static String decryptAES(String toDecrypt, final String key1, final String key2) throws Exception {
try {
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec keySpec = new PBEKeySpec(key1.toCharArray(), key2.getBytes(), 65536, 256);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
return new String(cipher.doFinal(Base64.getDecoder().decode(toDecrypt)));
} catch (Exception ex) {
throw new Exception(ex);
}
}
Here you can still expand its secureness by creating your own IV Spec key, which should contain only 16 character.
Actually, this is how AES encryption worked for me, You can also check this repo in GitHub for additional encryption methods.

Java encryption won't decrypt on Android

Okay, so when I encrypt anything, lets say in this case a file, with my computer. It works fine encrypting and decrypting said file. However if encrypt the file with my computer then send it too my android and run the same decryption code I wrote it wont decrypt the file properly. It doesn't show any errors, however the file is clearly not decrypted properly.
So I've learned that Bouncy Castle is quite different than JVM/JDK standard encryption library, so I'm not 100% sure if that's the problem. However it would make sense. The issue is that if it is I don't know how to use the JVM/JDK library for encryption on my android. I don't want too use the Bouncy Castle library on my computer.
public static void encrypt(File source, File dest, String password){
try{
FileInputStream inFile = new FileInputStream(source.getPath());
FileOutputStream outFile = new FileOutputStream(dest.getPath());
byte[] salt = new byte[8], iv = new byte[16];
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] input = new byte[64];
int bytesRead;
while((bytesRead = inFile.read(input)) != -1){
byte[] output = cipher.update(input, 0, bytesRead);
if(output != null){
outFile.write(output);
}
}
byte[] output = cipher.doFinal();
if(output != null){
outFile.write(output);
}
inFile.close();
outFile.flush();
outFile.close();
}catch(Exception e){
e.printStackTrace();
}
}
public static void decrypt(File source, File dest, String password){
try{
byte[] salt = new byte[8], iv = new byte[16];
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
FileInputStream fis = new FileInputStream(source.getPath());
FileOutputStream fos = new FileOutputStream(dest.getPath());
byte[] in = new byte[64];
int read;
while((read = fis.read(in)) != -1){
byte[] output = cipher.update(in, 0, read);
if(output != null){
fos.write(output);
}
}
byte[] output = cipher.doFinal();
if(output != null){
fos.write(output);
}
fis.close();
fos.flush();
fos.close();
}catch(Exception e){
e.printStackTrace();
}
}
The outcome would be too be able too encrypt any file with my computer using the standard JVM/JDK encryption library and being able too decrypt the same file with my android.
However if there is a different library other than Bouncy Castle that would work with android I'm open for ideas.
I've faced similar issue. First check if your encryption and decryption is setup properly.
If those are okay, then you should convert the encrypted text to Base64 or similar encoding.
Then decode the Base64 encoding first on the mobile and then decrypt the file.
The issue occurs because, some characters are not suitable for saving or transfering between mediums. They also gets affected by the underlying OS. Even if a bit is changed, your whole decrypted text will be changed, that might be the case here
ANDROID CODE
public static void decrypt(File source, File dest, String password){
try{
Base64InputStream fis = new Base64InputStream(new DataInputStream(new FileInputStream(source.getPath())), Base64.DEFAULT);
FileOutputStream fos = new FileOutputStream(dest.getPath());
byte[] salt = new byte[8], iv = new byte[16];
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] in = new byte[64];
int read;
while((read = fis.read(in)) != -1){
byte[] output = cipher.update(in, 0, read);
if(output != null){
fos.write(output);
}
}
byte[] output = cipher.doFinal();
if(output != null){
fos.write(output);
}
fis.close();
fos.flush();
fos.close();
}catch(Exception e){
e.printStackTrace();
}
}
Regular JVM
public static void encrypt(File source, File dest, String password){
try{
FileInputStream inFile = new FileInputStream(source.getPath());
OutputStream outFile = Base64.getEncoder().wrap(new FileOutputStream(dest.getPath()));
byte[] salt = new byte[8], iv = new byte[16];
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] input = new byte[64];
int bytesRead;
while((bytesRead = inFile.read(input)) != -1){
byte[] output = cipher.update(input, 0, bytesRead);
if(output != null){
outFile.write(output);
}
}
byte[] output = cipher.doFinal();
if(output != null){
outFile.write(output);
}
inFile.close();
outFile.flush();
outFile.close();
}catch(Exception e){
e.printStackTrace();
}
}
public static void decrypt(File source, File dest, String password){
try{
InputStream fis = Base64.getDecoder().wrap(new FileInputStream(source.getPath()));
//FileInputStream fis = new FileInputStream(source.getPath());
FileOutputStream fos = new FileOutputStream(dest.getPath());
byte[] salt = new byte[8], iv = new byte[16];
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] in = new byte[64];
int read;
while((read = fis.read(in)) != -1){
byte[] output = cipher.update(in, 0, read);
if(output != null){
fos.write(output);
}
}
byte[] output = cipher.doFinal();
if(output != null){
fos.write(output);
}
fis.close();
fos.flush();
fos.close();
}catch(Exception e){
e.printStackTrace();
}
}

Received byte array has different values than sent, AES encryption + IV

I'm trying to encrypt communication using AES, in java.
The key is hardcoded, and the IV is generated randomly through a SecureRandom and sent as the first 16 bytes of the encrypted message. However, when I try to read the first 16 bytes of the received message, I don't get the same byte array that I generated.
Here's the problematic code:
static byte[] bytes = new byte[16];
public static byte[] encrypt(String key, String message) {
try {
SecureRandom random = new SecureRandom();
random.nextBytes(bytes);
System.out.println("Outputting generated IV:");
for(int i=0; i < bytes.length; i++){
System.out.println(bytes[i]);
}
IvParameterSpec iv = new IvParameterSpec(bytes);
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 = Base64.encodeBase64(cipher.doFinal(message.getBytes()));
System.out.println("encrypted string: "
+ Base64.encodeBase64String(encrypted));
byte[] sendMe = new byte[bytes.length + encrypted.length];
System.arraycopy(bytes, 0, sendMe, 0, bytes.length);
System.arraycopy(encrypted, 0, sendMe, 0, encrypted.length);
return sendMe;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String key, byte[] received) {
try {
byte[] initVector = Arrays.copyOfRange(received, 0, 16);
byte[] encrypted = Arrays.copyOfRange(received, 16, received.length+1);
System.out.println("Outputting received IV:");
for(int i = 0; i < initVector.length; i++){
System.out.println(initVector[i]);
}
IvParameterSpec iv = new IvParameterSpec(initVector);
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;
}
Running this once, for example's sake, with the text "Hello world!" yielded the following output:
Outputting generated IV:
-79
-3
102
-103
-13
67
-63
-18
23
-114
74
26
18
-97
77
115
Outputting received IV:
36
-118
-87
-72
-119
43
101
55
50
-62
125
-98
65
35
48
-87
Which are obviously not the same.
Any help would be appreciated.
You are overwriting your IV with the encrypted data:
System.arraycopy(bytes, 0, sendMe, 0, bytes.length);
System.arraycopy(encrypted, 0, sendMe, 0, encrypted.length); // Overwrites the iv
You probably want:
System.arraycopy(bytes, 0, sendMe, 0, bytes.length);
System.arraycopy(encrypted, 0, sendMe, 16, encrypted.length);

Decryption fails on chaging the IV in AES algorithm

I have some encoded value received by my webservice. Now I have to decode this encoded string and get the bytes of it.
Now I am using this byte array as my IV value for decrypting a values using AES algorithm. But it is not giving me the proper output rather throws some junk values.
Here is my code,
byte[] decoded = Base64.decodeBase64(((String) "MTIzNDU2Nzg5MTIzNDU2Nw==").getBytes());
System.out.println(new String(decoded, "UTF-8") + "\n");
MTIzNDU2Nzg5MTIzNDU2Nw== is the encoded string received from the request xml.
Now decoded will be IV for the next number to be decrypted,
String c = decrypt1("JHIlf4iXM53tgsKHQEv1dlsUTeLr5GP3LfSNGlWENkg=", decoded);
System.out.println(c);
JHIlf4iXM53tgsKHQEv1dlsUTeLr5GP3LfSNGlWENkg= is the digit to be decrypted.
public static String decrypt1(Object data, byte[] ivBytes) throws InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException {
byte[] keyBytes = "keyPhrase".getBytes();
Cipher cipher = null;
if (ivBytes.length<16) {
System.out.println("error" + ivBytes.length);
//ivBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 98, 99, 100, 101, 102, 103};
}
byte[] byteArr = null;
try {
SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(
ivBytes));
if (data instanceof String) {
byteArr = Base64.decodeBase64(((String) data).getBytes("UTF-8"));
}
byteArr = (cipher.doFinal(byteArr));
} catch (Exception e) {
e.printStackTrace();
}
//return byteArr;
return new String(byteArr);
}
Note:
Instead if I use this IV,
byte[] ivBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0}; it works as expected.
You need to use the same initialization vector for encryption and decryption; you can transmit the IV in plaintext (i.e. it isn't secret)
You should also use a different IV for each ciphertext, generated with e.g. a counter or with SecureRandom

Categories

Resources