I’m implementing AES/GCM/NoPadding encryption in Swift for iOS with a minimum deployment target of 12.1. I’m trying to achieve similar functionality as my Java code below:
Cipher cipherAes = initCipher(Cipher.ENCRYPT_MODE, key, iv);
byte[] encryptedMessageByte = cipherAes.doFinal(messageBytes);
byte[] cipherByte = ByteBuffer.allocate(iv.length + salt.length + encryptedMessageByte.length)
.put(iv)
.put(salt)
.put(encryptedMessageByte)
.array();
In Swift, I’ve written the following code:
let gcm = GCM(iv: iv.bytes, additionalAuthenticatedData: nil, tagLength: tagLength)
let aes = try AES(key: key.bytes, blockMode: gcm, padding: .noPadding)
let encryptedMessage = try aes.encrypt(message.bytes)
let cipherData = Data(iv) + Data(salt) + Data(encryptedMessage)
However, the length of encryptedMessage in Swift differs from encryptedMessageByte in Java. I expected both to produce ciphertext of similar lengths.
Assurance:
I’m sure that the lengths of key, iv, and salt are the same in both Java and Swift implementations.
Question:
Are there any additional configurations or parameters needed for AES/GCM/NoPadding encryption in Swift to match the behavior in Java?
2
Answers
To ensure that your Swift implementation of AES/GCM/NoPadding encryption matches the behavior of your Java implementation, it’s essential to verify several aspects, including the correct setup of the key, IV, and encryption parameters. Both languages should produce the same ciphertext length when given the same input, provided that the AES/GCM setup is identical.
Here’s a detailed step-by-step comparison and setup to help you achieve consistent encryption results between Java and Swift:
Java Code
Let’s first review your Java encryption setup to ensure all parameters are clearly defined:
Swift Code
Now, let’s ensure your Swift code matches the Java setup:
Here’s the revised Swift code:
Key Points to Verify
Troubleshooting
CryptoSwift
library is being used correctly and supports the required AES/GCM functionality.By closely aligning the parameters and verifying each step, you should be able to achieve consistent encryption results between your Java and Swift implementations.
In the Java code, ciphertext and GCM authentication tag are concatenated by default; in the CryptoSwift code, both are handled detached by default.
To make the CryptoSwift code compatible with Java code, either ciphertext and tag can be explicitly concatenated:
or encryption is done in combined mode, whereby ciphertext and tag are implicitly concatenated as well:
See also the AES-GCM examples in the documentation