Kotlin/Native 移植踩坑记
前段时间,鉴于 Linwenxuan 已经写过了纯 Kotlin 的相关加密算法实现 ,想要把半成品的 lagrange-kotlin 移植到 Kotlin/Native 平台,项目地址位于 SaltifyDev/acidify 。在移植过程中,笔者进行了一些努力,但以失败告终,现记录过程如下。
在写下这篇文章不久后,笔者的移植工作受到了 Linwenxuan 的无私协助 ,他编写了纯 Kotlin 的高效 BigInt 实现,并且移植了 ECDH 算法,因而移植工作得以延续。笔者在此对 Linwenxuan 表示诚挚的感谢!
此文档仍然会保留,以记录笔者在移植过程中遇到的坑和寻找到的解决方案,供日后参考。
零反射的 Protobuf 框架
笔者利用 Kotlin 适用于编写 DSL 的特性,结合泛型编写了一个效率不是很高但不使用反射的 Protobuf 框架,大致的定义以及调用流程如下:
class PbObject<S>(val schema: S) {
constructor(schema: S, inputBytes: ByteArray) {
// read input bytes to tree
}
fun <T> get(supplier: S.() -> PbType<T>): T {
// read value from tree
}
}
object SomeSchema {
val intField = PbInt32(1) // underlying type: PbType<Int>
val stringField = PbString(2)
}
fun `extract intField from input`(input: ByteArray): Int {
val pbObj = PbObject(SomeSchema, input)
val intFieldValue = pbObj.get { intField }
return intFieldValue
}
Java 标准库的替代品
不得不说,Kotlin 的标准库远远没有 Java 的完善(一定程度上是因为大爹 JetBrains 太穷了)。但无论如何,笔者还是东拼西凑找到了一点能用的 Kotlin Multiplatform 库,下面是这个项目最后的 libs.versions.toml
(节选):
[libraries]
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlinxSerialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJSON" }
kotlinxCoroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
kotlinxIO = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinxIO" }
ktorClientCore = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktorClientCIO = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktorSerializationKotlinxJson = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
kmpBigNum = { module = "com.ionspin.kotlin:bignum", version.ref = "kmpBigNum" }
cryptoCore = { module = "dev.whyoleg.cryptography:cryptography-core", version.ref = "crypto" }
cryptoProviderOptimal = { module = "dev.whyoleg.cryptography:cryptography-provider-optimal", version.ref = "crypto" }
korlibsCompression = { module = "com.soywiz:korlibs-compression", version.ref = "korlibs" }
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
值得一提的是,其中的 korlibs
源自 Kotlin 的游戏引擎 KorGE ,包含全家桶级别的纯 Kotlin 实现的一些实用功能(尽管不知道可用性如何,Bug 有多少),不知道未来某天会不会被 JetBrains 招安。总之,在找齐了这么多实用工具之后,这个打满补丁的“恒河战舰”总算是能起航了。
插曲:Mac 的编译工具链
If you use a Mac and want to create and run applications for macOS or other Apple targets, you also need to install Xcode Command Line Tools , launch it, and accept the license terms first.
这其中的最后一句 “accept the license terms first” 非常重要。笔者在 Mac 上本身安装了 Xcode Command Line Tools,但在 link 阶段出现了报错,百思不得其解,最后在一篇博客上看到了必须要启动一次 Xcode 并且同意许可协议,才能继续运行,编译问题才算解决。
ECDH 的效率问题
真正在移植代码的时候,还是出现了问题,因为 lagrange-kotlin 的 ECDH 实现依赖了 java.math.BigInteger
,而 Kotlin 并未提供高效率的大整数标准库,移植再一次陷入了困境。笔者尝试了多个 BigInt 的实现(列表可见 ObserverOfTime/kbigint 仓库的 Alternatives 章节 ),其效率都不尽如人意,完成一次 ECDH 密钥交换的时间普遍在 ~10s。通过查阅更多的仓库,笔者发现了可能的原因 :现存的 Kotlin BigInt 的乘法算法实现的时间复杂度普遍在 O(n^2)
级别。笔者尝试依赖成品的 crypto library(例如 cryptography-kotlin ),但其中的 ECDH 并不支持 secp192k1
这一曲线类型。
基于以上种种挫折,笔者的 Kotlin/Native 移植尝试只好作罢。或许我们需要等待更有钱的公司“收养” Kotlin,给它提供更高效更完善的标准库实现;或许我们只是需要等待社区发展,生长出越来越多的“野鸡”库;或许,Kotlin/Native 只不过是黄粱一梦,市面上有那么多天生支持 native 目标的语言,何必要吃这个“强扭的瓜”呢?
CC BY-NC 4.0 2025 © Wesley Young.