gpt4 book ai didi

ios - Kotlin Native (iOS),使用 CValuesRef 和 CCCrypt

转载 作者:行者123 更新时间:2023-12-04 11:59:52 29 4
gpt4 key购买 nike

我正在针对 iOS 的 Kotlin 多平台项目中研究 AES256 加密算法。
我检查了一些在纯 Kotlin 中实现这一点的现有库(例如 krypto ),但没有一个符合我对其余代码的要求(已经在 J​​VM 和 JS 中实现了,所以不能变了)。
来自 iOS 背景,我决定使用 CommonCrypto .我改编并移植了来自 here 的代码但我被困在如何通过 ULong引用 CCCrypt函数,然后检索其值。
我非常仔细地阅读了 C Interop 上的 Kotlin 文档。和 Objective-C Interop ,但我找不到任何可以解释如何处理我的案例的示例。
特别是,我的问题是 numBytesEncrypted变量(见下面的代码)。我需要通过引用 CCCrypt 来传递它函数,然后读取其值以实例化结果 NSData长度正确。在 Objective-C/Swift 中,我会在变量前面加上 &调用函数时。
但是,Kotlin 不支持 &运算符(operator)。如果我从文档中理解正确,Native 中的替换是 CValueRef ( docs ),所以我使用了 cValue获取正确类型的引用的简写(应该是 size_t ,也就是 ULong )。
我试图实例化 CValueRef在两种方式中,就类型检查而言,两者似乎都有效:

val numBytesEncrypted = cValue<ULongVar>()
// or
val numBytesEncrypted = cValue<ULongVarOf<size_t>>()
然后我使用这段代码来获取函数执行后的值:
numBytesEncrypted.getPointer(MemScope()).pointed.value // <- this always returns 0.
我测试了算法的其余部分,它完美地工作(加密值是预期的值,解密也有效),但不知道加密/解密数据的长度,我无法实例化 NSData (以及由此产生的 ByteArray )正确。
这是完整的函数代码,包括我编写的扩展(基于找到的代码 here )来转换 NSDataByteArray :
private fun process(operation: CCOperation, key: ByteArray, initVector: ByteArray, data: ByteArray): ByteArray = memScoped {
bzero(key.refTo(0), key.size.convert())

val dataLength = data.size

val buffSize = (dataLength + kCCBlockSizeAES128.toInt()).convert<size_t>()
val buff = platform.posix.malloc(buffSize)

val numBytesEncrypted = cValue<ULongVarOf<size_t>>() // <- or the other way above

val status = CCCrypt(
operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
key.refTo(0), kCCKeySizeAES256.convert(),
initVector.refTo(0),
data.refTo(0), data.size.convert(),
buff, buffSize,
numBytesEncrypted
)

if (status == kCCSuccess) {
return NSData.dataWithBytesNoCopy(
buff,
numBytesEncrypted.getPointer(MemScope()).pointed.value // <- this always returns the original value of the variable or 0.
)
.toByteArray()
}

free(buff)
return byteArrayOfUnsigned(0)
}

fun NSData.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toInt()).apply {
usePinned {
memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length)
}
}
另外,这是我用来验证代码的单元测试:
@Test
fun testAes256() {
val initVector = ByteArray(16) { _ -> 0x00 }
val key = ByteArray(32) { _ -> 0x00 }
val data = ByteArray(1) { _ -> 0x01 }

val expectedEncrypted = byteArrayOfUnsigned(0xFE, 0x2D, 0xE0, 0xEE, 0xF3, 0x2A, 0x05, 0x10, 0xDC, 0x31, 0x2E, 0xD7, 0x7D, 0x12, 0x93, 0xEB)

val encrypted = process(kCCEncrypt, key, initVector, data)
val decrypted = process(kCCDecrypt, key, initVector, encrypted)

assertArraysEquals(expectedEncrypted, encrypted)
assertArraysEquals(data, decrypted)
}

private fun assertArraysEquals(expected: ByteArray, actual: ByteArray) {
if (expected.size != actual.size) asserter.fail("size is different. Expected: ${expected.size}, actual: ${actual.size}")
(expected.indices).forEach { pos ->
if (expected[pos] != actual[pos]) asserter.fail("entry at pos $pos different \n expected: ${debug(expected)} \n actual : ${debug(actual)}")
}
}
先感谢您!

最佳答案

改变

val numBytesEncrypted = cValue<ULongVarOf<size_t>>()
val numBytes = cValue<ULongVar>().ptr
你可以在你的代码中使用它
 NSData.dataWithBytesNoCopy(
buff,
numBytes.pointed.value
).toByteArray()
在描述的方法签名中, dataOutMoved 是 kotlinx.cinterop.CValuesRef 类型。
我发现 getPointer总是分配内存。
public abstract class CValues<T : CVariable> : CValuesRef<T>() {

public override fun getPointer(scope: AutofreeScope): CPointer<T> {
return place(interpretCPointer(scope.alloc(size, align).rawPtr)!!)
}
val numBytes = cValue<ULongVar>()
println("${numBytes.ptr.rawValue} ${numBytes.ptr.rawValue} ${numBytes.ptr.rawValue}")
0x7fa4a593bc18 0x7fa4a593ae28 0x7fa4a593b5d8


val numBytes = cValue<ULongVar>().ptr
println("${numBytes.rawValue} ${numBytes.rawValue} ${numBytes.rawValue}")
0x7fd5a287bfd8 0x7fd5a287bfd8 0x7fd5a287bfd8

关于ios - Kotlin Native (iOS),使用 CValuesRef 和 CCCrypt,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68397010/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com