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.
CodePudding user response:
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).