Cross platform AES Encryption between iOS and Kotlin/Java using Apples CryptoKit
Asked Answered
S

1

8

I want to send encrypted data form a server running a kotlin application to an iOS App using Apples CryptoKit. I have problems to initialize a AES.GCM.SealedBox and decrypt the data. In general I don't understand what Sealboxstag is for.

So first Kotlin side:

        fun ByteArray.aesEncrypt(key: ByteArray, iv: ByteArray? = null): ByteArray {
            return aes(this, Cipher.ENCRYPT_MODE, key, iv)
        }
        private fun aes(self: ByteArray, mode: Int, key: ByteArray, iv: ByteArray?): ByteArray{
            val skey = SecretKeySpec(key, "AES")
            val cipher = Cipher.getInstance("AES/GCM/PKCS5Padding")
            println("MODE: ${cipher.algorithm}")
            iv?.let {
                cipher.init(mode, skey, GCMParameterSpec(128, iv))
            }?: run{
                cipher.init(mode, skey)
            }
            val cipherText = ByteArray(cipher.getOutputSize(self.size))
            var ctLength = cipher.update(self, 0, self.size, cipherText, 0)
            ctLength += cipher.doFinal(cipherText, ctLength)
            return cipherText
        }

iOS:

    static private let privateKey = SymmetricKey(size: SymmetricKeySize.bits128)
    static private let nonce = AES.GCM.Nonce()

    static func decrypt(_ data: Data) -> Data {
        print("Encrypted data \(data.bytes)")
        print("Private key: \(privateKey.data.bytes)")
        print("Nonce: \(Array(nonce))")
        let boxToDecrypt = try! AES.GCM.SealedBox(combined: data)
        let plainData = try! AES.GCM.open(boxToDecrypt, using: privateKey)
        return plainData
    }

Of cause both sides have the same key and iv/nonce. The error message I'm running into is:

CryptoKit.CryptoKitError.incorrectParameterSize

in line:

let boxToDecrypt = try! AES.GCM.SealedBox(combined: data)

EDIT I: Additional payload info:

Server(Kotlin):

Not encrypted: 0,0,0,0,0,0,0,1
Key: 169,152,60,154,77,50,10,63,60,166,48,129,1,68,219,250
IV: 134,191,34,26,111,146,17,54,31,212,74,14
Encrypted: 158,154,213,95,227,42,155,199,169,183,166,67,139,154,198,172,229,82,34,30,40,188,41,73


Client(iOS):

Encrypted data [158, 154, 213, 95, 227, 42, 155, 199, 169, 183, 166, 67, 139, 154, 198, 172, 229, 82, 34, 30, 40, 188, 41, 73]
Nonce: [134, 191, 34, 26, 111, 146, 17, 54, 31, 212, 74, 14]
Private key: [169, 152, 60, 154, 77, 50, 10, 63, 60, 166, 48, 129, 1, 68, 219, 250]
Silsby answered 20/4, 2020 at 21:7 Comment(5)
Why not just transmit the data over TLS? It's easy to use and secure.Bondon
It must be possible to indicate at least what parameter is causing this and on what line of the code, I hope.Adlai
@MaartenBodewes Hey I updated my post with some payload info.Silsby
In Java / Kotlin the tag is automatically added to the end of the ciphertext. By default it is 128 bits or 16 bytes. It may be that the Swift sealed box used a different order. However, when I posted a question about this the fanbois voted it into oblivion, so I cannot be bothered anymore than posting this comment. Apple crypto documentation needs to be at deprecated levels it seems.Adlai
@MaartenBodewes Mhhh alright - but thanks :)Silsby
I
7

could you try this (or something like it) with your setup. From what I undestand you need to prefix data with nonce, because data from kotlin/java contains the cipher text plus the tag at the end. CryptoKit needs nonce || ciphertext || tag.

func decrypt(data: Data) -> String {
    // need to prefix data with nonce, because data from kotlin/java contains the cipher text plus the tag at the end.
    // we want nonce || ciphertext || tag for CryptoKit to be happy
    let combine = nonce + data
    if let myNewSealedBox = try? AES.GCM.SealedBox(combined: combine),
        let res = try? AES.GCM.open(myNewSealedBox, using: mykey),
        let myText = try? String(decoding: res, as: UTF8.self) {
        return myText
    }
    return ""
}
Instauration answered 21/4, 2020 at 13:48 Comment(3)
Thank you so much! :)Silsby
I remember the correct order now :P It's not different from normal, but the order is mucked up in every possible way within the documentation.Adlai
After hours of debugging this answer solved the problem for me, thank you very much!Tory

© 2022 - 2024 — McMap. All rights reserved.