Home > Blockchain >  AES-CBC: using CryptoJS in React-Native and CryptoSwift in Swift
AES-CBC: using CryptoJS in React-Native and CryptoSwift in Swift

Time:09-20

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�J׊p�"

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).

  • Related