I'm trying to migrate K/N 0.9.2 -> 1.3.0. I use...
# kotlin-native
a
I'm trying to migrate K/N 0.9.2 -> 1.3.0. I use iOs CommonCrypto module for Sha256 calculation. I have a crypto.def file with this content:
Copy code
package = crypto
headers = CommonCrypto/CommonDigest.h
compilerOpts.ios = -I/opt/local/include
In my .kt file I have
import crypto.*
line and I can use CC_SHA256 function. But when I tried to migrate to K/N 1.3.0 I had a
Unresolved reference: CC_SHA256
compile error. I know that 1.3.0 already have a
CommonCrypto.def
file, so I deleted my
crypto.def
file and replaced
import crypto.*
by
import platform.CoreCrypto.*
. Now I have no compile errors. But I have a linker error instead:
Copy code
ld: warning: directory not found for option '-L/opt/local/lib'
ld: framework not found CommonCrypto
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors
Could anybody help me?
o
Maybe it’s just a typo, could you please share how you use the API?
a
Copy code
import kotlinx.cinterop.*
import platform.Foundation.*
import platform.CoreCrypto.*

actual class Sha256Encoder actual constructor() {

	actual fun encode(text: String?): String {
		if (text == null || text.isEmpty()) {
			return "null"
		}

		memScoped {
			val dataIn = (text as NSString).dataUsingEncoding(NSUTF8StringEncoding.toULong())!!
			val macOut = NSMutableData.dataWithLength(CC_SHA256_DIGEST_LENGTH.convert())!!

			CC_SHA256(dataIn.bytes as CValuesRef<ByteVar>, dataIn.length.toUInt(), macOut.mutableBytes as CValuesRef<UByteVar>);

			val ba = macOut.bytes!!
			val len = macOut.length.toInt()

			return byteToHexString(ba.readBytes(len))
		}
	}
}
o
yes, it's a bug in K/N indeed, to workaround, remove from
$HOME/.konan/kotlin-native-macos-1.0.1//klib/platform/macos_x64/CommonCrypto/manifest
line
linkerOpts=-framework CommonCrypto
. We'll fix it in next release.
a
I've edited the
$HOME/.konan/kotlin-native-macos-1.0.1/klib/platform/ios_x64/CommonCrypto/manifest
and it works now. Thank you!
n
Alexander, thank you for posting your SHA256 code. Saved me a ton of time!
o
BTW, you can do that without explicit memory scopes, with Kotlin objects pinning , like
Copy code
import kotlinx.cinterop.*
import platform.CoreCrypto.CC_SHA256
import platform.CoreCrypto.CC_SHA256_DIGEST_LENGTH

fun main() {
    val input = "Hi Kotlin".toUtf8()
    val digest = UByteArray(CC_SHA256_DIGEST_LENGTH)
    input.usePinned { inputPinned ->
        digest.usePinned { digestPinned ->
            CC_SHA256(inputPinned.addressOf(0), input.size.convert(), digestPinned.addressOf(0))
        }
    }
    val digestString = digest.joinToString(separator = "") { it -> it.toString(16) }
    println(digestString)
}
n
It looks much simpler indeed, but sometimes the result lacks a couple of zero’s. I don’t have the time right now to understand why…
t
@nestserau @olonho I ran into the same issue regarding missing zero’s and could fix it by changing the last bit to
val digestString = digest.joinToString("") { it.toString(16).padStart(2, '0') }