Aim:
To be able to encrypt a piece of data (a string) on iOS and decrypt on Android or vice versa to provide users with end-to-end encryption.
Unfortunately, Encrypted Message in Java does not match the Encrypted Message in Swift.
Java: gTwbbTCiE+Km/5Lw3yWlTr/sd5aoN6II66CqsvbiSAE=
Swift: iFA3j0lBPiyz64ge0M67pBPWLYEsVgSHvwY2m+anDQ+lRUauQOq9b3cLqFH1
What I Tried:
Java Implementation
package com.company;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
public class Main {
public static void main(String[] args) throws Exception {
// Get Base64 encoder
Base64.Encoder b64e = Base64.getEncoder();
// Message to encrypt
String str = "Hello, playground";
// Password to use for encryption
String key = "password";
// The bytes of the string requiring encryption
byte[] strByteArray = str.getBytes(StandardCharsets.UTF_8);
// Print the message in plaintext
System.out.println("Message: " + str);
// Print the Base64 encoded message bytes
System.out.println("Message B64: " + b64e.encodeToString(strByteArray));
// The bytes of the key
byte[] keyByteArray = key.getBytes(StandardCharsets.UTF_8);
// Print the key in plaintext
System.out.println("Key: " + key);
// Create an instance of MessageDigest to hash the key using the SHA-256 algorithm
MessageDigest hasher = MessageDigest.getInstance("SHA-256");
// The bytes of the hash digest
byte[] keyHashByteArray = hasher.digest(keyByteArray);
// Print the Base64 encoded key hash bytes
System.out.println("Key B64: " + b64e.encodeToString(keyHashByteArray));
// Create an instance of a SecretKey from the key hash bytes
SecretKey secretKey = new SecretKeySpec(keyHashByteArray, "AES");
// Create an instance of an AES cipher
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// Set the cipher mode to encryption and supply the previously computed SecretKey
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// Encrypt the message string bytes using an AES-256 cipher using the secret key
byte[] ciphertext = cipher.doFinal(strByteArray);
// Print the Base64 encoded ciphertext bytes
System.out.println("Encrypted Message: " + b64e.encodeToString(ciphertext));
}
}
Java Output:
Message: Hello, playground
Message B64: SGVsbG8sIHBsYXlncm91bmQ=
Key: password
Key B64: XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=
Encrypted Message: gTwbbTCiE+Km/5Lw3yWlTr/sd5aoN6II66CqsvbiSAE=
Swift Implementation
import Cocoa
import CryptoKit
// Message to encrypt
var str = "Hello, playground"
// Print the message in plaintext
print("Message: \(str)")
// The bytes of the string requiring encryption
var messageByteArray = Data(str.utf8)
// Print the Base64 encoded message bytes
print("Message B64: \(Data(messageByteArray).base64EncodedString())")
// Password to use for encryption
var key = "password"
// Print the key in plaintext
print("Key: \(key)")
// The bytes of the key
var keyByteArray = Data(key.utf8)
// The bytes of the hash digest
var keyHashByteArray = SHA256.hash(data: keyByteArray);
// Create an instance of a SymmetricKey from the key hash bytes
var symetricKeyFromHash = SymmetricKey(data: keyHashByteArray)
// Print the Base64 encoded key hash bytes
symetricKeyFromHash.withUnsafeBytes {body in
print("Key B64: \(Data(body).base64EncodedString())")
}
// Encrypt the message string bytes using an AES-256 cipher using the secret key
let sealed = try AES.GCM.seal(messageByteArray, using: symetricKeyFromHash)
// Print the Base64 encoded ciphertext bytes
print("Encrypted Message: \(sealed.combined!.base64EncodedString())")
Swift Output:
Message: Hello, playground
Message B64: SGVsbG8sIHBsYXlncm91bmQ=
Key: password
Key B64: XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=
Encrypted Message: NAYn6W22c4IcJUyYpXAKbMLq5yktFUGDPYCOvIRFXISDAK4xrJHh9Yv+15Z9