I am trying to use GCM Mode for encryption and decryption. Unfortunately decryption doesn't work.
Do I have to use the same initialization vector for both encryption and decryption classes? I already tried that, unsuccessfully...
Could the random argument in keyGen.init(128, random)
be the problem?
Encryption code:
public class AES128SymmetricEncryption {
private static final int GCM_NONCE_LENGTH = 12; // in bytes
private static final int GCM_TAG_LENGTH = 16; // in bytes
public static void encode (FileInputStream ciphertextSource, FileOutputStream plaintextDestination)
{
try {
int numRead;
SecureRandom random = SecureRandom.getInstanceStrong();
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128, random);
SecretKey key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, getIV(random));
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] buf = new byte[2048];
while ((numRead = ciphertextSource.read(buf)) > 0) {
byte[] decryptedBlock = cipher.update(buf, 0, numRead);
plaintextDestination.write(decryptedBlock);
}
}
catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (plaintextDestination != null) {
ciphertextSource.close();
}
if (plaintextDestination != null) {
plaintextDestination.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static byte[] getIV(SecureRandom random) {
final byte[] nonce = new byte[GCM_NONCE_LENGTH];
random.nextBytes(nonce);
System.out.println(nonce);
return nonce;
}
public static void main(String[] args) throws GeneralSecurityException, IOException
{
Security.addProvider(new BouncyCastleProvider());
FileInputStream fis = new FileInputStream("C:/Users/roehrlef/Desktop/Test Data/Source Data/100KB.jpg");
FileOutputStream fos = new FileOutputStream("C:/Users/roehrlef/Desktop/Test Data/Encrypted Data/encrypted.jpg");
encode(fis, fos);
}
}
Decryption code:
public class AES128SymmetricDecryption {
private static final int GCM_NONCE_LENGTH = 12; // in bytes
private static final int GCM_TAG_LENGTH = 16; // in bytes
public static void decode (FileInputStream ciphertextSource, FileOutputStream plaintextDestination)
{
try {
int numRead = 0;
SecureRandom random = SecureRandom.getInstanceStrong();
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128, random);
SecretKey key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, getIV(random));
cipher.init(Cipher.DECRYPT_MODE, key, spec);
CipherInputStream cis = new CipherInputStream(ciphertextSource, cipher);
byte[] buf = new byte[2048];
while ((numRead = cis.read(buf)) > 0) {
byte[] decryptedBlock = cipher.update(buf, 0, numRead);
plaintextDestination.write(decryptedBlock);
}
}
catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (plaintextDestination != null) {
ciphertextSource.close();
}
if (plaintextDestination != null) {
plaintextDestination.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static byte[] getIV(SecureRandom random) {
final byte[] nonce = new byte[GCM_NONCE_LENGTH];
random.nextBytes(nonce);
System.out.println(nonce);
return nonce;
}
public static void main(String[] args) throws GeneralSecurityException, IOException
{
Security.addProvider(new BouncyCastleProvider());
FileInputStream fis = new FileInputStream("C:/Users/roehrlef/Desktop/Test Data/Encrypted Data/encrypted.jpg");
FileOutputStream fos = new FileOutputStream("C:/Users/roehrlef/Desktop/Test Data/Decrypted Data/decrypted.jpg");
decode(fis, fos);
}
}