I would like to encrypt and decrypt files. While decrypting I wish to skip first few bytes of the file and decrypt only the rest.
Here contains three files
input_file.txt - input text file for encryption
output_file.txt - encrypted input_file.txt file
decrypted_file.txt - decrypted output_file.txt file
Sample code:
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class FileReadWrite {
public static byte[] getAESKey() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
return bytes;
}
/**
* Method used to generate a random new iv
*
* #return Randomly generated iv
*/
public static byte[] getAESIV() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes);
return bytes;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
FileInputStream fin = new FileInputStream("/Users/emp/Research/Streams/input_file.txt");
FileOutputStream fout = new FileOutputStream("/Users/emp/Research/Streams/output_file.txt");
SecretKeySpec keySpec = null;
IvParameterSpec ivSpec = null;
Cipher ecipher = null;
Cipher dcipher = null;
byte[] keyBytes = getAESKey();
byte[] ivBytes = getAESIV();
// Creating keyspec and ivspec for generating cipher
keySpec = new SecretKeySpec(keyBytes,"AES");
ivSpec = new IvParameterSpec(ivBytes);
try {
ecipher = Cipher.getInstance("AES/CTR/NoPadding");
ecipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
CipherOutputStream cout = new CipherOutputStream(fout, ecipher);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
while((count = fin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
cout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
fout.close();
cout.close();
}
fin = new FileInputStream("/Users/emp/Research/Streams/output_file.txt");
fout = new FileOutputStream("/Users/emp/Research/Streams/decrypted_file.txt");
try {
dcipher = Cipher.getInstance("AES/CTR/NoPadding");
dcipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
//fin.skip(1024);
CipherInputStream cin = new CipherInputStream(fin, dcipher);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
**//cin.read(bytearray, 0, 30);**
while((count = cin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
fout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
cin.close();
fout.close();
}
System.out.println("File read write completed successfully !!! ");
}
}
Tried:
Cipher input stream skip - cin.skip(no_of_bytes) - this doesn't work - this decrypts the entire file
File input stream skip
fin.skip(no_of_bytes); CipherInputStream cin = new
CipherInputStream(fin, cipher);
This does not decrypt the file. The output file looks like encrypted.
Dummy read - Reading and ignoring from cipher input stream - this works
//cin.read(bytearray, 0, 30);
Please clarify me the following:
What skip and seek input stream does internally?
Why my cipher input stream seek doesn't work?
Why cipher input stream requires all the bytes to be read from the stream (I assume so) for decrypting? How does it work?
With reference to the article,
Random access InputStream using AES CTR mode in android
After updating the iv with offset value the decryption works fine.
Here is the updated code
package Streams;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class FileReadWrite {
private static final int AES_BLOCK_SIZE = 16;
public static final void jumpToOffset(final Cipher c, final SecretKeySpec aesKey, final IvParameterSpec iv, final long offset) {
if (!c.getAlgorithm().toUpperCase().startsWith("AES/CTR")) {
throw new IllegalArgumentException("Invalid algorithm, only AES/CTR mode supported");
}
if (offset < 0) {
throw new IllegalArgumentException("Invalid offset");
}
final int skip = (int) (offset % AES_BLOCK_SIZE);
final IvParameterSpec calculatedIVForOffset = calculateIVForOffset(iv, offset - skip);
try {
c.init(Cipher.ENCRYPT_MODE, aesKey, calculatedIVForOffset);
final byte[] skipBuffer = new byte[skip];
c.update(skipBuffer, 0, skip, skipBuffer);
Arrays.fill(skipBuffer, (byte) 0);
} catch (ShortBufferException | InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalStateException(e);
}
}
private static IvParameterSpec calculateIVForOffset(final IvParameterSpec iv, final long blockOffset) {
final BigInteger ivBI = new BigInteger(1, iv.getIV());
final BigInteger ivForOffsetBI = ivBI.add(BigInteger.valueOf(blockOffset / AES_BLOCK_SIZE));
final byte[] ivForOffsetBA = ivForOffsetBI.toByteArray();
final IvParameterSpec ivForOffset;
if (ivForOffsetBA.length >= AES_BLOCK_SIZE) {
ivForOffset = new IvParameterSpec(ivForOffsetBA, ivForOffsetBA.length - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
} else {
final byte[] ivForOffsetBASized = new byte[AES_BLOCK_SIZE];
System.arraycopy(ivForOffsetBA, 0, ivForOffsetBASized, AES_BLOCK_SIZE - ivForOffsetBA.length, ivForOffsetBA.length);
ivForOffset = new IvParameterSpec(ivForOffsetBASized);
}
return ivForOffset;
}
public static byte[] getAESKey() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
return bytes;
}
/**
* Method used to generate a random new iv
*
* #return Randomly generated iv
*/
public static byte[] getAESIV() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes);
return bytes;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
FileInputStream fin = new FileInputStream("/Users/emp/Research/Streams/input_file.txt");
FileOutputStream fout = new FileOutputStream("/Users/emp/Research/Streams/output_file.txt");
SecretKeySpec keySpec = null;
IvParameterSpec ivSpec = null;
Cipher ecipher = null;
Cipher dcipher = null;
byte[] keyBytes = getAESKey();
byte[] ivBytes = getAESIV();
// Creating keyspec and ivspec for generating cipher
keySpec = new SecretKeySpec(keyBytes,"AES");
ivSpec = new IvParameterSpec(ivBytes);
try {
ecipher = Cipher.getInstance("AES/CTR/NoPadding");
ecipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
CipherOutputStream cout = new CipherOutputStream(fout, ecipher);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
while((count = fin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
cout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
fout.close();
cout.close();
}
fin = new FileInputStream("/Users/emp/Research/Streams/output_file.txt");
fout = new FileOutputStream("/Users/emp/Research/Streams/decrypted_file.txt");
try {
dcipher = Cipher.getInstance("AES/CTR/NoPadding");
dcipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
fin.skip(1024);
jumpToOffset(dcipher, keySpec, ivSpec, 1024);
CipherInputStream cin = new CipherInputStream(fin, dcipher);
//cin.skip(1024);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
//cin.read(bytearray, 0, 30);
while((count = cin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
fout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
cin.close();
fout.close();
}
System.out.println("File read write completed successfully !!! ");
}
}
Related
I'm working on a file encryption benchmark for large files and tested ChaCha20-Poly1305, but received an error on decryption part:
java.lang.RuntimeException: javax.crypto.ShortBufferException: Output buffer too small
at java.base/com.sun.crypto.provider.ChaCha20Cipher.engineDoFinal(ChaCha20Cipher.java:703)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2085)
at ChaCha20.ChaCha20Poly1305Jre.main(ChaCha20Poly1305Jre.java:73)
Caused by: javax.crypto.ShortBufferException: Output buffer too small
at java.base/com.sun.crypto.provider.ChaCha20Cipher$EngineAEADDec.doFinal(ChaCha20Cipher.java:1360)
at java.base/com.sun.crypto.provider.ChaCha20Cipher.engineDoFinal(ChaCha20Cipher.java:701)
This is not an error in my program but in OpenJava 11 I'm using and should get fixed (known since 2019, see https://bugs.openjdk.java.net/browse/JDK-8224997).
Even with the newest "Early adopter"-version (OpenJDK11U-jdk_x64_windows_11.0.7_9_ea) the error still occurs. This test is run with java version: 11.0.6+8-b520.43.
My question is: is there any other way to perform file encryption with ChaCha20-Poly1305 with native JCE for large files ?
I do not want to use BouncyCastle (as I'm using BC allready for the counterpart benchmark) or reading the plainfile completly into memory (in my source the
testfile is only 1.024 bytes large but the benchmark will test up to 1 GB files). As well I do not want to use ChaCha20 as it does not provide any authentication.
You can find the sources for ChaCha20Poly1305Jce.java, ChaCha20Poly1305JceNoStream.java and ChaCha20Jce.java in my Github-Repo https://github.com/java-crypto/Stackoverflow/tree/master/ChaCha20Poly1305.
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
public class ChaCha20Poly1305Jce {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
System.out.println("File En-/Decryption with ChaCha20-Poly1305 JCE");
System.out.println("see: https://stackoverflow.com/questions/61520639/chacha20-poly1305-fails-with-shortbufferexception-output-buffer-too-small");
System.out.println("\njava version: " + Runtime.version());
String filenamePlain = "test1024.txt";
String filenameEnc = "test1024enc.txt";
String filenameDec = "test1024dec.txt";
Files.deleteIfExists(new File(filenamePlain).toPath());
generateRandomFile(filenamePlain, 1024);
// setup chacha20-poly1305-cipher
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] key = new byte[32]; // 32 for 256 bit key or 16 for 128 bit
byte[] nonce = new byte[12]; // nonce = 96 bit
sr.nextBytes(key);
sr.nextBytes(nonce);
// Get Cipher Instance
Cipher cipherE = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
// Create parameterSpec
AlgorithmParameterSpec algorithmParameterSpec = new IvParameterSpec(nonce);
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key, "ChaCha20");
System.out.println("keySpec: " + keySpec.getAlgorithm() + " " + keySpec.getFormat());
System.out.println("cipher algorithm: " + cipherE.getAlgorithm());
// initialize the cipher for encryption
cipherE.init(Cipher.ENCRYPT_MODE, keySpec, algorithmParameterSpec);
// encryption
System.out.println("start encryption");
byte inE[] = new byte[8192];
byte outE[] = new byte[8192];
try (InputStream is = new FileInputStream(new File(filenamePlain));
OutputStream os = new FileOutputStream(new File(filenameEnc))) {
int len = 0;
while (-1 != (len = is.read(inE))) {
cipherE.update(inE, 0, len, outE, 0);
os.write(outE, 0, len);
}
byte[] outEf = cipherE.doFinal();
os.write(outEf, 0, outEf.length);
} catch (Exception e) {
e.printStackTrace();
}
// decryption
System.out.println("start decryption");
Cipher cipherD = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
// initialize the cipher for decryption
cipherD.init(Cipher.DECRYPT_MODE, keySpec, algorithmParameterSpec);
byte inD[] = new byte[8192];
byte outD[] = new byte[8192];
try (InputStream is = new FileInputStream(new File(filenameEnc));
OutputStream os = new FileOutputStream(new File(filenameDec))) {
int len = 0;
while (-1 != (len = is.read(inD))) {
cipherD.update(inD, 0, len, outD, 0);
os.write(outD, 0, len);
}
byte[] outDf = cipherD.doFinal();
os.write(outDf, 0, outDf.length);
} catch (Exception e) {
e.printStackTrace();
}
// file compare
System.out.println("compare plain <-> dec: " + Arrays.equals(sha256(filenamePlain), sha256(filenameDec)));
}
public static void generateRandomFile(String filename, int size) throws IOException, NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] data = new byte[size];
sr.nextBytes(data);
Files.write(Paths.get(filename), data, StandardOpenOption.CREATE);
}
public static byte[] sha256(String filenameString) throws IOException, NoSuchAlgorithmException {
byte[] buffer = new byte[8192];
int count;
MessageDigest md = MessageDigest.getInstance("SHA-256");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filenameString));
while ((count = bis.read(buffer)) > 0) {
md.update(buffer, 0, count);
}
bis.close();
return md.digest();
}
}
Using the Early Access version of OpenJDK 11.0.8 (get it here: https://adoptopenjdk.net/upstream.html?variant=openjdk11&ga=ea)
I was able to run the (edited) testprogram (now I'm using CipherInput/OutputStreams).
File En-/Decryption with ChaCha20-Poly1305 JCE
see: https://stackoverflow.com/questions/61520639/chacha20-poly1305-fails-with-shortbufferexception-output-buffer-too-small
java version: 11.0.8-ea+8
start encryption
keySpec: ChaCha20 RAW
cipher algorithm: ChaCha20-Poly1305/None/NoPadding
start decryption
compare plain <-> dec: true
Edit: I missed the final version (GA) for one hour but it's working as well:
java version: 11.0.8+10
start encryption
keySpec: ChaCha20 RAW
cipher algorithm: ChaCha20-Poly1305/None/NoPadding
start decryption
compare plain <-> dec: true
new code:
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.*;
import java.util.Arrays;
public class ChaCha20Poly1305JceCis {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
System.out.println("File En-/Decryption with ChaCha20-Poly1305 JCE");
System.out.println("see: https://stackoverflow.com/questions/61520639/chacha20-poly1305-fails-with-shortbufferexception-output-buffer-too-small");
System.out.println("\njava version: " + Runtime.version());
String filenamePlain = "test1024.txt";
String filenameEnc = "test1024enc.txt";
String filenameDec = "test1024dec.txt";
Files.deleteIfExists(new File(filenamePlain).toPath());
generateRandomFile(filenamePlain, 1024);
// setup chacha20-poly1305-cipher
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] key = new byte[32]; // 32 for 256 bit key or 16 for 128 bit
byte[] nonce = new byte[12]; // nonce = 96 bit
sr.nextBytes(key);
sr.nextBytes(nonce);
System.out.println("start encryption");
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
try (FileInputStream in = new FileInputStream(filenamePlain);
FileOutputStream out = new FileOutputStream(filenameEnc);
CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "ChaCha20");
System.out.println("keySpec: " + secretKeySpec.getAlgorithm() + " " + secretKeySpec.getFormat());
System.out.println("cipher algorithm: " + cipher.getAlgorithm());
//AlgorithmParameterSpec algorithmParameterSpec = new IvParameterSpec(nonce);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(nonce));
byte[] buffer = new byte[8096];
int nread;
while ((nread = in.read(buffer)) > 0) {
encryptedOutputStream.write(buffer, 0, nread);
}
encryptedOutputStream.flush();
}
// decryption
System.out.println("start decryption");
Cipher cipherD = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
try (FileInputStream in = new FileInputStream(filenameEnc); // i don't care about the path as all is lokal
CipherInputStream cipherInputStream = new CipherInputStream(in, cipherD);
FileOutputStream out = new FileOutputStream(filenameDec)) // i don't care about the path as all is lokal
{
byte[] buffer = new byte[8192];
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "ChaCha20");
//AlgorithmParameterSpec algorithmParameterSpec = new IvParameterSpec(nonce);
cipherD.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(nonce));
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
out.write(buffer, 0, nread);
}
out.flush();
}
// file compare
System.out.println("compare plain <-> dec: " + Arrays.equals(sha256(filenamePlain), sha256(filenameDec)));
}
public static void generateRandomFile(String filename, int size) throws IOException, NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] data = new byte[size];
sr.nextBytes(data);
Files.write(Paths.get(filename), data, StandardOpenOption.CREATE);
}
public static byte[] sha256(String filenameString) throws IOException, NoSuchAlgorithmException {
byte[] buffer = new byte[8192];
int count;
MessageDigest md = MessageDigest.getInstance("SHA-256");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filenameString));
while ((count = bis.read(buffer)) > 0) {
md.update(buffer, 0, count);
}
bis.close();
return md.digest();
}
}
Edit July 23 2020: Seems to be that not all Java versions with version nr 11.0.8 got fixed. I tested the "original" Oracle Java 1.0.8 for Windows x64 and the error still persists. I reported this to Oracle Bug tracker and it was assigned as a Bug ID: JDK-8249844 (https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8249844).
I am trying to encrypt and decrypt data using CBC mode.
Here, I am first reading the data from a plaintext.txt file and writing the output which is the data of the plaintext.txt to another ciphertext.txt file. While trying to decrypt, I am reading the encrypted data from the file into bytes but for some reason, it's giving me an error. Can someone help me solving this?
Here is my encryption function
// The encryption Function CBC MODE
public static byte[] encrypt(String plainText, String key) throws Exception
{
// Loading the secret key from the Key.txt file
String fileName="../data/key.txt";
try
{
BufferedReader in = new BufferedReader(new FileReader(fileName)); // Initialize a Buffer reader
key = in.readLine(); // Reading the data from txt file
}
//error message if the file is not found
catch(FileNotFoundException ex)
{
System.out.println("Unable to open file '" + fileName + "'");
}
catch(IOException ex)
{
System.out.println("Error reading file '" + fileName + "'");
}
byte[] clean = plainText.getBytes(); //Getting the data in bytes from the plain text
// Generating IV.
//From the initialization vector, we create an IvParameterSpec which is required when creating the Cipher.
int ivSize = 16;
byte[] iv = new byte[ivSize];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
//System.out.println("The Iv is = "+ivParameterSpec);
// Hashing key.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key.getBytes("UTF-8"));
byte[] keyBytes = new byte[32];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(clean);
// Combine IV and encrypted part.
byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
try
{
PrintWriter writer = new PrintWriter("../data/ciphertext.txt");
writer.println(encryptedIVAndText);
writer.close();
}
catch(Exception ex)
{
System.out.println(ex);
System.out.println("File is not there");
}
return encryptedIVAndText;
}
And here is my decryption function.
// Decrypting fucntion CBC mode
public static String decrypt(byte[] encryptedIvTextBytes, String key) throws Exception
{
FileInputStream encryptedTextFis = new FileInputStream("../data/ciphertext.txt");
byte[] encText = new byte[encryptedTextFis.available()];
int lol = encryptedTextFis.available();
System.out.println("lol "+ lol);
encryptedTextFis.read(encText);
encryptedTextFis.close();
// encrypted = readFile("../data/ciphertext.txt", StandardCharsets.UTF_8).getBytes();
encryptedIvTextBytes = encText;
//System.out.println("..........??????");
String fileName="../data/key.txt";
String fileName2="../data/ciphertext.txt";
try
{
BufferedReader in = new BufferedReader(new FileReader(fileName));
BufferedReader in2 = new BufferedReader(new FileReader(fileName2));
key = in.readLine();
// byte[] array = Files.readAllBytes(new File("/path/to/file").toPath());
}
//error message if the file is not found
catch(FileNotFoundException ex)
{
System.out.println("Unable to open file '" + fileName + "'");
}
catch(IOException ex)
{
System.out.println("Error reading file '" + fileName + "'");
}
int ivSize = 16;
int keySize = 32;
//System.out.println("..........??????");
// Extract IV.
byte[] iv = new byte[ivSize];
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
System.out.println("..........??????");
// Extract encrypted part.
int encryptedSize = encryptedIvTextBytes.length - ivSize;
byte[] encryptedBytes = new byte[encryptedSize];
System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
System.out.println("..........??????");
// Hash key.
byte[] keyBytes = new byte[keySize];
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(key.getBytes());
System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Decrypt.
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); //Decrypting the encrypted data to a cipherblock data
byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes); // Decrypting the cipher dadat to Plaintext
//Writing the output to a txt file
try
{
PrintWriter writer = new PrintWriter("../data/result.txt");
writer.println(new String(decrypted));
writer.close();
}
catch(Exception ex)
{
System.out.println(ex);
System.out.println("File is not there");
}
return new String(decrypted); //Returning the decrypted data to main function
}
The output of the encrypted text file is of the form [B#3159c4b8.
I am getting the below error.
It seems exception is here:
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
The length of array encryptedIvTextBytes is 11 (as you say and the result is shown also). Now you want to copy 16 (as the length of iv) bytes from encryptedIvTextBytes.
But the main reason is from this note that your saving method to save encrypted data is not valid. Encrypted data may contain some bytes which are not a readable character. When you save encrypted data as a string such bytes are dropped. To solve this problem see #Maarten and #MS90 comments.
Here is a code that suits your needs:
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
String key = "abcdefghijklmop";// you could store it somewhere ...
justToMakePlainTextFile();
byte[] encrypted = encrypt("plaintext",key);
decrypt(encrypted, key);
}
public static void justToMakePlainTextFile() {
try {
RandomAccessFile randomAccessFile = new RandomAccessFile("plaintext", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
String randomText = "Ho-ho-ho-ho! This is going to be a nice weekend and I am going to swim soon.";
byte[] bytes = randomText.getBytes();
ByteBuffer byteBuffer = ByteBuffer.allocate(randomText.length());//alocate new ByteBuffer of size randomeText.length
byteBuffer.put(bytes);
byteBuffer.flip();
fileChannel.write(byteBuffer);
randomAccessFile.close();
fileChannel.close();
} catch (IOException ioE) {
System.err.println("JVM reported an error! Take a look: " + ioE);
}
}
public static byte[] encrypt(String file, String key) throws Exception {
RandomAccessFile reader = new RandomAccessFile(file, "r");
FileChannel channel = reader.getChannel();
int bufferSize = 1024;
if (bufferSize > channel.size()) {
bufferSize = (int) channel.size();
}
ByteBuffer buff = ByteBuffer.allocate(bufferSize);
channel.read(buff);
buff.flip();
byte[] clean = buff.array();
channel.close();
reader.close();
// Generating IV.
int ivSize = 16;
byte[] iv = new byte[ivSize];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Hashing key.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key.getBytes("UTF-8"));
byte[] keyBytes = new byte[16];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(clean);
// Combine IV and encrypted part.
byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
return encryptedIVAndText;
}
public static void decrypt(byte[] encryptedIvTextBytes, String key) throws Exception {
int ivSize = 16;
int keySize = 16;
// Extract IV.
byte[] iv = new byte[ivSize];
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Extract encrypted part.
int encryptedSize = encryptedIvTextBytes.length - ivSize;
byte[] encryptedBytes = new byte[encryptedSize];
System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
// Hash key.
byte[] keyBytes = new byte[keySize];
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(key.getBytes());
System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Decrypt.
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);
try {
RandomAccessFile randomAccessFile = new RandomAccessFile("ciphertext", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
byte[] bytes = decrypted;
ByteBuffer byteBuffer = ByteBuffer.allocate(decrypted.length);//alocate new ByteBuffer of size randomeText.length
byteBuffer.put(bytes);
byteBuffer.flip();
fileChannel.write(byteBuffer);
randomAccessFile.close();
fileChannel.close();
} catch (IOException ioE) {
System.err.println("JVM reported an error! Take a look: " + ioE);
}
}
ciphertext and plaintext files are in your projects home folder created.
I am not sure what wrong I have done to this. To cut story short I want to decrypt a file with the given secretKey and using iv and I am using the following code to do so :
package com.Crypt.test;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.SecureRandom;
public class AES256CBCTest {
static String encoding = "UTF-8";
public static void main(String[] args) throws Exception {
String key = "BURP6070";
File inputFile = new File("/Users/jaynigam/Documents/workspace/EncryptDecrypt/files/test.xml.enc");
try {
BufferedReader br = new BufferedReader(new FileReader(inputFile));
String st;
File outputFile =null;
FileOutputStream outputStream = null;
try {
while ((st = br.readLine()) != null){
//decrypt(someString.getBytes(encoding), key);
String decrypted = decrypt(st.getBytes(), key);
outputFile = new File("/Users/jaynigam/Documents/workspace/EncryptDecrypt/files/decryptTest.xml.dec");
outputStream = new FileOutputStream(outputFile);
byte[] strToBytes = decrypted.getBytes(encoding);
outputStream.write(strToBytes);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
outputStream.close();
br.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//byte[] encrypted = encrypt(clean, key);
public static byte[] encrypt(String plainText, String key) throws Exception {
byte[] clean = plainText.getBytes();
// Generating IV.
int ivSize = 16;
byte[] iv = new byte[ivSize];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Hashing key.
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(key.getBytes());
byte[] keyBytes = new byte[32];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(clean);
// Combine IV and encrypted part.
byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
return encryptedIVAndText;
}
public static String decrypt(byte[] encryptedIvTextBytes, String key) throws Exception {
int ivSize = 16;
int keySize = 16;
// Extract IV.
byte[] iv = new byte[ivSize];
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Extract encrypted part.
int encryptedSize = encryptedIvTextBytes.length - ivSize;
byte[] encryptedBytes = new byte[encryptedSize];
System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
// Hash key.
byte[] keyBytes = new byte[keySize];
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(key.getBytes());
System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Decrypt.
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/NoPadding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);
return new String(decrypted);
}
}
This returns me an output like ?lm:#?Ú¤?w?)P#?\?s????Ka???0??{???w|k???o?\?. I have already tried UTF-8 decoding. But still no luck till now. Does anyone have any clue on this one?
I've had exactly the same problem as you, and also used the same source code!
I had a problem using the return and input parameters as byte[], so i've converted it to String with Base64 encoding, so i didnt end up with problems with encodings.
My class:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
public class PasswordManager {
private static final Logger LOGGER = LoggerFactory.getLogger(PasswordManager.class);
private static final String key = "DdFfGg998012jffW"; // 128 bit key
private PasswordManager() {
}
public static String encrypt(String plainText) {
if (plainText == null) {
return null;
}
byte[] clean = plainText.getBytes();
// Generating IV.
int ivSize = 16;
byte[] iv = new byte[ivSize];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
try {
// Hashing key.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key.getBytes(StandardCharsets.UTF_8));
byte[] keyBytes = new byte[16];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(clean);
// Combine IV and encrypted part.
byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);
return Base64.getEncoder().encodeToString(encryptedIVAndText);
} catch (Exception e) {
LOGGER.error("Exception in decrypting a password. Returning null", e);
return null;
}
}
public static String decrypt(String encryptedString) {
if (encryptedString == null) {
return null;
}
byte[] encryptedIvTextBytes = Base64.getDecoder().decode(encryptedString);
int ivSize = 16;
int keySize = 16;
// Extract IV.
byte[] iv = new byte[ivSize];
System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Extract encrypted part.
int encryptedSize = encryptedIvTextBytes.length - ivSize;
byte[] encryptedBytes = new byte[encryptedSize];
System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
try {
// Hash key.
byte[] keyBytes = new byte[keySize];
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(key.getBytes());
System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
// Decrypt.
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);
return new String(decrypted);
} catch (Exception e) {
LOGGER.error("Exception in decrypting a password. Returning null", e);
return null;
}
}
}
Also try using a key with the same length as mine, try that first, as it could be the problem. After try to use Base64 on string operations on your while loop.
Hope it helps you.
I am trying to write a program to encrypt and decrypt files using java, but I get an error on the decrypt function:
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
here is the code for the encryption:
public static void EncryptFile(String inFile, PublicKey rsaPublicKey) {
AesManaged aesManaged = new AesManaged();
try {
aesManaged.keySize = 256;
aesManaged.blockSize = 128;
aesManaged.mode = "AES/CBC/PKCS5Padding";
byte[] key = generateKey(aesManaged.keySize);
byte[] keyEncrypted = encryptKey(key, rsaPublicKey);
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.length;
LenK = BitConverter.GetBytes(lKey);
int lIV = aesManaged.IV().length;
LenIV = BitConverter.GetBytes(lIV);
// Write the following to the FileStream
// for the encrypted file (outFs):
// - length of the key
// - length of the IV
// - ecrypted key
// - the IV
// - the encrypted cipher content
String outFile = "test.lamar";
ByteArrayOutputStream outFs = new ByteArrayOutputStream();
outFs.write(LenK);
outFs.write(LenIV);
outFs.write(keyEncrypted);
byte[] i = aesManaged.IV();
outFs.write(i);
IvParameterSpec ivspec = new IvParameterSpec(aesManaged.IV());
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance(aesManaged.mode);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
FileInputStream fileIn = new FileInputStream(inFile);
CipherOutputStream cipherOut = new CipherOutputStream(outFs, cipher);
int blockSiseByte = aesManaged.blockSize / 8;
byte[] data = new byte[blockSiseByte];
int count;
// Read in the data from the file and encrypt it
while ((count = fileIn.read(data, 0, blockSiseByte)) != -1) {
cipherOut.write(data, 0, count);
}
try (OutputStream outputStream = new FileOutputStream(outFile)) {
outFs.writeTo(outputStream);
}
// Close the encrypted file
fileIn.close();
outFs.close();
cipherOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
and the code for the decryption:
public static void DecryptFile(String inFile, String outFile,
PrivateKey rsaPrivateKey) {
FileOutputStream outFs = null;
try {
// Create instance of AesManaged for
// symetric decryption of the data.
AesManaged aesManaged = new AesManaged();
{
aesManaged.keySize = 256;
aesManaged.blockSize = 128;
aesManaged.mode = "AES/CBC/PKCS5Padding";
// Create byte arrays to get the length of
// the encrypted key and IV.
// These values were stored as 4 bytes each
// at the beginning of the encrypted package.
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
// Use FileStream objects to read the encrypted
// file (inFs) and save the decrypted file (outFs).
{
byte[] fileBytes = FileUtils.readFileToByteArray(new File(inFile));
ByteArrayInputStream inFs = new ByteArrayInputStream(
fileBytes);
;
for (int i = 0; i < LenK.length; i++) {
LenK[i] = (byte) inFs.read();
}
for(int i = 0; i< LenIV.length;i++){
LenIV[i] = (byte)inFs.read();
}
// Convert the lengths to integer values.
int lenK = BitConverter.ToInt32(LenK, 0);
int lenIV = BitConverter.ToInt32(LenIV, 0);
//int startC = lenK + lenIV + 8;
//int lenC = (int) fileBytes.length - startC;
// Create the byte arrays for
// the encrypted AesManaged key,
// the IV, and the cipher text.
byte[] KeyEncrypted = new byte[lenK];
byte[] IV = new byte[lenIV];
// Extract the key and IV
for(int i = 0;i<lenK;i++){
KeyEncrypted[i] = (byte)inFs.read();
}
for(int i =0;i<lenIV;i++){
IV[i] = (byte)inFs.read();
}
// to decrypt the AesManaged key.
byte[] KeyDecrypted = decryptKey(KeyEncrypted,rsaPrivateKey);
Cipher transform = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivspec = new IvParameterSpec(IV);
SecretKeySpec secretKeySpec = new SecretKeySpec(KeyDecrypted, "AES");
transform.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
// Decrypt the key.
outFs = new FileOutputStream(outFile);
int count = 0;
int offset = 0;
int blockSizeBytes = aesManaged.blockSize / 8;
byte[] data = new byte[blockSizeBytes];
CipherInputStream cipherIn = new CipherInputStream(
inFs, transform);
while ((count = cipherIn.read(data, 0, blockSizeBytes)) != -1) {
outFs.write(data, 0, count);
}
inFs.close();
cipherIn.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
The error occurred at the line:while ((count = cipherIn.read(data, 0, blockSizeBytes)) != -1) after many iterations.
What am I missing here?
Im sending a file from Server to a Client but i need to send a encrypted file with AES 256 and receive a original for client use in diferente machine.
I want use 2 string to generate a SHA256 for example: "fruit" and "car29".
After generate this key I want to use this key as secretkey to encrypt with AES256.The client and server know the two strings.
My server code:
public final static int SOCKET_PORT = 4444;
public final static String FILE_TO_SEND = "C:\\file.txt";
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
try {
servsock = new ServerSocket(SOCKET_PORT);
while (true) {
System.out.println("Waiting...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
// send file
File myFile = new File(FILE_TO_SEND);
byte[] mybytearray = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray, 0, mybytearray.length);
os = sock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
os.write(mybytearray, 0, mybytearray.length);
os.flush();
System.out.println("Done.");
} finally {
if (bis != null) {
bis.close();
}
if (os != null) {
os.close();
}
if (sock != null) {
sock.close();
}
}
}
} finally {
if (servsock != null) {
servsock.close();
}
}
}
My client code:
public final static int SOCKET_PORT = 4444;
public final static String SERVER = "127.0.0.1";
public final static String FILE_TO_RECEIVED = "C:\\file.txt";
public final static int FILE_SIZE = 6022386;
public static void main (String [] args ) throws IOException {
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock = null;
try {
sock = new Socket(SERVER, SOCKET_PORT);
System.out.println("Connecting...");
// receive file
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File " + FILE_TO_RECEIVED
+ " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null) fos.close();
if (bos != null) bos.close();
if (sock != null) sock.close();
}
}
Thanks in advance!
There's some function I write for you, check it out.
For generating HASH/Digest:
public byte[] generateHASH(byte[] message) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hash = messageDigest.digest(message);
return hash;
}
For Encryption:
public byte[] encrypt(byte[] msg, byte[] key, byte[] iv) throws Exception {
//prepare key
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
//prepare cipher
String cipherALG = "AES/CBC/PKCS5padding"; // use your preferred algorithm
Cipher cipher = Cipher.getInstance(cipherALG);
String string = cipher.getAlgorithm();
//as iv (Initial Vector) is only required for CBC mode
if (string.contains("CBC")) {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
}
byte[] encMessage = cipher.doFinal(msg);
return encMessage;
}
For Decryption:
public byte[] decrypt(byte[] encMsgtoDec, byte[] key, byte[] iv) throws Exception {
//prepare key
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
//prepare cipher
String cipherALG = "AES/CBC/PKCS5padding"; // use your preferred algorithm
Cipher cipher = Cipher.getInstance(cipherALG);
String string = cipher.getAlgorithm();
//as iv (Initial Vector) is only required for CBC mode
if (string.contains("CBC")) {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
}
byte[] decMsg = cipher.doFinal(encMsgtoDec);
return decMsg;
}
Note:
If you use CBC mode, then both encrypt() and decrypt() use same iv, otherwise you don't need iv, and of course key is same for both.
Your key generation process is naive. You better use RSA public key encryption for key exchange or Diffie–Hellman key exchange method for secret key transfer.
I would suggest you to use SSL. The data encryption comes by default. The SSL handshake takes care of generating and exchanging the encryption keys and subsequently encrypting the data from the source and decrypting it at the receiving end. All this happens at the transport layer and the application does not have to bother or do anything explicit except for configuring it to use SSL.