Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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]
like image 902
HansDeBeer Avatar asked Apr 20 '20 21:04

HansDeBeer


People also ask

What is AES in iOS?

A container for Advanced Encryption Standard (AES) ciphers. iOS 13.0+ iPadOS 13.0+ macOS 10.15+ Mac Catalyst 13.0+ tvOS 13.0+ watchOS 6.0+

What is AES CBC 256?

What is 256-bit AES encryption? 256-bit AES encryption refers to the process of concealing plaintext data using the AES algorithm and an AES key length of 256 bits. In addition, 256 bits is the largest AES key length size, as well as its most mathematically complex. It is also the most difficult to crack.

What is AES CBC PKCS5Padding?

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); Cipher name is composed of 3 parts. The first part is the name of the algorithm – AES. The second part is the mode in which the algorithm should be used – CBC. The third part is the padding scheme which is going to be used – PKCS5Padding.


1 Answers

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 ""
}
like image 56
workingdog support Ukraine Avatar answered Sep 29 '22 18:09

workingdog support Ukraine