I'm building a React-Native app that uses NotificationServiceExtension on iOS to intercept encrypted notifications and decrypt them before showing to the user.
On the react-native side, I encrypt the message using CryptoJS:
const originalText = 'This will be encrypted';
const theAESKeyWordArray = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
const iv = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f"); // Test iv text is in hexadecimal and converting it to wordArray
const ciphertext = CryptoJS.AES.encrypt(originalText, theAESKeyWordArray, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv: iv
}).toString();
On the NotificationServiceExtension side (Swift) using CryptoSwift, after receiving the notification, I'm trying to decode it using the following code:
The "encryptedBody" variable when printed out to console looks exactly the same as console.log(ciphertext) in react-native side. I can also see that when printed out the clearAESKey.string(encoding: .utf8) is the same as that which I used to to encrypt it on the react-native side.
let AESKey = Array<UInt8>(hex: try clearAESKey.string(encoding: .utf8))
let iv = Array<UInt8>(hex: "101112131415161718191a1b1c1d1e1f")
let bufContent: [UInt8] = [UInt8] (encryptedBody.utf8)
let aes = try AES(key: AESKey, blockMode: CBC(iv: iv), padding: .pkcs7)
let padded = Padding.pkcs7.add(to: bufContent, blockSize: AES.blockSize)
let decryptedBody = try aes.decrypt(padded)
let decryptedData = Data(decryptedBody)
let decryptedString = String(decoding: decryptedBody, as: UTF8.self)
print(decryptedString)
The printed output of decryptedString is something like this "L����JtϑJ��E7sD��)�ga�Jp�"
Any ideas what I am doing wrong? Thanks anyone for your help.
Key and IV must be hex decoded, the ciphertext returned by the CryptoJS code must be Base64 decoded. Before decryption, no padding must be applied:
let AESKey = [UInt8](hex: "000102030405060708090a0b0c0d0e0f")
let iv = [UInt8](hex: "101112131415161718191a1b1c1d1e1f")
let bufContent = [UInt8](base64: "GErWj4t2vW0u1o1Z9iUNo8gxkO1O0Bl8l3amQ86EKKw=")
let aes = try AES(key: AESKey, blockMode: CBC(iv: iv), padding: .pkcs7)
let decryptedBody = try aes.decrypt(bufContent)
let decryptedString = String(bytes: decryptedBody, encoding: .utf8)!
print(decryptedString) // This will be encrypted
Keep in mind that a static IV is insecure (for testing purposes this is of course OK).