【问题标题】:Cross platform AES Encryption between iOS and Kotlin/Java using Apples CryptoKit使用 Apples CryptoKit 在 iOS 和 Kotlin/Java 之间进行跨平台 AES 加密
【发布时间】:2020-08-03 12:33:15
【问题描述】:

我想使用 Apples CryptoKit 将加密数据从运行 kotlin 应用程序的服务器发送到 iOS 应用程序。 我在初始化AES.GCM.SealedBox 和解密数据时遇到问题。一般来说,我不明白 Sealboxstag 的用途。

所以首先是 Kotlin 方面:

        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
    }

当然,双方都有相同的密钥和 iv/nonce。我遇到的错误消息是:

CryptoKit.CryptoKitError.incorrectParameterSize

排队:

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

编辑我: 额外的有效载荷信息:

服务器(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


客户端(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]

【问题讨论】:

  • 为什么不直接通过 TLS 传输数据?它易于使用且安全。
  • 我希望至少可以指出 what 参数导致了这种情况以及代码的哪一行。
  • @MaartenBodewes 嘿,我用一些有效载荷信息更新了我的帖子。
  • 在 Java / Kotlin 中,标签会自动添加到密文的末尾。默认为 128 位或 16 字节。可能是斯威夫特密封盒使用了不同的顺序。然而,当我发布一个关于此的问题时,fanbois 投票将其遗忘,所以我只能发布此评论。 Apple 加密文档似乎需要处于已弃用的水平。
  • @MaartenBodewes Mhhh 好的 - 但谢谢 :)

标签: swift kotlin encryption aes apple-cryptokit


【解决方案1】:

你能用你的设置试试这个(或类似的东西)吗?据我了解 您需要在数据前面加上 nonce,因为来自 kotlin/java 的数据包含密文加上末尾的标签。 CryptoKit 需要 nonce ||密文 ||标记。

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 ""
}

【讨论】:

  • 非常感谢! :)
  • 我在这方面花了很多时间,因为它很有趣。我学到了很多东西。
  • 我现在记住了正确的顺序 :P 这与正常的顺序没有什么不同,但是在文档中以各种可能的方式弄乱了顺序。
  • 哈哈,我不会调用 CryptoKit 文字文档。绝对应该弃用。
  • 经过数小时的调试,这个答案为我解决了问题,非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-14
  • 2012-01-30
  • 2017-05-16
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
相关资源
最近更新 更多