I need to encrypt with swift and decrypt with java around 1000 files in a directory.
I tested a prototype with a string and it works thanks to answer from https://stackoverflow.com/users/1831987/vgr at Swift AES GCM encryptor and Java decryption - Padding issues
But when I place that string in a file, it does not work. It works if I print cipher text and tag during encryption and use them separately to decrypt in java, but that's not how it can be done in real world. The file content which is cipher text+nonce+tag, must be decrypted as a whole.
What am I doing wrong here please?
SWIFT ENCRYPTOR
static func encryptDecryptSingleTestFile() {
do {
//encrypt
let data = try Data(contentsOf: URL(fileURLWithPath: filePath1))
print("data in original file \(String(decoding: data, as: UTF8.self))")
let sealedBox = try! AES.GCM.seal(data, using: symKey, nonce: nonce)
let ciphertext = sealedBox.ciphertext.base64EncodedString()
print("ciphertext of sealedbox in file: \(ciphertext)")
let tag = sealedBox.tag
print("tag of sealedbox in file: \(tag.base64EncodedString())")
try sealedBox.combined!.write(to: URL(fileURLWithPath: filePath2))
//DECRYPT - just for testing, actual decrypting will happen in java code
let data2 = try Data(contentsOf: URL(fileURLWithPath: filePath2))
print("data in encrypted file \(String(decoding: data2, as: UTF8.self))")
let sealedBox2 = try AES.GCM.SealedBox(combined: data2)
let decryptedData = try AES.GCM.open(sealedBox2, using: symKey)
try decryptedData.write(to: URL(fileURLWithPath: filePath3))
let ciphertext2 = sealedBox2.ciphertext.base64EncodedString()
let dataInDecryptedFile = try Data(contentsOf: URL(fileURLWithPath: filePath3))
print("data in decrypted file \(String(decoding: dataInDecryptedFile, as: UTF8.self))")
} catch {
print(error)
}
}
OUTPUT
data in original file: abc
ciphertext of sealedbox in file: UoRsEQ==
tag of sealedbox in file: KaryGdpX0t1KwXaDFXEnkw==
data in encrypted file: ~�g�ա�R��@R�l)���W��J�v�q'�
data in decrypted file: abc
JAVA DECRYPTOR
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.FileUtils;
public class FileDecryptro {
static String secret = "my-xxx-bit-secret-my-secret-my-s";
static String nonce = "fv1nixTVoYpSvpdA";
//below values are obtained from the swift encryptor class print statements
static String tag = "KaryGdpX0t1KwXaDFXEnkw==";
static String cipherText = "UoRsEQ==";
public static void main(String args[]) throws Exception {
//decrypt with cipher and tag - WORKS
String decriptedValue = decrypt(cipherText,tag);
System.out.println("output from cipher and tag:" + decriptedValue);
//decrypt from file content which has nonce,tag,ciphertext combined. - DOES NOT WORK
System.out.println("going to decrypt from file which has nonce, tag, ciphertext combined");
String inputFileName = "a_e.txt";
String inputFileContent = FileUtils.readFileToString(new File(inputFileName));///ciphertext and tag is included
System.out.println("inputFileContent:"+inputFileContent);
String decriptedValue2 = decrypt(inputFileContent.getBytes());
System.out.println("output:" + decriptedValue2);
}
static String decrypt(byte[] ciphertextWithTagBytes) throws Exception {
byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
byte[] nonceBytes = Base64.getDecoder().decode(nonce);
//decrypt
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, nonceBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
byte[] plaintextBytes = cipher.doFinal(ciphertextWithTagBytes);
String plaintext = new String(plaintextBytes, StandardCharsets.UTF_8);
return plaintext;
}
static String decrypt(String cipherText, String tag) throws Exception {
byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
byte[] nonceBytes = Base64.getDecoder().decode(nonce);
//append tagBytes to cipherText
byte[] tagBytes = Base64.getDecoder().decode(tag);
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodedCipherText = decoder.decode(cipherText);
byte[] decodedTag = decoder.decode(tag);
byte[] ciphertextBytes = new byte[decodedCipherText.length + decodedTag.length];
ByteBuffer.wrap(ciphertextBytes).put(decodedCipherText).put(decodedTag);
//decrypt
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, nonceBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
byte[] plaintextBytes = cipher.doFinal(ciphertextBytes);
String plaintext = new String(plaintextBytes, StandardCharsets.UTF_8);
return plaintext;
}
}
OUTPUT
output from cipher and tag:abc
going to decrypt from file which has nonce, tag, ciphertext combined
inputFileContent:~�g�ա�R��@R�l)���W��J�v�q'�
Exception in thread "main" javax.crypto.AEADBadTagException: Tag mismatch!