Kotlin 多平台是一项新技术,它缺少许多库。
您将无法在 iOS 上运行 java 代码,因此Cipher
无法在通用代码中使用。
在编写应用程序时,您经常会遇到类似的问题,解决方案始终相同:创建一个接口类并为每个平台实现它。
commomMain/Crypto.kt
expect object Crypto {
fun calculateHash(data: ByteArray, key: ByteArray): ByteArray
}
在 android 部分,您可以Cipher
轻松使用:
androidMain/Crypto.kt
actual object Crypto {
fun calculateHash(data: ByteArray, key: ByteArray): ByteArray {
val cipher: Cipher
var encrypted = ByteArray(16)
try {
val secretKeyEcb: SecretKey = SecretKeySpec(key, "AES")
cipher = Cipher.getInstance("AES")
cipher.init(Cipher.ENCRYPT_MODE, secretKeyEcb)
encrypted = cipher.doFinal(data, 0, 16)
} catch (e: Exception) {
e.printStackTrace()
}
return encrypted.copyOf(8)
}
}
而要实现这iosCommon
部分,您需要为您的问题寻找 iOS 解决方案。我建议你寻找一个 Objective C 解决方案,因为 kotlin 会根据该语言的标头生成它的文件,所以这样的解决方案将比 Swift 解决方案更容易实现。
我遇到的第一个是这个答案,我开始使用它。
您可以尝试在 github 上搜索,看看是否有人已经实现了它。我尝试了 iOS 和 kotlin 过滤的关键类,通常结果数量很少,如果幸运的话,你会找到你需要的。
就您而言,我很幸运能找到此代码。CCCrypt
这是+ kotlin language=)的唯一搜索结果。我将它与obj-c answer结合起来。这看起来与您的Cipher
代码不完全一样,由于某种原因,您也只占用了前 8 个字节。但你应该明白:
actual object Crypto {
@Throws(Throwable::class)
fun calculateHash(data: ByteArray, key: ByteArray): ByteArray {
if (!listOf(
kCCKeySizeAES128,
kCCKeySizeAES192,
kCCKeySizeAES256,
).contains(key.count().toUInt())
) {
throw IllegalStateException("Invalid key length ${key.count()}")
}
val ivLength = kCCBlockSizeAES128
val output = ByteArray(
size = ivLength.toInt() * 2 + data.size
) { 0.toByte() }
val outputSize = ULongArray(1) { 0u }
key.usePinned { keyPinned ->
data.usePinned { inputPinned ->
output.usePinned { outputPinned ->
outputSize.usePinned { outputSizePinned ->
val rcbStatus = SecRandomCopyBytes(
kSecRandomDefault,
ivLength.toULong(),
outputPinned.addressOf(0)
)
if (rcbStatus != kCCSuccess) {
throw IllegalStateException("calculateHash rcbStatus $rcbStatus")
}
val ccStatus = CCCrypt(
op = kCCEncrypt,
alg = kCCAlgorithmAES,
options = kCCOptionPKCS7Padding,
key = keyPinned.addressOf(0),
keyLength = key.size.toULong(),
iv = outputPinned.addressOf(0),
dataIn = inputPinned.addressOf(0),
dataInLength = data.size.toULong(),
dataOut = outputPinned.addressOf(ivLength.toInt()),
dataOutAvailable = output.size.toULong() - ivLength,
dataOutMoved = outputSizePinned.addressOf(0),
)
if (ccStatus != kCCSuccess) {
throw IllegalStateException("calculateHash ccStatus $ccStatus")
}
}
}
}
}
return output.copyOf((outputSize.first() + ivLength).toInt())
}
}