diff --git a/README.md b/README.md index 2b30433..a636610 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,26 @@ # Libsodium bindings for Kotiln Multiplatform -Libsodium bindings project uses libsodium c sources, libsodium.js as well as LazySodium Java and Android to provide a kotlin multiplatform wrapper library for libsodium. +Libsodium bindings project uses libsodium c sources and libsodium.js to provide a kotlin multiplatform wrapper library for libsodium. ## Installation -The libsodium binding library is not published yet, once the sample showing the basic usage is ready, the library will be published. You can track the implementation -[progress here](https://github.com/ionspin/kotlin-multiplatform-crypto/blob/master/supported_bindings_list.md) +#### Gradle +```kotlin +implementation("com.ionspin.kotlin:multiplatform-crypto-lisodium-bindings:0.8.0") +``` + +#### Snapshot builds +```kotlin +repositories { + maven { + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } +} +implementation("com.ionspin.kotlin:multiplatform-crypto-lisodium-bindings:0.8.1-SNAPSHOT ") + +``` + ## Usage @@ -18,8 +32,7 @@ The libsodium binding library is not published yet, once the sample showing the Before using the wrapper you need to initialize the underlying libsodium library. You can use either a callback or coroutines approach ``` - = runTest { - LibsodiumInitializer.initializeWithCallback { + LibsodiumInitializer.initializeWithCallback { // Libsodium initialized } ``` @@ -125,31 +138,20 @@ Currently supported native platforms: |minGW X86 64| :heavy_check_mark: | |minGW X86 32| :x: | +[List of supported bindings](https://github.com/ionspin/kotlin-multiplatform-crypto/blob/master/supported_bindings_list.md) +### Where do the compiled libraries used by JVM and Android come from +Android .so files come from running dist-build scripts in libsodium which you can find in the libsodium submodule +Java Linux Arm/X86_64 and Mac so and dylib are the same as produced by multiplatform builds, also based on the same submodule commit +Java Windows dll is from https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip + ### TODO: - Copy/adapt code documentation, currently only some functions have documentation that is a copy-paste from libsodium website -- Replace LazySodium with direct JNA calls, and add build scripts for required libraries if missing - Android testing - Fix browser testing, both locally and in CI/CD - LobsodiumUtil `unpad` and `fromBase64` native implementations use a nasty hack to support shared native sourceset. The hack either needs to be removed and replaced with another solution or additional safeguards need to be added. - Complete exposing libsodium constants -### Known issues: -- Using LazySodium self built variant to fix some of the bugs present in LazySodium, but **Android** is using directly - LazySodium release which has not been updated (latest version is 4.2.0), this means that randombytes_random, basetobin and - base64tohex functions are not working on Android, as well as problems with sodium_pad: - - https://github.com/terl/lazysodium-java/issues/83 - - https://github.com/terl/lazysodium-java/issues/85 - - https://github.com/terl/lazysodium-java/issues/86 - - Also it is not clear where are the precompiled libraries in LazySodium coming from - - This will be handled by providing a new JNA libsodium wrapper library - - #### Notes for Gitlab runners: - At the moment all runners need to have android sdk diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt index 8198cec..0c8c609 100644 --- a/buildSrc/src/main/kotlin/Deps.kt +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -24,14 +24,16 @@ object Versions { val dokkaPlugin = "1.4.20" val taskTreePlugin = "1.5" val kotlinBigNumVersion = "0.2.8-SNAPSHOT" - val lazySodium = "4.3.1-SNAPSHOT" - val jna = "5.5.0" + val jna = "5.7.0" val kotlinPoet = "1.6.0" val libsodiumBindings = "0.1.1-SNAPSHOT" val ktor = "1.3.2" val timber = "4.7.1" val kodeinVersion = "7.1.0" + val resourceLoader = "1.3.10" + + } @@ -39,7 +41,7 @@ object Versions { object ReleaseInfo { val group = "com.ionspin.kotlin" val version = "0.1.0-SNAPSHOT" - val bindingsVersion = "0.1.1-SNAPSHOT" + val bindingsVersion = "0.8.0-SNAPSHOT" } object Deps { @@ -112,11 +114,9 @@ object Deps { val kotlinPoet = "com.squareup:kotlinpoet:${Versions.kotlinPoet}" + val resourceLoader = "co.libly:resource-loader:${Versions.resourceLoader}" + object Delegated { - // Temporary until reported lazysodium issues are fixed. My snapshot build with - // And cause I registered com.ionspin.kotlin as maven central package root now I have to use - // that even though this is pure java library. :) - val lazysodium = "com.ionspin.kotlin:lazysodium-java:${Versions.lazySodium}" val jna = "net.java.dev.jna:jna:${Versions.jna}" } } @@ -139,6 +139,7 @@ object Deps { val ktorClientSerialization = "io.ktor:ktor-client-serialization-jvm:${Versions.ktor}" val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.kotlinSerialization}" val timber = "com.jakewharton.timber:timber:${Versions.timber}" + val jna = "net.java.dev.jna:jna:${Versions.jna}@aar" } object Desktop { diff --git a/multiplatform-crypto-libsodium-bindings/build.gradle.kts b/multiplatform-crypto-libsodium-bindings/build.gradle.kts index 738d574..cb5fe7f 100644 --- a/multiplatform-crypto-libsodium-bindings/build.gradle.kts +++ b/multiplatform-crypto-libsodium-bindings/build.gradle.kts @@ -48,7 +48,6 @@ val sonatypeUsernameEnv: String? = System.getenv()["SONATYPE_USERNAME"] repositories { mavenCentral() jcenter() - maven("https://dl.bintray.com/terl/lazysodium-maven") maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots") } @@ -73,6 +72,9 @@ android { isMinifyEnabled = false } } + sourceSets.getByName("main") { +// jniLibs.srcDir("src/androidMain/libs") + } } @@ -80,9 +82,10 @@ android { kotlin { val hostOsName = getHostOsName() android() + jvm() runningOnLinuxx86_64 { println("Configuring Linux X86-64 targets") - jvm() + js(IR) { browser { testTask { @@ -438,14 +441,16 @@ kotlin { val androidMain by getting { isNotRunningInIdea { - kotlin.srcDirs("src/androidSpecific", "src/jvmMain/kotlin") + kotlin.srcDirs("src/androidMain", "src/androidSpecific", "src/jvmMain/kotlin") } isRunningInIdea { - kotlin.srcDirs("src/androidSpecific") + kotlin.srcDirs("src/androidSpecific", "src/jvmMain/kotlin") } dependencies { - implementation("com.goterl.lazycode:lazysodium-android:4.2.0@aar") implementation("net.java.dev.jna:jna:5.5.0@aar") + implementation(Deps.Jvm.resourceLoader) { + exclude("net.java.dev.jna", "jna") + } } } @@ -458,28 +463,30 @@ kotlin { } } + val jvmMain by getting { + kotlin.srcDirs("src/jvmSpecific", "src/jvmMain/kotlin") + dependencies { + implementation(kotlin(Deps.Jvm.stdLib)) + implementation(kotlin(Deps.Jvm.test)) + implementation(kotlin(Deps.Jvm.testJUnit)) + implementation(Deps.Jvm.resourceLoader) + + implementation(Deps.Jvm.Delegated.jna) + + implementation("org.slf4j:slf4j-api:1.7.30") + } + } + val jvmTest by getting { + dependencies { + implementation(kotlin(Deps.Jvm.test)) + implementation(kotlin(Deps.Jvm.testJUnit)) + implementation(kotlin(Deps.Jvm.reflection)) + } + } runningOnLinuxx86_64 { println("Configuring Linux 64 Bit source sets") - val jvmMain by getting { - kotlin.srcDirs("src/jvmSpecific", "src/jvmMain/kotlin") - dependencies { - implementation(kotlin(Deps.Jvm.stdLib)) - implementation(kotlin(Deps.Jvm.test)) - implementation(kotlin(Deps.Jvm.testJUnit)) - //lazysodium - implementation(Deps.Jvm.Delegated.lazysodium) - implementation(Deps.Jvm.Delegated.jna) - } - } - val jvmTest by getting { - dependencies { - implementation(kotlin(Deps.Jvm.test)) - implementation(kotlin(Deps.Jvm.testJUnit)) - implementation(kotlin(Deps.Jvm.reflection)) - } - } val jsMain by getting { @@ -678,6 +685,13 @@ tasks { } +allprojects { + tasks.withType(JavaCompile::class) { + sourceCompatibility = "1.8" + targetCompatibility = "1.8" + } +} + signing { diff --git a/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/arm64-v8a/libsodium.so b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/arm64-v8a/libsodium.so new file mode 100755 index 0000000..f788e86 Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/arm64-v8a/libsodium.so differ diff --git a/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/armeabi-v7a/libsodium.so b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/armeabi-v7a/libsodium.so new file mode 100755 index 0000000..9f95266 Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/armeabi-v7a/libsodium.so differ diff --git a/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/armeabi/libsodium.so b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/armeabi/libsodium.so new file mode 100755 index 0000000..a35a5e6 Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/armeabi/libsodium.so differ diff --git a/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86/libsodium.so b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86/libsodium.so new file mode 100755 index 0000000..ebc9823 Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86/libsodium.so differ diff --git a/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86_64/libsodium.so.so b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86_64/libsodium.so.so new file mode 100755 index 0000000..046b0db Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86_64/libsodium.so.so differ diff --git a/multiplatform-crypto-libsodium-bindings/src/androidSpecific/com/ionspin/kotlin/crypto/AndroidSodiumWrapper.kt b/multiplatform-crypto-libsodium-bindings/src/androidSpecific/com/ionspin/kotlin/crypto/AndroidSodiumWrapper.kt index b537c33..3e38013 100644 --- a/multiplatform-crypto-libsodium-bindings/src/androidSpecific/com/ionspin/kotlin/crypto/AndroidSodiumWrapper.kt +++ b/multiplatform-crypto-libsodium-bindings/src/androidSpecific/com/ionspin/kotlin/crypto/AndroidSodiumWrapper.kt @@ -1,12 +1,2 @@ package com.ionspin.kotlin.crypto -import com.goterl.lazycode.lazysodium.LazySodiumAndroid -import com.goterl.lazycode.lazysodium.SodiumAndroid - - -/** - * Created by Ugljesa Jovanovic - * ugljesa.jovanovic@ionspin.com - * on 22-Aug-2020 - */ -typealias SodiumWrapper = SodiumAndroid diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/stream/Stream.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/stream/Stream.kt index 1f4ab72..7171c71 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/stream/Stream.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/stream/Stream.kt @@ -9,13 +9,22 @@ const val crypto_stream_chacha20_KEYBYTES = 32 const val crypto_stream_chacha20_NONCEBYTES = 8 const val crypto_stream_chacha20_ietf_KEYBYTES = 32 const val crypto_stream_chacha20_ietf_NONCEBYTES = 12 +const val crypto_stream_xchacha20_NONCEBYTES = 24 +const val crypto_stream_xchacha20_KEYBYTES = 32 expect object Stream { - fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray) : UByteArray - fun chacha20IetfXor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray - fun chacha20IetfXorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray fun chacha20Keygen() : UByteArray + + fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray) : UByteArray fun chacha20Xor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray fun chacha20XorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray + + fun chacha20IetfXor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray + fun chacha20IetfXorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray + +// fun xChacha20Keygen() : UByteArray +// +// fun xChacha20Xor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray +// fun xChacha20XorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray } diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt index d8360f0..1a69d8f 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt @@ -10,6 +10,9 @@ enum class Base64Variants(val value: Int) { ORIGINAL(1), ORIGINAL_NO_PADDING(3), URLSAFE(5), URLSAFE_NO_PADDING(7) } +class ConversionException() : RuntimeException("Conversion failed") +class PaddingException() : RuntimeException("Padding failed") + expect object LibsodiumUtil { fun memcmp(first: UByteArray, second: UByteArray) : Boolean diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/stream/StreamTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/stream/StreamTest.kt index 3003444..fa8d442 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/stream/StreamTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/stream/StreamTest.kt @@ -68,4 +68,26 @@ class StreamTest { } } } + +// @Test +// fun testXChaCha20IetfStream() = runTest { +// LibsodiumInitializer.initializeWithCallback { +// val message = "This is a cha cha message".encodeToUByteArray() +// val nonce = LibsodiumRandom.bufDeterministic(crypto_stream_xchacha20_NONCEBYTES, seed) +// val key = Stream.xChacha20Keygen() +// val encryptedUsingLibsodium = Stream.xChacha20Xor(message, nonce, key) +// val encryptedUsingLibsodiumWithInitialCounter = Stream.xChacha20XorIc(message, nonce, 0U, key) +// println(encryptedUsingLibsodium.toHexString()) +// println(encryptedUsingLibsodiumWithInitialCounter.toHexString()) +// assertTrue { +// encryptedUsingLibsodium.contentEquals(encryptedUsingLibsodiumWithInitialCounter) +// } +// val decryptedUsingLibsodium = Stream.xChacha20Xor(encryptedUsingLibsodium, nonce, key) +// println(message.toHexString()) +// println(decryptedUsingLibsodium.toHexString()) +// assertTrue { +// decryptedUsingLibsodium.contentEquals(message) +// } +// } +// } } diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt index a3aa2c5..3b4fe47 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt @@ -232,6 +232,10 @@ interface JsSodiumInterface { fun crypto_stream_chacha20_xor(message : Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array fun crypto_stream_chacha20_xor_ic(message : Uint8Array, nonce: Uint8Array, initialCounter: UInt, key: Uint8Array) : Uint8Array + fun crypto_stream_xchacha20_keygen() : Uint8Array + fun crypto_stream_xchacha20_xor(message : Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array + fun crypto_stream_xchacha20_xor_ic(message : Uint8Array, nonce: Uint8Array, initialCounter: UInt, key: Uint8Array) : Uint8Array + // ---- Stream end ---- // ---- Scalar multiplication ---- diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt index 4845654..2dbc0fe 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt @@ -79,4 +79,42 @@ actual object Stream { return result.toUByteArray() } + +// actual fun xChacha20Keygen(): UByteArray { +// val result = getSodium().crypto_stream_xchacha20_keygen() +// +// return result.toUByteArray() +// } +// +// actual fun xChacha20Xor( +// message: UByteArray, +// nonce: UByteArray, +// key: UByteArray +// ): UByteArray { +// val result = getSodium().crypto_stream_xchacha20_xor( +// message.toUInt8Array(), +// nonce.toUInt8Array(), +// key.toUInt8Array() +// ) +// +// return result.toUByteArray() +// } +// +// actual fun xChacha20XorIc( +// message: UByteArray, +// nonce: UByteArray, +// initialCounter: ULong, +// key: UByteArray +// ): UByteArray { +// val result = getSodium().crypto_stream_xchacha20_xor_ic( +// message.toUInt8Array(), +// nonce.toUInt8Array(), +// initialCounter.toUInt(), +// key.toUInt8Array() +// ) +// +// return result.toUByteArray() +// } + + } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/JnaLibsodiumInterface.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/JnaLibsodiumInterface.kt new file mode 100644 index 0000000..f2fa16a --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/JnaLibsodiumInterface.kt @@ -0,0 +1,1288 @@ +package com.ionspin.kotlin.crypto + +import com.sun.jna.Library +import com.sun.jna.Pointer +import com.sun.jna.Structure + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Feb-2021 + */ +class Hash256State : Structure() { + override fun getFieldOrder(): List = listOf("state", "count", "buf") + + @JvmField + val state = IntArray(8) + + @JvmField + var count: Long = 0 + + @JvmField + val buf = ByteArray(64) +} + +class Hash512State : Structure() { + override fun getFieldOrder(): List = listOf("state", "count", "buf") + + @JvmField + val state = LongArray(8) + + @JvmField + var count: LongArray = LongArray(2) + + @JvmField + val buf = ByteArray(128) +} + +class Blake2bState : Structure() { + override fun getFieldOrder(): List = listOf("opaque") + + @JvmField + val opaque = ByteArray(384) +} + +//typedef struct crypto_sign_ed25519ph_state { +// crypto_hash_sha512_state hs; +//} crypto_sign_ed25519ph_state; +class Ed25519SignatureState : Structure() { + override fun getFieldOrder() = listOf("hs") + + @JvmField + var hs: Hash512State = Hash512State() +} + + +// typedef struct crypto_secretstream_xchacha20poly1305_state { +// unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES]; +// unsigned char nonce[crypto_stream_chacha20_ietf_NONCEBYTES]; +// unsigned char _pad[8]; +// } crypto_secretstream_xchacha20poly1305_state; +class SecretStreamXChaCha20Poly1305State : Structure() { + override fun getFieldOrder(): List = listOf("k", "nonce", "_pad") + + @JvmField + val k = ByteArray(32) + + @JvmField + val nonce = ByteArray(12) + + @JvmField + val _pad = ByteArray(8) +} + +interface JnaLibsodiumInterface : Library { + + // ---- Utils ---- + fun sodium_version_string(): String + + fun randombytes_buf(buffer: ByteArray, bufferSize: Int) + + // void randombytes_buf_deterministic(void * const buf, const size_t size, + // const unsigned char seed[randombytes_SEEDBYTES]) + fun randombytes_buf_deterministic( + buffer: ByteArray, + size: Int, + seed: ByteArray + ) + + // uint32_t randombytes_random(void) + fun randombytes_random() : Long + + // uint32_t randombytes_uniform(const uint32_t upper_bound); + fun randombytes_uniform( + upperBound: Long + ) : Long + + // void sodium_memzero(void * const pnt, const size_t len); + fun sodium_memzero(array: ByteArray, len: Int) + + // int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len) + fun sodium_memcmp(b1: ByteArray, b2: ByteArray, len: Int): Int + + // char *sodium_bin2hex(char * const hex, const size_t hex_maxlen, + // const unsigned char * const bin, const size_t bin_len) + fun sodium_bin2hex( + hex: ByteArray, + hexMaxlen: Int, + bin: ByteArray, + binLen: Int + ): String + + // int sodium_hex2bin( + // unsigned char * const bin, const size_t bin_maxlen, + // const char * const hex, const size_t hex_len, + // const char * const ignore, size_t * const bin_len, + // const char ** const hex_end) + fun sodium_hex2bin( + bin: ByteArray, + binMaxLength: Int, + hex: ByteArray, + hexLen: Int, + ignore: ByteArray?, + binLen: Pointer, + hexEnd: Pointer? + ): Int + + // int sodium_pad(size_t *padded_buflen_p, unsigned char *buf, + // size_t unpadded_buflen, size_t blocksize, size_t max_buflen) + fun sodium_pad( + paddedBufferLength: Pointer, + buffer: ByteArray, + unpaddedBufferLength: Int, + blockSize: Int, + maxBufferLength: Int + ): Int + + // int sodium_unpad(size_t *unpadded_buflen_p, const unsigned char *buf, + // size_t padded_buflen, size_t blocksize) + fun sodium_unpad( + unpaddedBufferLength: Pointer, + buffer: ByteArray, + paddedBufferLength: Int, + blockSize: Int + ) + + + // char *sodium_bin2base64(char * const b64, const size_t b64_maxlen, + // const unsigned char * const bin, const size_t bin_len, + // const int variant) + fun sodium_bin2base64( + base64: ByteArray, + base64MaxLength: Int, + bin: ByteArray, + binLength: Int, + variant: Int + ): Int + + // int sodium_base642bin( + // unsigned char * const bin, const size_t bin_maxlen, + // const char * const b64, const size_t b64_len, + // const char * const ignore, size_t * const bin_len, + // const char ** const b64_end, const int variant) + fun sodium_base642bin( + bin: ByteArray, + binMaxLength: Int, + base64: ByteArray, + base64Length: Int, + ignore: ByteArray?, + binLength: Pointer, + base64End: Pointer?, + variant: Int + ): Int + + // size_t sodium_base64_encoded_len(const size_t bin_len, const int variant) + fun sodium_base64_encoded_len(binLength: Int, variant: Int): Int + + // --- Utils end ---- + + // int crypto_generichash(unsigned char *out, size_t outlen, + // const unsigned char *in, unsigned long long inlen, + // const unsigned char *key, size_t keylen) + fun crypto_generichash( + out: ByteArray, + outlen: Int, + input: ByteArray, + inputLength: Long, + key: ByteArray, + keylen: Int + ): Int + + // int crypto_hash_sha256(unsigned char *out, const unsigned char *in, + // unsigned long long inlen) + fun crypto_hash_sha256(out: ByteArray, input: ByteArray, inputLength: Long): Int + + // int crypto_hash_sha512(unsigned char *out, const unsigned char *in, + // unsigned long long inlen) + fun crypto_hash_sha512(out: ByteArray, input: ByteArray, inputLength: Long): Int +// +// // ---- Generic hash ---- // Updateable +// + + // int crypto_generichash_init(crypto_generichash_state *state, + // const unsigned char *key, + // const size_t keylen, const size_t outlen) + // Output cant be larger than 64 so no need to use Long to represent size_t here + fun crypto_generichash_init(state: Blake2bState, key: ByteArray, keylen: Int, outlen: Int): Int + + // int crypto_generichash_update(crypto_generichash_state *state, + // const unsigned char *in, + // unsigned long long inlen) + fun crypto_generichash_update(state: Blake2bState, inputMessage: ByteArray, inputLength: Long): Int + + // int crypto_generichash_final(crypto_generichash_state *state, + // unsigned char *out, const size_t outlen) + // Output cant be larger than 64 so no need to use Long to represent size_t here + fun crypto_generichash_final(state: Blake2bState, out: ByteArray, hashLength: Int): Int + + // void crypto_generichash_keygen(unsigned char k[crypto_generichash_KEYBYTES]) + fun crypto_generichash_keygen(key: ByteArray) + + fun crypto_generichash_statebytes(): Int + + // +// // ---- Generic hash end ---- // Updateable +// +// // ---- Blake2b ---- + // int crypto_generichash_blake2b(unsigned char *out, size_t outlen, + // const unsigned char *in, + // unsigned long long inlen, + // const unsigned char *key, size_t keylen) + // Output cant be larger than 64 so no need to use Long to represent size_t here + fun crypto_generichash_blake2b( + out: ByteArray, + outlen: Int, + input: ByteArray, + inputLength: Long, + key: ByteArray, + keylen: Int + ): Int + + // int crypto_generichash_blake2b_init(crypto_generichash_blake2b_state *state, + // const unsigned char *key, + // const size_t keylen, const size_t outlen) + fun crypto_generichash_blake2b_init(kstate: ByteArray, key: ByteArray, keylen: Int, outlen: Int): Int + + // int crypto_generichash_blake2b_update(crypto_generichash_blake2b_state *state, + // const unsigned char *in, + // unsigned long long inlen) + fun crypto_generichash_blake2b_update(state: ByteArray, inputMessage: ByteArray, inputLength: Long): Int + + // int crypto_generichash_blake2b_final(crypto_generichash_blake2b_state *state, + // unsigned char *out, + // const size_t outlen) + fun crypto_generichash_blake2b_final(state: ByteArray, out: ByteArray, hashLength: Int): Int + + // void crypto_generichash_blake2b_keygen(unsigned char k[crypto_generichash_blake2b_KEYBYTES]) + fun crypto_generichash_blake2b_keygen(key: ByteArray) +// +// // ---- Blake2b end ---- +// +// // ---- Short hash ---- +// + + // int crypto_shorthash(unsigned char *out, const unsigned char *in, + // unsigned long long inlen, const unsigned char *k) + fun crypto_shorthash(out: ByteArray, input: ByteArray, inlen: Long, key: ByteArray): Int + + // void crypto_shorthash_keygen(unsigned char k[crypto_shorthash_KEYBYTES]) + fun crypto_shorthash_keygen(key: ByteArray): Int + +// +// ---- Short hash end ---- +// + + // int crypto_hash_sha256_init(crypto_hash_sha256_state *state) + fun crypto_hash_sha256_init(state: Hash256State): Int + + // int crypto_hash_sha256_update(crypto_hash_sha256_state *state, + // const unsigned char *in, + // unsigned long long inlen) + fun crypto_hash_sha256_update(state: Hash256State, input: ByteArray, inlen: Long): Int + + // int crypto_hash_sha256_final(crypto_hash_sha256_state *state, + // unsigned char *out) + fun crypto_hash_sha256_final(state: Hash256State, out: ByteArray): Int + + + // int crypto_hash_sha512_init(crypto_hash_sha512_state *state) + fun crypto_hash_sha512_init(state: Hash512State): Int + + // int crypto_hash_sha512_update(crypto_hash_sha512_state *state, + // const unsigned char *in, + // unsigned long long inlen) + fun crypto_hash_sha512_update(state: Hash512State, input: ByteArray, inlen: Long): Int + + // int crypto_hash_sha512_final(crypto_hash_sha512_state *state, + // unsigned char *out) + fun crypto_hash_sha512_final(state: Hash512State, out: ByteArray): Int + + + // + // --------------------- AEAD + // + + // + // XChaCha20Poly1305Ietf + // + + // int crypto_aead_xchacha20poly1305_ietf_encrypt( + // unsigned char *c, + // unsigned long long *clen_p, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *nsec, + // const unsigned char *npub, + // const unsigned char *k + // ) + fun crypto_aead_xchacha20poly1305_ietf_encrypt( + ciphertext: ByteArray, + ciphertextLength: LongArray?, + message: ByteArray, + messageLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + nsec: ByteArray?, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_xchacha20poly1305_ietf_decrypt( + // unsigned char *m, + // unsigned long long *mlen_p, + // unsigned char *nsec, + // const unsigned char *c, + // unsigned long long clen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_xchacha20poly1305_ietf_decrypt( + message: ByteArray, + messageLength: LongArray?, + nsec: ByteArray?, + ciphertext: ByteArray, + ciphertextLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_xchacha20poly1305_ietf_encrypt_detached( + // unsigned char *c, + // unsigned char *mac, + // unsigned long long *maclen_p, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *nsec, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_xchacha20poly1305_ietf_encrypt_detached( + ciphertext: ByteArray, + mac: ByteArray, + maclen: LongArray?, + message: ByteArray, + messageLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + nsec: ByteArray?, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_xchacha20poly1305_ietf_decrypt_detached( + // unsigned char *m, + // unsigned char *nsec, + // const unsigned char *c, + // unsigned long long clen, + // const unsigned char *mac, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_xchacha20poly1305_ietf_decrypt_detached( + message: ByteArray, + nsec: ByteArray?, + ciphertext: ByteArray, + ciphertextLength: Long, + mac: ByteArray, + additionalData: ByteArray, + additionalDataLength: Long, + npub: ByteArray, + key: ByteArray + ): Int + + // void crypto_aead_xchacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES]) + fun crypto_aead_xchacha20poly1305_ietf_keygen(key: ByteArray) + + // + // ChaCha20Poly1305Ietf + // + + // int crypto_aead_chacha20poly1305_ietf_encrypt( + // unsigned char *c, + // unsigned long long *clen_p, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *nsec, + // const unsigned char *npub, + // const unsigned char *k + // ) + fun crypto_aead_chacha20poly1305_ietf_encrypt( + ciphertext: ByteArray, + ciphertextLength: LongArray?, + message: ByteArray, + messageLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + nsec: ByteArray?, + npub: ByteArray, + key: ByteArray + ) + + // int crypto_aead_chacha20poly1305_ietf_decrypt( + // unsigned char *m, + // unsigned long long *mlen_p, + // unsigned char *nsec, + // const unsigned char *c, + // unsigned long long clen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_chacha20poly1305_ietf_decrypt( + message: ByteArray, + messageLength: LongArray?, + nsec: ByteArray?, + ciphertext: ByteArray, + ciphertextLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_chacha20poly1305_ietf_encrypt_detached( + // unsigned char *c, + // unsigned char *mac, + // unsigned long long *maclen_p, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *nsec, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_chacha20poly1305_ietf_encrypt_detached( + ciphertext: ByteArray, + mac: ByteArray, + maclen: LongArray?, + message: ByteArray, + messageLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + nsec: ByteArray?, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_chacha20poly1305_ietf_decrypt_detached( + // unsigned char *m, + // unsigned char *nsec, + // const unsigned char *c, + // unsigned long long clen, + // const unsigned char *mac, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_chacha20poly1305_ietf_decrypt_detached( + message: ByteArray, + nsec: ByteArray?, + ciphertext: ByteArray, + ciphertextLength: Long, + mac: ByteArray, + additionalData: ByteArray, + additionalDataLength: Long, + npub: ByteArray, + key: ByteArray + ): Int + + // void crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES]) + fun crypto_aead_chacha20poly1305_ietf_keygen(key: ByteArray) + + // + // ChaCha20Poly1305 + // + + // + // //decrypt + // int crypto_aead_xchacha20poly1305_encrypt( + // unsigned char *c, + // unsigned long long *clen_p, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *nsec, + // const unsigned char *npub, + // const unsigned char *k + // ) + fun crypto_aead_chacha20poly1305_encrypt( + ciphertext: ByteArray, + ciphertextLength: LongArray?, + message: ByteArray, + messageLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + nsec: ByteArray?, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_xchacha20poly1305_decrypt(unsigned char *m, + // unsigned long long *mlen_p, + // unsigned char *nsec, + // const unsigned char *c, + // unsigned long long clen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_chacha20poly1305_decrypt( + message: ByteArray, + messageLength: LongArray?, + nsec: ByteArray?, + ciphertext: ByteArray, + ciphertextLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_chacha20poly1305_encrypt_detached( + // unsigned char *c, + // unsigned char *mac, + // unsigned long long *maclen_p, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *nsec, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_chacha20poly1305_encrypt_detached( + ciphertext: ByteArray, + mac: ByteArray, + maclen: LongArray?, + message: ByteArray, + messageLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + nsec: ByteArray?, + npub: ByteArray, + key: ByteArray + ): Int + + // int crypto_aead_chacha20poly1305_decrypt_detached( + // unsigned char *m, + // unsigned char *nsec, + // const unsigned char *c, + // unsigned long long clen, + // const unsigned char *mac, + // const unsigned char *ad, + // unsigned long long adlen, + // const unsigned char *npub, + // const unsigned char *k) + fun crypto_aead_chacha20poly1305_decrypt_detached( + message: ByteArray, + nsec: ByteArray?, + ciphertext: ByteArray, + ciphertextLength: Long, + mac: ByteArray, + additionalData: ByteArray, + additionalDataLength: Long, + npub: ByteArray, + key: ByteArray + ): Int + + // void crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES]) + fun crypto_aead_chacha20poly1305_keygen(key: ByteArray) + + + // ---- AEAD end ---- + + // ---- Secret stream ----- + + // crypto_secretstream_xchacha20poly1305_headerbytes + fun crypto_secretstream_xchacha20poly1305_headerbytes(): Int + + //encrypt + + // int crypto_secretstream_xchacha20poly1305_init_push + // (crypto_secretstream_xchacha20poly1305_state *state, + // unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES], + // const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) + fun crypto_secretstream_xchacha20poly1305_init_push( + state: SecretStreamXChaCha20Poly1305State, + header: ByteArray, + key: ByteArray + ): Int + + // int crypto_secretstream_xchacha20poly1305_push + // (crypto_secretstream_xchacha20poly1305_state *state, + // unsigned char *c, unsigned long long *clen_p, + // const unsigned char *m, unsigned long long mlen, + // const unsigned char *ad, unsigned long long adlen, unsigned char tag) + fun crypto_secretstream_xchacha20poly1305_push( + state: SecretStreamXChaCha20Poly1305State, + ciphertext: ByteArray, + ciphertextLength: LongArray?, + message: ByteArray, + messageLength: Long, + additionalData: ByteArray, + additionalDataLength: Long, + tag: Byte + ): Int + + // decrypt + + // int crypto_secretstream_xchacha20poly1305_init_pull + // (crypto_secretstream_xchacha20poly1305_state *state, + // const unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES], + // const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) + fun crypto_secretstream_xchacha20poly1305_init_pull( + state: SecretStreamXChaCha20Poly1305State, + header: ByteArray, + key: ByteArray + ): Int + + // int crypto_secretstream_xchacha20poly1305_pull + // (crypto_secretstream_xchacha20poly1305_state *state, + // unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p, + // const unsigned char *c, unsigned long long clen, + // const unsigned char *ad, unsigned long long adlen) + fun crypto_secretstream_xchacha20poly1305_pull( + state: SecretStreamXChaCha20Poly1305State, + message: ByteArray, + messageLength: LongArray?, + tagAddress: ByteArray, + ciphertext: ByteArray, + ciphertextLength: Long, + additionalData: ByteArray, + additionalDataLength: Long + ): Int + + //keygen and rekey + + // void crypto_secretstream_xchacha20poly1305_keygen + // (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]) + fun crypto_secretstream_xchacha20poly1305_keygen(key: ByteArray) + + // void crypto_secretstream_xchacha20poly1305_rekey + // (crypto_secretstream_xchacha20poly1305_state *state) + fun crypto_secretstream_xchacha20poly1305_rekey(state: SecretStreamXChaCha20Poly1305State) + + + // ---- Secret stream end ----- +// +// // ---- SecretBox ---- + + // int crypto_secretbox_detached( + // unsigned char *c, unsigned char *mac, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *n, + // const unsigned char *k) + fun crypto_secretbox_detached( + ciphertext: ByteArray, + mac: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + key: ByteArray + ): Int + + // int crypto_secretbox_easy( + // unsigned char *c, const unsigned char *m, + // unsigned long long mlen, const unsigned char *n, + // const unsigned char *k) + fun crypto_secretbox_easy( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + key: ByteArray + ): Int + + // void crypto_secretbox_keygen(unsigned char k[crypto_secretbox_KEYBYTES]) + fun crypto_secretbox_keygen(key: ByteArray) + + // int crypto_secretbox_open_detached( + // unsigned char *m, + // const unsigned char *c, + // const unsigned char *mac, + // unsigned long long clen, + // const unsigned char *n, + // const unsigned char *k) + fun crypto_secretbox_open_detached( + message: ByteArray, + ciphertext: ByteArray, + mac: ByteArray, + ciphertextLength: Long, + nonce: ByteArray, + key: ByteArray + ): Int + + // int crypto_secretbox_open_easy( + // unsigned char *m, const unsigned char *c, + // unsigned long long clen, const unsigned char *n, + // const unsigned char *k) + fun crypto_secretbox_open_easy( + message: ByteArray, + ciphertext: ByteArray, + ciphertextLength: Long, + nonce: ByteArray, + key: ByteArray + ): Int + + // ---- SecretBox End ---- + + // ---- Auth ---- + + // int crypto_auth(unsigned char *out, const unsigned char *in, + // unsigned long long inlen, const unsigned char *k) + fun crypto_auth( + out: ByteArray, + input: ByteArray, + inputLength: Long, + key: ByteArray + ): Int + + // void crypto_auth_keygen(unsigned char k[crypto_auth_KEYBYTES]) + fun crypto_auth_keygen(key: ByteArray) + + // int crypto_auth_verify(const unsigned char *h, const unsigned char *in, + // unsigned long long inlen, const unsigned char *k) + fun crypto_auth_verify( + hash: ByteArray, + input: ByteArray, + inputLength: Long, + key: ByteArray + ): Int + + //Same params as general variant + fun crypto_auth_hmacsha256( + out: ByteArray, + input: ByteArray, + inputLength: Long, + key: ByteArray + ): Int + + //Same params as general variant + fun crypto_auth_hmacsha256_keygen(key: ByteArray) + + //Same params as general variant + fun crypto_auth_hmacsha256_verify( + hash: ByteArray, + input: ByteArray, + inputLength: Long, + key: ByteArray + ): Int + + //Same params as general variant + fun crypto_auth_hmacsha512( + out: ByteArray, + input: ByteArray, + inputLength: Long, + key: ByteArray + ): Int + + //Same params as general variant + fun crypto_auth_hmacsha512_keygen(key: ByteArray) + + //Same params as general variant + fun crypto_auth_hmacsha512_verify( + hash: ByteArray, + input: ByteArray, + inputLength: Long, + key: ByteArray + ): Int + + // +// // ---- Auth end ---- +// +// // ---- Box ---- +// + // int crypto_box_keypair(unsigned char *pk, unsigned char *sk) + fun crypto_box_keypair(publicKey: ByteArray, secretKey: ByteArray) + + // int crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk, + // const unsigned char *seed) + fun crypto_box_seed_keypair( + publicKey: ByteArray, + secretKey: ByteArray, + seed: ByteArray + ): Int + + // int crypto_box_easy(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, const unsigned char *n, + // const unsigned char *pk, const unsigned char *sk) + fun crypto_box_easy( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + recipientPublicKey: ByteArray, + senderSecretKey: ByteArray + ): Int + + // int crypto_box_open_easy(unsigned char *m, const unsigned char *c, + // unsigned long long clen, const unsigned char *n, + // const unsigned char *pk, const unsigned char *sk) + fun crypto_box_open_easy( + message: ByteArray, + ciphertext: ByteArray, + ciphertextLength: Long, + nonce: ByteArray, + senderPublickKey: ByteArray, + recipientSecretKey: ByteArray + ): Int + + // int crypto_box_detached(unsigned char *c, unsigned char *mac, + // const unsigned char *m, unsigned long long mlen, + // const unsigned char *n, const unsigned char *pk, + // const unsigned char *sk) + fun crypto_box_detached( + ciphertext: ByteArray, + mac: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + recipientPublicKey: ByteArray, + senderSecretKey: ByteArray + ): Int + + // int crypto_box_open_detached( + // unsigned char *m, const unsigned char *c, + // const unsigned char *mac, + // unsigned long long clen, + // const unsigned char *n, + // const unsigned char *pk, + // const unsigned char *sk) + fun crypto_box_open_detached( + message: ByteArray, + ciphertext: ByteArray, + mac: ByteArray, + ciphertextLength: Long, + nonce: ByteArray, + senderPublickKey: ByteArray, + recipientSecretKey: ByteArray + ): Int + + // int crypto_box_beforenm(unsigned char *k, const unsigned char *pk, + // const unsigned char *sk) + fun crypto_box_beforenm( + sessionKey: ByteArray, + publicKey: ByteArray, + secretKey: ByteArray + ): Int + + // int crypto_box_easy_afternm(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, const unsigned char *n, + // const unsigned char *k) + fun crypto_box_easy_afternm( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + sessionKey: ByteArray + ): Int + + // int crypto_box_open_easy_afternm(unsigned char *m, const unsigned char *c, + // unsigned long long clen, const unsigned char *n, + // const unsigned char *k) + fun crypto_box_open_easy_afternm( + message: ByteArray, + ciphertext: ByteArray, + ciphertextLength: Long, + nonce: ByteArray, + sessionKey: ByteArray + ): Int + + // int crypto_box_seal(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, const unsigned char *pk) + fun crypto_box_seal( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + recipientPublicKey: ByteArray + ): Int + + + // int crypto_box_seal_open(unsigned char *m, const unsigned char *c, + // unsigned long long clen, + // const unsigned char *pk, const unsigned char *sk) + fun crypto_box_seal_open( + message: ByteArray, + ciphertext: ByteArray, + ciphertextLength: Long, + senderPublickKey: ByteArray, + recipientSecretKey: ByteArray + ): Int +// +// // ---- Box end ---- +// +// // ---- Sign start ---- + + // int crypto_sign( + // unsigned char *sm, unsigned long long *smlen_p, + // const unsigned char *m, unsigned long long mlen, + // const unsigned char *sk) + fun crypto_sign( + signedMessage: ByteArray, + signedMessageLength: LongArray?, + message: ByteArray, + messageLength: Long, + secretKey: ByteArray + ): Int + + // int crypto_sign_open( + // unsigned char *m, unsigned long long *mlen_p, + // const unsigned char *sm, unsigned long long smlen, + // const unsigned char *pk) + fun crypto_sign_open( + message: ByteArray, + messageLength: LongArray?, + signedMessage: ByteArray, + signedMessageLength: Long, + publicKey: ByteArray + ): Int + + // int crypto_sign_detached( + // unsigned char *sig, unsigned long long *siglen_p, + // const unsigned char *m, unsigned long long mlen, + // const unsigned char *sk) + fun crypto_sign_detached( + signature: ByteArray, + signatureLength: LongArray?, + message: ByteArray, + messageLength: Long, + secretKey: ByteArray + ): Int + + // int crypto_sign_verify_detached( + // const unsigned char *sig, + // const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *pk) + fun crypto_sign_verify_detached( + signature: ByteArray, + message: ByteArray, + messageLength: Long, + publicKey: ByteArray + ): Int + + // int crypto_sign_ed25519_pk_to_curve25519( + // unsigned char *curve25519_pk, + // const unsigned char *ed25519_pk) + fun crypto_sign_ed25519_pk_to_curve25519( + curve25519PublicKey: ByteArray, + ed25519PublicKey: ByteArray + ): Int + + // int crypto_sign_ed25519_sk_to_curve25519(unsigned char *curve25519_sk, + // const unsigned char *ed25519_sk) + fun crypto_sign_ed25519_sk_to_curve25519( + curve25519SecretKey: ByteArray, + ed25519SecretKey: ByteArray + ): Int + + // int crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk) + fun crypto_sign_ed25519_sk_to_pk( + ed25519PublicKey: ByteArray, + ed25519SecretKey: ByteArray + ): Int + + // int crypto_sign_ed25519_sk_to_seed(unsigned char *seed, + // const unsigned char *sk) + fun crypto_sign_ed25519_sk_to_seed( + seed: ByteArray, + ed25519SecretKey: ByteArray + ): Int + + // int crypto_sign_init(crypto_sign_state *state); + fun crypto_sign_init(state: Ed25519SignatureState) + + // int crypto_sign_update(crypto_sign_state *state, + // const unsigned char *m, unsigned long long mlen) + fun crypto_sign_update( + state: Ed25519SignatureState, + message: ByteArray, + messageLength: Long + ): Int + + // int crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig, + // unsigned long long *siglen_p, + // const unsigned char *sk) + fun crypto_sign_final_create( + state: Ed25519SignatureState, + signature: ByteArray, + signatureLength: LongArray?, + secretKey: ByteArray + ): Int + + // int crypto_sign_final_verify(crypto_sign_state *state, const unsigned char *sig, + // const unsigned char *pk) + fun crypto_sign_final_verify( + state: Ed25519SignatureState, + signature: ByteArray, + publicKey: ByteArray + ): Int + + // int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) + fun crypto_sign_keypair( + publicKey: ByteArray, secretKey: ByteArray + ) + + // int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, + // const unsigned char *seed) + fun crypto_sign_seed_keypair( + publicKey: ByteArray, + secretKey: ByteArray, + seed: ByteArray + ): Int + + +// // ---- Sign end ---- +// +// + + +// // ---- KDF ---- +// + + // int crypto_kdf_derive_from_key(unsigned char *subkey, size_t subkey_len, + // uint64_t subkey_id, + // const char ctx[crypto_kdf_CONTEXTBYTES], + // const unsigned char key[crypto_kdf_KEYBYTES]) + fun crypto_kdf_derive_from_key( + subkey: ByteArray, + subkeyLength: Int, + subkeyId: Long, + context: ByteArray, + key: ByteArray + ) + + // void crypto_kdf_keygen(unsigned char k[crypto_kdf_KEYBYTES]) + fun crypto_kdf_keygen( + key: ByteArray + ) +// +// // ---- KDF end ----- +// + + + // // ---- Password hashing ---- +// + // int crypto_pwhash(unsigned char * const out, unsigned long long outlen, + // const char * const passwd, unsigned long long passwdlen, + // const unsigned char * const salt, + // unsigned long long opslimit, size_t memlimit, int alg) + fun crypto_pwhash( + output: ByteArray, + outputLength: Long, + password: String, + passwordLength: Long, + salt: ByteArray, + opslimit: Long, + memlimit: Long, + algorithm : Int + ) : Int + + // int crypto_pwhash_str(char out[crypto_pwhash_STRBYTES], + // const char * const passwd, unsigned long long passwdlen, + // unsigned long long opslimit, size_t memlimit) + fun crypto_pwhash_str( + output: ByteArray, + password: String, + passwordLength: Long, + opslimit: Long, + memlimit: Long + ) : Int + + // int crypto_pwhash_str_needs_rehash(const char str[crypto_pwhash_STRBYTES], + // unsigned long long opslimit, size_t memlimit) + fun crypto_pwhash_str_needs_rehash( + output: ByteArray, + opslimit: Long, + memlimit: Long + ) : Int + // int crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES], + // const char * const passwd, + // unsigned long long passwdlen) + fun crypto_pwhash_str_verify( + hash: ByteArray, + password: String, + passwordLength: Long + ) : Int + +// +// // ---- Password hashing end ---- +// + + + +// // ---- Key exchange ---- + + + // int crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], + // unsigned char sk[crypto_kx_SECRETKEYBYTES]) + fun crypto_kx_keypair( + publicKey: ByteArray, + secretKey: ByteArray + ) + + + // int crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES], + // unsigned char sk[crypto_kx_SECRETKEYBYTES], + // const unsigned char seed[crypto_kx_SEEDBYTES]) + fun crypto_kx_seed_keypair( + publicKey: ByteArray, + secretKey: ByteArray, + seed: ByteArray + ) + // int crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], + // unsigned char tx[crypto_kx_SESSIONKEYBYTES], + // const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES], + // const unsigned char client_sk[crypto_kx_SECRETKEYBYTES], + // const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES]) + fun crypto_kx_client_session_keys( + receiveKey : ByteArray, + sendKey: ByteArray, + clientPublicKey: ByteArray, + clientSecretKey: ByteArray, + serverPublicKey: ByteArray + ) + // int crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES], + // unsigned char tx[crypto_kx_SESSIONKEYBYTES], + // const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES], + // const unsigned char server_sk[crypto_kx_SECRETKEYBYTES], + // const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES]) + fun crypto_kx_server_session_keys( + receiveKey: ByteArray, + sendKey: ByteArray, + serverPublicKey: ByteArray, + serverSecretKey: ByteArray, + clientPublicKey: ByteArray + ) + +// +// // ---- Key exchange end ---- +// +// // -- Stream ---- + + // int crypto_stream_chacha20(unsigned char *c, unsigned long long clen, + // const unsigned char *n, const unsigned char *k) + fun crypto_stream_chacha20( + stream: ByteArray, + streamLength: Long, + nonce: ByteArray, + key: ByteArray + ) : Int + // int crypto_stream_chacha20_xor(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, const unsigned char *n, + // const unsigned char *k) + fun crypto_stream_chacha20_xor( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + key: ByteArray + ) : Int + // int crypto_stream_chacha20_xor_ic(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *n, uint64_t ic, + // const unsigned char *k) + fun crypto_stream_chacha20_xor_ic( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + initialCounter : Long, + key: ByteArray + ) : Int + + // int crypto_stream_chacha20_ietf(unsigned char *c, unsigned long long clen, + // const unsigned char *n, const unsigned char *k) + fun crypto_stream_chacha20_ietf( + stream: ByteArray, + streamLength: Long, + nonce: ByteArray, + key: ByteArray + ) : Int + + // int crypto_stream_chacha20_ietf_xor(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, const unsigned char *n, + // const unsigned char *k) + fun crypto_stream_chacha20_ietf_xor( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + key: ByteArray + ) : Int + + // int crypto_stream_chacha20_ietf_xor_ic(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *n, uint32_t ic, + // const unsigned char *k) + fun crypto_stream_chacha20_ietf_xor_ic( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + initialCounter : Long, + key: ByteArray + ) : Int + + // void crypto_stream_chacha20_keygen(unsigned char k[crypto_stream_chacha20_KEYBYTES]) + fun crypto_stream_chacha20_keygen(key: ByteArray) + + // int crypto_stream_xchacha20(unsigned char *c, unsigned long long clen, + // const unsigned char *n, const unsigned char *k) + fun crypto_stream_xchacha20( + stream: ByteArray, + streamLength: Long, + nonce: ByteArray, + key: ByteArray + ) : Int + + // int crypto_stream_xchacha20_xor(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, const unsigned char *n, + // const unsigned char *k) + fun crypto_stream_xchacha20_xor( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + key: ByteArray + ) : Int + + // int crypto_stream_xchacha20_xor_ic(unsigned char *c, const unsigned char *m, + // unsigned long long mlen, + // const unsigned char *n, uint64_t ic, + // const unsigned char *k) + fun crypto_stream_xchacha20_xor_ic( + ciphertext: ByteArray, + message: ByteArray, + messageLength: Long, + nonce: ByteArray, + initialCounter : Long, + key: ByteArray + ) : Int + // void crypto_stream_xchacha20_keygen(unsigned char k[crypto_stream_xchacha20_KEYBYTES]) + fun crypto_stream_xchacha20_keygen(key: ByteArray) + + +// +// // ---- Stream end ---- +// +// // ---- Scalar multiplication ---- +// + // int crypto_scalarmult(unsigned char *q, const unsigned char *n, + // const unsigned char *p) + fun crypto_scalarmult(q: ByteArray, n: ByteArray, p: ByteArray) + // int crypto_scalarmult_base(unsigned char *q, const unsigned char *n) + fun crypto_scalarmult_base(q: ByteArray, b: ByteArray) +// +// // ---- Scalar multiplication end ---- +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/LibsodiumInitializer.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/LibsodiumInitializer.kt index 0f72b4b..abe7dbe 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/LibsodiumInitializer.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/LibsodiumInitializer.kt @@ -1,19 +1,59 @@ package com.ionspin.kotlin.crypto +import co.libly.resourceloader.FileLoader +import com.sun.jna.Native +import com.sun.jna.Platform +import java.io.File +import java.lang.RuntimeException + /** * Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 02/Aug/2020 */ actual object LibsodiumInitializer { private var isPlatformInitialized = false - lateinit var sodium : SodiumWrapper + private fun loadLibrary() : JnaLibsodiumInterface { + val libraryFile = when { + Platform.isMac() -> { + FileLoader.get().load("dynamic-macos-x86-64.dylib", Any::class.java) + } + Platform.isLinux() -> { + FileLoader.get().load("dynamic-linux-x86-64-libsodium.so", Any::class.java) + } + Platform.isWindows() -> { + FileLoader.get().load("dynamic-msvc-x86-64-libsodium.dll", Any::class.java) + } + Platform.isAndroid() -> { + when { + Platform.is64Bit() -> { + File("irrelevant") + } + else -> throw RuntimeException("Unsupported platform") + } + } + else -> throw RuntimeException("Unknown platform") + + } + + + val library = if (Platform.isAndroid()) { + Native.load("sodium", JnaLibsodiumInterface::class.java) as JnaLibsodiumInterface + } else { + Native.load(libraryFile.absolutePath, JnaLibsodiumInterface::class.java) as JnaLibsodiumInterface + } + + return library + } + + + lateinit var sodiumJna : JnaLibsodiumInterface actual suspend fun initialize() { - sodium = SodiumWrapper() + sodiumJna = loadLibrary() isPlatformInitialized = true } actual fun initializeWithCallback(done: () -> Unit) { - sodium = SodiumWrapper() + sodiumJna = loadLibrary() isPlatformInitialized = true done() } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/TmpAccessor.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/TmpAccessor.kt new file mode 100644 index 0000000..0e25ead --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/TmpAccessor.kt @@ -0,0 +1,10 @@ +package com.ionspin.kotlin.crypto + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Feb-2021 + */ +object TmpAccessor { + fun getVersion() : String = LibsodiumInitializer.sodiumJna.sodium_version_string() +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedData.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedData.kt index 523fb9a..17b276e 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedData.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedData.kt @@ -1,6 +1,6 @@ package com.ionspin.kotlin.crypto.aead -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object AuthenticatedEncryptionWithAssociatedData { @@ -14,7 +14,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val ciphertext = UByteArray(message.size + crypto_aead_xchacha20poly1305_ietf_ABYTES) - sodium.crypto_aead_xchacha20poly1305_ietf_encrypt( + sodiumJna.crypto_aead_xchacha20poly1305_ietf_encrypt( ciphertext.asByteArray(), null, message.asByteArray(), @@ -35,7 +35,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val message = UByteArray(ciphertextAndTag.size - crypto_aead_xchacha20poly1305_ietf_ABYTES) - val validationResult = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt( + val validationResult = sodiumJna.crypto_aead_xchacha20poly1305_ietf_decrypt( message.asByteArray(), null, null, @@ -60,7 +60,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { ): AeadEncryptedDataAndTag { val ciphertext = UByteArray(message.size) val authenticationTag = UByteArray(crypto_aead_xchacha20poly1305_ietf_ABYTES) - sodium.crypto_aead_xchacha20poly1305_ietf_encrypt_detached( + sodiumJna.crypto_aead_xchacha20poly1305_ietf_encrypt_detached( ciphertext.asByteArray(), authenticationTag.asByteArray(), null, @@ -83,7 +83,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val message = UByteArray(ciphertext.size) - val validationResult = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt_detached( + val validationResult = sodiumJna.crypto_aead_xchacha20poly1305_ietf_decrypt_detached( message.asByteArray(), null, ciphertext.asByteArray(), @@ -107,7 +107,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val ciphertext = UByteArray(message.size + crypto_aead_chacha20poly1305_ietf_ABYTES) - sodium.crypto_aead_chacha20poly1305_ietf_encrypt( + sodiumJna.crypto_aead_chacha20poly1305_ietf_encrypt( ciphertext.asByteArray(), null, message.asByteArray(), @@ -128,7 +128,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val message = UByteArray(ciphertextAndTag.size - crypto_aead_chacha20poly1305_ietf_ABYTES) - val validationResult = sodium.crypto_aead_chacha20poly1305_ietf_decrypt( + val validationResult = sodiumJna.crypto_aead_chacha20poly1305_ietf_decrypt( message.asByteArray(), null, null, @@ -153,7 +153,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { ): AeadEncryptedDataAndTag { val ciphertext = UByteArray(message.size) val authenticationTag = UByteArray(crypto_aead_chacha20poly1305_ietf_ABYTES) - sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached( + sodiumJna.crypto_aead_chacha20poly1305_ietf_encrypt_detached( ciphertext.asByteArray(), authenticationTag.asByteArray(), null, @@ -176,7 +176,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val message = UByteArray(ciphertext.size) - val validationResult = sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached( + val validationResult = sodiumJna.crypto_aead_chacha20poly1305_ietf_decrypt_detached( message.asByteArray(), null, ciphertext.asByteArray(), @@ -200,7 +200,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val ciphertext = UByteArray(message.size + crypto_aead_chacha20poly1305_ABYTES) - sodium.crypto_aead_chacha20poly1305_encrypt( + sodiumJna.crypto_aead_chacha20poly1305_encrypt( ciphertext.asByteArray(), null, message.asByteArray(), @@ -221,7 +221,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val message = UByteArray(ciphertextAndTag.size - crypto_aead_chacha20poly1305_ABYTES) - val validationResult = sodium.crypto_aead_chacha20poly1305_decrypt( + val validationResult = sodiumJna.crypto_aead_chacha20poly1305_decrypt( message.asByteArray(), null, null, @@ -246,7 +246,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { ): AeadEncryptedDataAndTag { val ciphertext = UByteArray(message.size) val authenticationTag = UByteArray(crypto_aead_chacha20poly1305_ABYTES) - sodium.crypto_aead_chacha20poly1305_encrypt_detached( + sodiumJna.crypto_aead_chacha20poly1305_encrypt_detached( ciphertext.asByteArray(), authenticationTag.asByteArray(), null, @@ -269,7 +269,7 @@ actual object AuthenticatedEncryptionWithAssociatedData { key: UByteArray ): UByteArray { val message = UByteArray(ciphertext.size) - val validationResult = sodium.crypto_aead_chacha20poly1305_decrypt_detached( + val validationResult = sodiumJna.crypto_aead_chacha20poly1305_decrypt_detached( message.asByteArray(), null, ciphertext.asByteArray(), @@ -288,19 +288,19 @@ actual object AuthenticatedEncryptionWithAssociatedData { actual fun xChaCha20Poly1305IetfKeygen(): UByteArray { val generatedKey = UByteArray(crypto_aead_xchacha20poly1305_ietf_KEYBYTES) - sodium.crypto_aead_xchacha20poly1305_ietf_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_aead_xchacha20poly1305_ietf_keygen(generatedKey.asByteArray()) return generatedKey } actual fun chaCha20Poly1305IetfKeygen(): UByteArray { val generatedKey = UByteArray(crypto_aead_chacha20poly1305_ietf_KEYBYTES) - sodium.crypto_aead_chacha20poly1305_ietf_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_aead_chacha20poly1305_ietf_keygen(generatedKey.asByteArray()) return generatedKey } actual fun chaCha20Poly1305Keygen(): UByteArray { val generatedKey = UByteArray(crypto_aead_chacha20poly1305_KEYBYTES) - sodium.crypto_aead_chacha20poly1305_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_aead_chacha20poly1305_keygen(generatedKey.asByteArray()) return generatedKey } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/auth/Auth.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/auth/Auth.kt index e6b6207..39f7d58 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/auth/Auth.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/auth/Auth.kt @@ -1,17 +1,17 @@ package com.ionspin.kotlin.crypto.auth -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object Auth { actual fun authKeygen(): UByteArray { val generatedKey = UByteArray(crypto_auth_KEYBYTES) - sodium.crypto_auth_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_auth_keygen(generatedKey.asByteArray()) return generatedKey } actual fun auth(message: UByteArray, key: UByteArray): UByteArray { val mac = UByteArray(crypto_auth_BYTES) - sodium.crypto_auth( + sodiumJna.crypto_auth( mac.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -21,7 +21,7 @@ actual object Auth { } actual fun authVerify(tag: UByteArray, message: UByteArray, key: UByteArray): Boolean { - return sodium.crypto_auth_verify( + return sodiumJna.crypto_auth_verify( tag.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -31,13 +31,13 @@ actual object Auth { actual fun authHmacSha256Keygen(): UByteArray { val generatedKey = UByteArray(crypto_auth_hmacsha256_KEYBYTES) - sodium.crypto_auth_hmacsha256_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_auth_hmacsha256_keygen(generatedKey.asByteArray()) return generatedKey } actual fun authHmacSha256(message: UByteArray, key: UByteArray): UByteArray { val mac = UByteArray(crypto_auth_hmacsha256_BYTES) - sodium.crypto_auth_hmacsha256( + sodiumJna.crypto_auth_hmacsha256( mac.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -51,7 +51,7 @@ actual object Auth { message: UByteArray, key: UByteArray ): Boolean { - return sodium.crypto_auth_hmacsha256_verify( + return sodiumJna.crypto_auth_hmacsha256_verify( tag.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -61,13 +61,13 @@ actual object Auth { actual fun authHmacSha512Keygen(): UByteArray { val generatedKey = UByteArray(crypto_auth_hmacsha512_KEYBYTES) - sodium.crypto_auth_hmacsha512_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_auth_hmacsha512_keygen(generatedKey.asByteArray()) return generatedKey } actual fun authHmacSha512(message: UByteArray, key: UByteArray): UByteArray { val mac = UByteArray(crypto_auth_hmacsha512_BYTES) - sodium.crypto_auth_hmacsha512( + sodiumJna.crypto_auth_hmacsha512( mac.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -81,7 +81,7 @@ actual object Auth { message: UByteArray, key: UByteArray ): Boolean { - return sodium.crypto_auth_hmacsha512_verify( + return sodiumJna.crypto_auth_hmacsha512_verify( tag.asByteArray(), message.asByteArray(), message.size.toLong(), diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/box/Box.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/box/Box.kt index 27b8be7..8f1f990 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/box/Box.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/box/Box.kt @@ -1,6 +1,6 @@ package com.ionspin.kotlin.crypto.box -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object Box { /** @@ -11,7 +11,7 @@ actual object Box { actual fun keypair(): BoxKeyPair { val publicKey = UByteArray(crypto_box_PUBLICKEYBYTES) val secretKey = UByteArray(crypto_box_SECRETKEYBYTES) - sodium.crypto_box_keypair(publicKey.asByteArray(), secretKey.asByteArray()) + sodiumJna.crypto_box_keypair(publicKey.asByteArray(), secretKey.asByteArray()) return BoxKeyPair(publicKey, secretKey) } @@ -21,7 +21,7 @@ actual object Box { actual fun seedKeypair(seed: UByteArray): BoxKeyPair { val publicKey = UByteArray(crypto_box_PUBLICKEYBYTES) val secretKey = UByteArray(crypto_box_SECRETKEYBYTES) - sodium.crypto_box_seed_keypair(publicKey.asByteArray(), secretKey.asByteArray(), seed.asByteArray()) + sodiumJna.crypto_box_seed_keypair(publicKey.asByteArray(), secretKey.asByteArray(), seed.asByteArray()) return BoxKeyPair(publicKey, secretKey) } @@ -39,7 +39,7 @@ actual object Box { sendersSecretKey: UByteArray ): UByteArray { val ciphertext = UByteArray(message.size + crypto_box_MACBYTES) - sodium.crypto_box_easy( + sodiumJna.crypto_box_easy( ciphertext.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -64,7 +64,7 @@ actual object Box { recipientsSecretKey: UByteArray ): UByteArray { val message = UByteArray(ciphertext.size - crypto_box_MACBYTES) - val validationResult = sodium.crypto_box_open_easy( + val validationResult = sodiumJna.crypto_box_open_easy( message.asByteArray(), ciphertext.asByteArray(), ciphertext.size.toLong(), @@ -85,7 +85,7 @@ actual object Box { */ actual fun beforeNM(publicKey: UByteArray, secretKey: UByteArray): UByteArray { val sessionKey = UByteArray(crypto_box_BEFORENMBYTES) - sodium.crypto_box_beforenm(sessionKey.asByteArray(), publicKey.asByteArray(), secretKey.asByteArray()) + sodiumJna.crypto_box_beforenm(sessionKey.asByteArray(), publicKey.asByteArray(), secretKey.asByteArray()) return sessionKey } @@ -99,7 +99,7 @@ actual object Box { ): UByteArray { val ciphertext = UByteArray(message.size + crypto_box_MACBYTES) - sodium.crypto_box_easy_afternm( + sodiumJna.crypto_box_easy_afternm( ciphertext.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -119,7 +119,7 @@ actual object Box { precomputedKey: UByteArray ): UByteArray { val message = UByteArray(ciphertext.size - crypto_box_MACBYTES) - val validationResult = sodium.crypto_box_open_easy_afternm( + val validationResult = sodiumJna.crypto_box_open_easy_afternm( message.asByteArray(), ciphertext.asByteArray(), ciphertext.size.toLong(), @@ -149,7 +149,7 @@ actual object Box { val ciphertext = UByteArray(message.size) val tag = UByteArray(crypto_box_MACBYTES) - sodium.crypto_box_detached( + sodiumJna.crypto_box_detached( ciphertext.asByteArray(), tag.asByteArray(), message.asByteArray(), @@ -177,7 +177,7 @@ actual object Box { ): UByteArray { val message = UByteArray(ciphertext.size) - val validationResult = sodium.crypto_box_open_detached( + val validationResult = sodiumJna.crypto_box_open_detached( message.asByteArray(), ciphertext.asByteArray(), tag.asByteArray(), @@ -196,7 +196,7 @@ actual object Box { actual fun seal(message: UByteArray, recipientsPublicKey: UByteArray): UByteArray { val ciphertextWithPublicKey = UByteArray(message.size + crypto_box_SEALBYTES) - sodium.crypto_box_seal( + sodiumJna.crypto_box_seal( ciphertextWithPublicKey.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -207,7 +207,7 @@ actual object Box { actual fun sealOpen(ciphertext: UByteArray, recipientsPublicKey: UByteArray, recipientsSecretKey: UByteArray): UByteArray { val message = UByteArray(ciphertext.size - crypto_box_SEALBYTES) - val validationResult = sodium.crypto_box_seal_open( + val validationResult = sodiumJna.crypto_box_seal_open( message.asByteArray(), ciphertext.asByteArray(), ciphertext.size.toLong(), @@ -223,4 +223,4 @@ actual object Box { } -} \ No newline at end of file +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHash.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHashJvm.kt similarity index 62% rename from multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHash.kt rename to multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHashJvm.kt index f674d82..d540452 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHash.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHashJvm.kt @@ -1,13 +1,14 @@ package com.ionspin.kotlin.crypto.generichash -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.Blake2bState +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna /** * Created by Ugljesa Jovanovic * ugljesa.jovanovic@ionspin.com * on 21-Aug-2020 */ -actual class GenericHashStateInternal(internal val data: ByteArray) +actual typealias GenericHashStateInternal = Blake2bState actual object GenericHash { actual fun genericHash( @@ -16,12 +17,12 @@ actual object GenericHash { key: UByteArray? ): UByteArray { val hash = UByteArray(requestedHashLength) - sodium.crypto_generichash( + sodiumJna.crypto_generichash( hash.asByteArray(), requestedHashLength, message.asByteArray(), message.size.toLong(), - key?.asByteArray(), + key?.asByteArray() ?: ByteArray(0), (key?.size ?: 0) ) return hash @@ -31,8 +32,8 @@ actual object GenericHash { requestedHashLength: Int, key: UByteArray? ): GenericHashState { - val state = GenericHashStateInternal(ByteArray(sodium.crypto_generichash_statebytes())) - sodium.crypto_generichash_init(state.data, key?.asByteArray(), key?.size ?: 0, requestedHashLength) + val state = GenericHashStateInternal() + sodiumJna.crypto_generichash_init(state, key?.asByteArray() ?: ByteArray(0), key?.size ?: 0, requestedHashLength) return GenericHashState(requestedHashLength, state) } @@ -40,18 +41,18 @@ actual object GenericHash { state: GenericHashState, messagePart: UByteArray ) { - sodium.crypto_generichash_update(state.internalState.data, messagePart.asByteArray(), messagePart.size.toLong()) + sodiumJna.crypto_generichash_update(state.internalState, messagePart.asByteArray(), messagePart.size.toLong()) } actual fun genericHashFinal(state: GenericHashState): UByteArray { val hashResult = ByteArray(state.hashLength) - sodium.crypto_generichash_final(state.internalState.data, hashResult, state.hashLength) + sodiumJna.crypto_generichash_final(state.internalState, hashResult, state.hashLength) return hashResult.asUByteArray() } actual fun genericHashKeygen(): UByteArray { val generatedKey = UByteArray(crypto_generichash_BYTES) - sodium.crypto_generichash_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_generichash_keygen(generatedKey.asByteArray()) return generatedKey } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/HashJvm.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/HashJvm.kt index cdaf573..283cdc8 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/HashJvm.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/HashJvm.kt @@ -1,54 +1,55 @@ package com.ionspin.kotlin.crypto.hash -import com.goterl.lazycode.lazysodium.interfaces.Hash -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.Hash256State +import com.ionspin.kotlin.crypto.Hash512State +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna -actual typealias Sha256State = Hash.State256 -actual typealias Sha512State = Hash.State512 +actual typealias Sha256State = Hash256State +actual typealias Sha512State = Hash512State actual object Hash { actual fun sha256(data: UByteArray): UByteArray { val resultHash = UByteArray(crypto_hash_sha256_BYTES) - sodium.crypto_hash_sha256(resultHash.asByteArray(), data.asByteArray(), data.size.toLong()) + sodiumJna.crypto_hash_sha256(resultHash.asByteArray(), data.asByteArray(), data.size.toLong()) return resultHash } actual fun sha256Init(): Sha256State { - val state = Hash.State256() - sodium.crypto_hash_sha256_init(state) + val state = Hash256State() + sodiumJna.crypto_hash_sha256_init(state) return state } actual fun sha256Update(state: Sha256State, data: UByteArray) { - sodium.crypto_hash_sha256_update(state, data.asByteArray(), data.size.toLong()) + sodiumJna.crypto_hash_sha256_update(state, data.asByteArray(), data.size.toLong()) } actual fun sha256Final(state: Sha256State): UByteArray { val resultHash = UByteArray(crypto_hash_sha256_BYTES) - sodium.crypto_hash_sha256_final(state, resultHash.asByteArray()) + sodiumJna.crypto_hash_sha256_final(state, resultHash.asByteArray()) return resultHash } actual fun sha512(data: UByteArray): UByteArray { val resultHash = UByteArray(crypto_hash_sha512_BYTES) - sodium.crypto_hash_sha512(resultHash.asByteArray(), data.asByteArray(), data.size.toLong()) + sodiumJna.crypto_hash_sha512(resultHash.asByteArray(), data.asByteArray(), data.size.toLong()) return resultHash } actual fun sha512Init(): Sha512State { - val state = Hash.State512() - sodium.crypto_hash_sha512_init(state) + val state = Hash512State() + sodiumJna.crypto_hash_sha512_init(state) return state } actual fun sha512Update(state: Sha512State, data: UByteArray) { - sodium.crypto_hash_sha512_update(state, data.asByteArray(), data.size.toLong()) + sodiumJna.crypto_hash_sha512_update(state, data.asByteArray(), data.size.toLong()) } actual fun sha512Final(state: Sha512State): UByteArray { val resultHash = UByteArray(crypto_hash_sha512_BYTES) - sodium.crypto_hash_sha512_final(state, resultHash.asByteArray()) + sodiumJna.crypto_hash_sha512_final(state, resultHash.asByteArray()) return resultHash } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/kdf/Kdf.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/kdf/Kdf.kt index 7df70a6..8a66305 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/kdf/Kdf.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/kdf/Kdf.kt @@ -1,6 +1,6 @@ package com.ionspin.kotlin.crypto.kdf -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object Kdf { /** @@ -26,7 +26,7 @@ actual object Kdf { val subkey = UByteArray(subkeyLength) val contextEncoded = context.encodeToByteArray() - sodium.crypto_kdf_derive_from_key( + sodiumJna.crypto_kdf_derive_from_key( subkey.asByteArray(), subkeyLength, subkeyId.toLong(), @@ -42,8 +42,8 @@ actual object Kdf { */ actual fun keygen(): UByteArray { val masterKey = UByteArray(crypto_kdf_KEYBYTES) - sodium.crypto_kdf_keygen(masterKey.asByteArray()) + sodiumJna.crypto_kdf_keygen(masterKey.asByteArray()) return masterKey } -} \ No newline at end of file +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/keyexchange/KeyExchange.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/keyexchange/KeyExchange.kt index e140bc2..5bcc890 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/keyexchange/KeyExchange.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/keyexchange/KeyExchange.kt @@ -1,13 +1,13 @@ package com.ionspin.kotlin.crypto.keyexchange -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object KeyExchange { actual fun clientSessionKeys(clientPublicKey: UByteArray, clientSecretKey: UByteArray, serverPublicKey: UByteArray) : KeyExchangeSessionKeyPair { val receiveKey = UByteArray(crypto_kx_SESSIONKEYBYTES) val sendKey = UByteArray(crypto_kx_SESSIONKEYBYTES) - sodium.crypto_kx_client_session_keys( + sodiumJna.crypto_kx_client_session_keys( receiveKey.asByteArray(), sendKey.asByteArray(), clientPublicKey.asByteArray(), @@ -25,7 +25,7 @@ actual object KeyExchange { val secretKey = UByteArray(crypto_kx_SECRETKEYBYTES) - sodium.crypto_kx_keypair(publicKey.asByteArray(), secretKey.asByteArray()) + sodiumJna.crypto_kx_keypair(publicKey.asByteArray(), secretKey.asByteArray()) return KeyExchangeKeyPair(publicKey, secretKey) @@ -35,7 +35,7 @@ actual object KeyExchange { val publicKey = UByteArray(crypto_kx_PUBLICKEYBYTES) val secretKey = UByteArray(crypto_kx_SECRETKEYBYTES) - sodium.crypto_kx_seed_keypair(publicKey.asByteArray(), secretKey.asByteArray(), seed.asByteArray()) + sodiumJna.crypto_kx_seed_keypair(publicKey.asByteArray(), secretKey.asByteArray(), seed.asByteArray()) return KeyExchangeKeyPair(publicKey, secretKey) } @@ -44,7 +44,7 @@ actual object KeyExchange { val receiveKey = UByteArray(crypto_kx_SESSIONKEYBYTES) val sendKey = UByteArray(crypto_kx_SESSIONKEYBYTES) - sodium.crypto_kx_server_session_keys( + sodiumJna.crypto_kx_server_session_keys( receiveKey.asByteArray(), sendKey.asByteArray(), serverPublicKey.asByteArray(), diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/pwhash/PasswordHash.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/pwhash/PasswordHash.kt index 93999ca..36aabce 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/pwhash/PasswordHash.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/pwhash/PasswordHash.kt @@ -1,6 +1,6 @@ package com.ionspin.kotlin.crypto.pwhash -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna import com.sun.jna.NativeLong actual object PasswordHash { @@ -10,7 +10,7 @@ actual object PasswordHash { * PASSWD_MIN and crypto_pwhash_PASSWD_MAX. outlen should be at least crypto_pwhash_BYTES_MIN = 16 (128 bits) and * at most crypto_pwhash_BYTES_MAX. * - * See https://libsodium.gitbook.io/doc/password_hashing/default_phf for more details + * See https://libsodiumJna.gitbook.io/doc/password_hashing/default_phf for more details */ actual fun pwhash( outputLength: Int, @@ -22,14 +22,14 @@ actual object PasswordHash { ): UByteArray { val hashedPassword = UByteArray(outputLength) - sodium.crypto_pwhash( + sodiumJna.crypto_pwhash( hashedPassword.asByteArray(), outputLength.toLong(), - password.encodeToByteArray(), + password, password.length.toLong(), salt.asByteArray(), opsLimit.toLong(), - NativeLong(memLimit.toLong()), + memLimit.toLong(), algorithm ) @@ -48,12 +48,12 @@ actual object PasswordHash { */ actual fun str(password: String, opslimit: ULong, memlimit: Int): UByteArray { val output = ByteArray(crypto_pwhash_STRBYTES) - sodium.crypto_pwhash_str( + sodiumJna.crypto_pwhash_str( output, - password.encodeToByteArray(), + password, password.length.toLong(), opslimit.toLong(), - NativeLong(memlimit.toLong()) + memlimit.toLong() ) return output.asUByteArray() } @@ -69,10 +69,10 @@ actual object PasswordHash { opslimit: ULong, memlimit: Int ): Int { - return sodium.crypto_pwhash_str_needs_rehash( + return sodiumJna.crypto_pwhash_str_needs_rehash( passwordHash.asByteArray(), opslimit.toLong(), - NativeLong(memlimit.toLong()) + memlimit.toLong() ) } @@ -82,9 +82,9 @@ actual object PasswordHash { * It returns 0 if the verification succeeds, and -1 on error. */ actual fun strVerify(passwordHash: UByteArray, password: String): Boolean { - val result = sodium.crypto_pwhash_str_verify( + val result = sodiumJna.crypto_pwhash_str_verify( passwordHash.asByteArray(), - password.encodeToByteArray(), + password, password.length.toLong() ) diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt index b936a28..54e4710 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt @@ -1,6 +1,6 @@ package com.ionspin.kotlin.crypto.scalarmult -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object ScalarMultiplication { /** @@ -18,7 +18,7 @@ actual object ScalarMultiplication { actual fun scalarMultiplication(secretKeyN: UByteArray, publicKeyP: UByteArray): UByteArray { val result = UByteArray(crypto_scalarmult_BYTES) - sodium.crypto_scalarmult(result.asByteArray(), secretKeyN.asByteArray(), publicKeyP.asByteArray()) + sodiumJna.crypto_scalarmult(result.asByteArray(), secretKeyN.asByteArray(), publicKeyP.asByteArray()) return result @@ -35,7 +35,7 @@ actual object ScalarMultiplication { ): UByteArray { val result = UByteArray(crypto_scalarmult_BYTES) - sodium.crypto_scalarmult_base(result.asByteArray(), secretKeyN.asByteArray()) + sodiumJna.crypto_scalarmult_base(result.asByteArray(), secretKeyN.asByteArray()) return result } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretbox/SecretBox.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretbox/SecretBox.kt index 8f113e6..c2e63b9 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretbox/SecretBox.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretbox/SecretBox.kt @@ -1,11 +1,11 @@ package com.ionspin.kotlin.crypto.secretbox -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object SecretBox { actual fun easy(message: UByteArray, nonce: UByteArray, key: UByteArray): UByteArray { val ciphertext = UByteArray(message.size + crypto_secretbox_MACBYTES) - sodium.crypto_secretbox_easy( + sodiumJna.crypto_secretbox_easy( ciphertext.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -21,7 +21,7 @@ actual object SecretBox { key: UByteArray ): UByteArray { val decrypted = UByteArray(ciphertext.size - crypto_secretbox_MACBYTES) - val validationResult = sodium.crypto_secretbox_open_easy( + val validationResult = sodiumJna.crypto_secretbox_open_easy( decrypted.asByteArray(), ciphertext.asByteArray(), ciphertext.size.toLong(), @@ -41,7 +41,7 @@ actual object SecretBox { ): SecretBoxEncryptedDataAndTag { val ciphertext = UByteArray(message.size) val authenticationTag = UByteArray(crypto_secretbox_MACBYTES) - sodium.crypto_secretbox_detached( + sodiumJna.crypto_secretbox_detached( ciphertext.asByteArray(), authenticationTag.asByteArray(), message.asByteArray(), @@ -59,7 +59,7 @@ actual object SecretBox { key: UByteArray ): UByteArray { val message = UByteArray(ciphertext.size) - val validationResult = sodium.crypto_secretbox_open_detached( + val validationResult = sodiumJna.crypto_secretbox_open_detached( message.asByteArray(), ciphertext.asByteArray(), tag.asByteArray(), @@ -75,7 +75,7 @@ actual object SecretBox { actual fun keygen() : UByteArray { val generatedKey = UByteArray(crypto_secretbox_KEYBYTES) - sodium.crypto_secretbox_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_secretbox_keygen(generatedKey.asByteArray()) return generatedKey } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStreamJvm.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStreamJvm.kt index ca6470c..c20ef6a 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStreamJvm.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStreamJvm.kt @@ -1,15 +1,15 @@ package com.ionspin.kotlin.crypto.secretstream -import com.goterl.lazycode.lazysodium.interfaces.SecretStream -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna +import com.ionspin.kotlin.crypto.SecretStreamXChaCha20Poly1305State -actual typealias SecretStreamState = SecretStream.State +actual typealias SecretStreamState = SecretStreamXChaCha20Poly1305State actual object SecretStream { actual fun xChaCha20Poly1305InitPush(key: UByteArray): SecretStreamStateAndHeader { val state = SecretStreamState() - val header = UByteArray(sodium.crypto_secretstream_xchacha20poly1305_headerbytes()) - sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray()) + val header = UByteArray(sodiumJna.crypto_secretstream_xchacha20poly1305_headerbytes()) + sodiumJna.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray()) return SecretStreamStateAndHeader(state, header) } @@ -20,7 +20,7 @@ actual object SecretStream { tag: UByte ): UByteArray { val ciphertext = UByteArray(message.size + crypto_secretstream_xchacha20poly1305_ABYTES) - sodium.crypto_secretstream_xchacha20poly1305_push( + sodiumJna.crypto_secretstream_xchacha20poly1305_push( state, ciphertext.asByteArray(), null, @@ -38,7 +38,7 @@ actual object SecretStream { header: UByteArray ): SecretStreamStateAndHeader { val state = SecretStreamState() - sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header.asByteArray(), key.asByteArray()) + sodiumJna.crypto_secretstream_xchacha20poly1305_init_pull(state, header.asByteArray(), key.asByteArray()) return SecretStreamStateAndHeader(state, header) } @@ -49,7 +49,7 @@ actual object SecretStream { ): DecryptedDataAndTag { val result = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES) val tagArray = UByteArray(1) { 0U } - val validationResult = sodium.crypto_secretstream_xchacha20poly1305_pull( + val validationResult = sodiumJna.crypto_secretstream_xchacha20poly1305_pull( state, result.asByteArray(), null, @@ -67,12 +67,12 @@ actual object SecretStream { actual fun xChaCha20Poly1305Keygen(): UByteArray { val generatedKey = UByteArray(crypto_secretstream_xchacha20poly1305_KEYBYTES) - sodium.crypto_secretstream_xchacha20poly1305_keygen(generatedKey.asByteArray()) + sodiumJna.crypto_secretstream_xchacha20poly1305_keygen(generatedKey.asByteArray()) return generatedKey } actual fun xChaCha20Poly1305Rekey(state: SecretStreamState) { - sodium.crypto_secretstream_xchacha20poly1305_rekey(state) + sodiumJna.crypto_secretstream_xchacha20poly1305_rekey(state) } } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt index f915ef7..4c072ec 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt @@ -1,6 +1,7 @@ package com.ionspin.kotlin.crypto.shortinputhash -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna +import com.sun.jna.NativeLong /** * Created by Ugljesa Jovanovic @@ -12,13 +13,13 @@ import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium actual object ShortHash { actual fun shortHash(data: UByteArray, key: UByteArray): UByteArray { val hashResult = UByteArray(crypto_shorthash_BYTES) - sodium.crypto_shorthash(hashResult.asByteArray(), data.asByteArray(), data.size.toLong(), key.asByteArray()) + sodiumJna.crypto_shorthash(hashResult.asByteArray(), data.asByteArray(), data.size.toLong(), key.asByteArray()) return hashResult } actual fun shortHashKeygen(): UByteArray { val key = UByteArray(crypto_shorthash_KEYBYTES) - sodium.crypto_shorthash_keygen(key.asByteArray()) + sodiumJna.crypto_shorthash_keygen(key.asByteArray()) return key } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/signature/SignatureJvm.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/signature/SignatureJvm.kt index 56f022b..7ce7b93 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/signature/SignatureJvm.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/signature/SignatureJvm.kt @@ -1,9 +1,9 @@ package com.ionspin.kotlin.crypto.signature -import com.goterl.lazycode.lazysodium.interfaces.Sign -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.Ed25519SignatureState +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna -actual typealias SignatureState = Sign.StateCryptoSign +actual typealias SignatureState = Ed25519SignatureState actual object Signature { actual fun init(): SignatureState { @@ -11,7 +11,7 @@ actual object Signature { } actual fun update(state: SignatureState, data: UByteArray) { - sodium.crypto_sign_update(state, data.asByteArray(), data.size.toLong()) + sodiumJna.crypto_sign_update(state, data.asByteArray(), data.size.toLong()) } actual fun finalCreate( @@ -19,7 +19,7 @@ actual object Signature { secretKey: UByteArray ): UByteArray { val signature = UByteArray(crypto_sign_BYTES) - sodium.crypto_sign_final_create( + sodiumJna.crypto_sign_final_create( state, signature.asByteArray(), null, @@ -33,7 +33,7 @@ actual object Signature { signature: UByteArray, publicKey: UByteArray ) { - val verificationResult = sodium.crypto_sign_final_verify( + val verificationResult = sodiumJna.crypto_sign_final_verify( state, signature.asByteArray(), publicKey.asByteArray() @@ -50,7 +50,7 @@ actual object Signature { actual fun keypair(): SignatureKeyPair { val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES) val secretKey = UByteArray(crypto_sign_SECRETKEYBYTES) - sodium.crypto_sign_keypair( + sodiumJna.crypto_sign_keypair( publicKey.asByteArray(), secretKey.asByteArray(), ) @@ -65,9 +65,9 @@ actual object Signature { actual fun seedKeypair(seed: UByteArray): SignatureKeyPair { val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES) val secretKey = UByteArray(crypto_sign_SECRETKEYBYTES) - - - sodium.crypto_sign_seed_keypair( + + + sodiumJna.crypto_sign_seed_keypair( publicKey.asByteArray(), secretKey.asByteArray(), seed.asByteArray() @@ -76,13 +76,13 @@ actual object Signature { } /** - * The sodium.crypto_sign() function prepends a signature to a message m whose length is mlen bytes, using the secret key sk. - * The signed message, which includes the signature + a plain copy of the message, is put into sm, and is sodium.crypto_sign_BYTES + mlen bytes long. + * The sodiumJna.crypto_sign() function prepends a signature to a message m whose length is mlen bytes, using the secret key sk. + * The signed message, which includes the signature + a plain copy of the message, is put into sm, and is sodiumJna.crypto_sign_BYTES + mlen bytes long. */ actual fun sign(message: UByteArray, secretKey: UByteArray): UByteArray { val signedMessage = UByteArray(message.size + crypto_sign_BYTES) - - sodium.crypto_sign( + + sodiumJna.crypto_sign( signedMessage.asByteArray(), null, message.asByteArray(), @@ -94,13 +94,13 @@ actual object Signature { } /** - * The sodium.crypto_sign_open() function checks that the signed message sm whose length is smlen bytes has a valid signature for the public key pk. + * The sodiumJna.crypto_sign_open() function checks that the signed message sm whose length is smlen bytes has a valid signature for the public key pk. * If the signature is doesn't appear to be valid, the function throws an exception */ actual fun open(signedMessage: UByteArray, publicKey: UByteArray): UByteArray { val message = UByteArray(signedMessage.size - crypto_sign_BYTES) - val verificationResult = sodium.crypto_sign_open( + val verificationResult = sodiumJna.crypto_sign_open( message.asByteArray(), null, signedMessage.asByteArray(), @@ -115,13 +115,13 @@ actual object Signature { /** * In detached mode, the signature is stored without attaching a copy of the original message to it. - * The sodium.crypto_sign_detached() function signs the message m whose length is mlen bytes, using the secret key sk, - * and puts the signature into sig, which can be up to sodium.crypto_sign_BYTES bytes long. + * The sodiumJna.crypto_sign_detached() function signs the message m whose length is mlen bytes, using the secret key sk, + * and puts the signature into sig, which can be up to sodiumJna.crypto_sign_BYTES bytes long. */ actual fun detached(message: UByteArray, secretKey: UByteArray): UByteArray { val signature = UByteArray(crypto_sign_BYTES) - sodium.crypto_sign_detached( + sodiumJna.crypto_sign_detached( signature.asByteArray(), null, message.asByteArray(), @@ -133,7 +133,7 @@ actual object Signature { } /** - * The sodium.crypto_sign_verify_detached() function verifies that sig is a valid signature for the message m whose length + * The sodiumJna.crypto_sign_verify_detached() function verifies that sig is a valid signature for the message m whose length * is mlen bytes, using the signer's public key pk. */ actual fun verifyDetached( @@ -142,7 +142,7 @@ actual object Signature { publicKey: UByteArray ) { - val verificationResult = sodium.crypto_sign_verify_detached( + val verificationResult = sodiumJna.crypto_sign_verify_detached( signature.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -155,11 +155,11 @@ actual object Signature { } /** - * The sodium.crypto_sign_ed25519_pk_to_curve25519() function converts an Ed25519 public key ed25519_pk to an X25519 public key and stores it into x25519_pk. + * The sodiumJna.crypto_sign_ed25519_pk_to_curve25519() function converts an Ed25519 public key ed25519_pk to an X25519 public key and stores it into x25519_pk. */ actual fun ed25519PkToCurve25519(ed25519PublicKey: UByteArray) : UByteArray { val x25519PublicKey = UByteArray(crypto_scalarmult_curve25519_BYTES) - sodium.crypto_sign_ed25519_sk_to_curve25519( + sodiumJna.crypto_sign_ed25519_sk_to_curve25519( x25519PublicKey.asByteArray(), ed25519PublicKey.asByteArray() ) @@ -168,7 +168,7 @@ actual object Signature { actual fun ed25519SkToCurve25519(ed25519SecretKey: UByteArray) : UByteArray { val x25519SecretKey = UByteArray(crypto_scalarmult_curve25519_BYTES) - sodium.crypto_sign_ed25519_sk_to_curve25519( + sodiumJna.crypto_sign_ed25519_sk_to_curve25519( x25519SecretKey.asByteArray(), ed25519SecretKey.asByteArray() ) @@ -176,13 +176,13 @@ actual object Signature { } /** - * The secret key actually includes the seed (either a random seed or the one given to sodium.crypto_sign_seed_keypair()) as well as the public key. + * The secret key actually includes the seed (either a random seed or the one given to sodiumJna.crypto_sign_seed_keypair()) as well as the public key. * While the public key can always be derived from the seed, the precomputation saves a significant amount of CPU cycles when signing. */ actual fun ed25519SkToSeed(secretKey: UByteArray): UByteArray { val seed = UByteArray(crypto_sign_SEEDBYTES) - sodium.crypto_sign_ed25519_sk_to_seed( + sodiumJna.crypto_sign_ed25519_sk_to_seed( seed.asByteArray(), secretKey.asByteArray() ) @@ -192,13 +192,13 @@ actual object Signature { } /** - * The secret key actually includes the seed (either a random seed or the one given to sodium.crypto_sign_seed_keypair()) as well as the public key. + * The secret key actually includes the seed (either a random seed or the one given to sodiumJna.crypto_sign_seed_keypair()) as well as the public key. * While the public key can always be derived from the seed, the precomputation saves a significant amount of CPU cycles when signing. */ actual fun ed25519SkToPk(secretKey: UByteArray): UByteArray { val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES) - sodium.crypto_sign_ed25519_sk_to_pk( + sodiumJna.crypto_sign_ed25519_sk_to_pk( publicKey.asByteArray(), secretKey.asByteArray() ) @@ -206,4 +206,4 @@ actual object Signature { return publicKey } -} \ No newline at end of file +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt index 32d17f6..eaec0e9 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt @@ -1,12 +1,12 @@ package com.ionspin.kotlin.crypto.stream -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna actual object Stream { actual fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray): UByteArray { val result = UByteArray(clen) - sodium.crypto_stream_chacha20(result.asByteArray(), clen.toLong(), nonce.asByteArray(), key.asByteArray()) + sodiumJna.crypto_stream_chacha20(result.asByteArray(), clen.toLong(), nonce.asByteArray(), key.asByteArray()) return result } @@ -18,7 +18,7 @@ actual object Stream { ): UByteArray { val result = UByteArray(message.size) - sodium.crypto_stream_chacha20_ietf_xor( + sodiumJna.crypto_stream_chacha20_ietf_xor( result.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -37,7 +37,7 @@ actual object Stream { ): UByteArray { val result = UByteArray(message.size) - sodium.crypto_stream_chacha20_ietf_xor_ic( + sodiumJna.crypto_stream_chacha20_ietf_xor_ic( result.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -52,7 +52,7 @@ actual object Stream { actual fun chacha20Keygen(): UByteArray { val result = UByteArray(crypto_stream_chacha20_KEYBYTES) - sodium.crypto_stream_chacha20_keygen(result.asByteArray()) + sodiumJna.crypto_stream_chacha20_keygen(result.asByteArray()) return result } @@ -64,7 +64,7 @@ actual object Stream { ): UByteArray { val result = UByteArray(message.size) - sodium.crypto_stream_chacha20_xor( + sodiumJna.crypto_stream_chacha20_xor( result.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -83,7 +83,7 @@ actual object Stream { ): UByteArray { val result = UByteArray(message.size) - sodium.crypto_stream_chacha20_xor_ic( + sodiumJna.crypto_stream_chacha20_xor_ic( result.asByteArray(), message.asByteArray(), message.size.toLong(), @@ -95,4 +95,50 @@ actual object Stream { return result } + +// actual fun xChacha20Keygen(): UByteArray { +// val result = UByteArray(crypto_stream_chacha20_KEYBYTES) +// +// sodiumJna.crypto_stream_xchacha20_keygen(result.asByteArray()) +// +// return result +// } +// +// actual fun xChacha20Xor( +// message: UByteArray, +// nonce: UByteArray, +// key: UByteArray +// ): UByteArray { +// val result = UByteArray(message.size) +// +// sodiumJna.crypto_stream_xchacha20_xor( +// result.asByteArray(), +// message.asByteArray(), +// message.size.toLong(), +// nonce.asByteArray(), +// key.asByteArray() +// ) +// +// return result +// } +// +// actual fun xChacha20XorIc( +// message: UByteArray, +// nonce: UByteArray, +// initialCounter: ULong, +// key: UByteArray +// ): UByteArray { +// val result = UByteArray(message.size) +// +// sodiumJna.crypto_stream_xchacha20_xor_ic( +// result.asByteArray(), +// message.asByteArray(), +// message.size.toLong(), +// nonce.asByteArray(), +// initialCounter.toLong(), +// key.asByteArray() +// ) +// +// return result +// } } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumRandom.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumRandom.kt index fbbcae3..26e24a1 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumRandom.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumRandom.kt @@ -1,6 +1,6 @@ package com.ionspin.kotlin.crypto.util -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna /** * Created by Ugljesa Jovanovic @@ -13,7 +13,7 @@ actual object LibsodiumRandom { */ actual fun buf(size: Int): UByteArray { val result = ByteArray(size) - sodium.randombytes_buf(result, size) + sodiumJna.randombytes_buf(result, size) return result.asUByteArray() } @@ -27,7 +27,7 @@ actual object LibsodiumRandom { */ actual fun bufDeterministic(size: Int, seed: UByteArray): UByteArray { val result = ByteArray(size) - sodium.randombytes_buf_deterministic(result, size, seed.asByteArray()) + sodiumJna.randombytes_buf_deterministic(result, size, seed.asByteArray()) return result.asUByteArray() } @@ -35,9 +35,7 @@ actual object LibsodiumRandom { * The randombytes_random() function returns an unpredictable value between 0 and 0xffffffff (included). */ actual fun random(): UInt { - //Broken in lazysodium-java https://github.com/terl/lazysodium-java/issues/86 - //Using temporary forked and fixed build until pull request is accepted in original repo - return sodium.randombytes_random().toUInt() + return sodiumJna.randombytes_random().toUInt() } @@ -48,9 +46,7 @@ actual object LibsodiumRandom { * upper_bound is not a power of 2. Note that an upper_bound < 2 leaves only a single element to be chosen, namely 0 */ actual fun uniform(upperBound: UInt): UInt { - //Broken in lazysodium-java https://github.com/terl/lazysodium-java/issues/86 - //Using temporary fixed build until pull request is accepted - return sodium.randombytes_uniform(upperBound.toInt()).toUInt() + return sodiumJna.randombytes_uniform(upperBound.toLong()).toUInt() } } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt index a88bf78..7422108 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt @@ -1,6 +1,7 @@ package com.ionspin.kotlin.crypto.util -import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna +import com.sun.jna.ptr.IntByReference import java.lang.RuntimeException import java.util.* @@ -9,100 +10,63 @@ actual object LibsodiumUtil { if (first.size != second.size) { throw RuntimeException("Sodium memcmp() only supports comparing same length arrays") } - return sodium.sodium_memcmp(first.asByteArray(), second.asByteArray(), first.size) == 0 + return sodiumJna.sodium_memcmp(first.asByteArray(), second.asByteArray(), first.size) == 0 } actual fun memzero(target: UByteArray) { - sodium.sodium_memzero(target.asByteArray(), target.size) + sodiumJna.sodium_memzero(target.asByteArray(), target.size) } actual fun pad(unpaddedData: UByteArray, blocksize: Int): UByteArray { - // Pad is invalid in lazysodium-java because it uses char arrays, which are 2 bytes in java - // while libsodium expects 1 byte char array - // See https://github.com/terl/lazysodium-java/issues/85 - - //This is temporary solution until lazysodium is fixed - if (blocksize == 0) { - throw RuntimeException("Invalid block size: $blocksize") - } - val padAmount = blocksize - (unpaddedData.size % blocksize) - val result = if (padAmount == blocksize) { - unpaddedData + UByteArray(blocksize) { - when (it) { - 0 -> 0x80U - else -> 0x00U - } - } - } else { - unpaddedData + UByteArray(padAmount) { - when (it) { - 0 -> 0x80U - else -> 0x00U - } + val newPadSizeReference = IntByReference(0) + val newSize = ((unpaddedData.size / blocksize) + 1) * blocksize + val paddedArray = UByteArray(newSize) { + if (it < unpaddedData.size) { + unpaddedData[it] + } else { + 0U } } + val resultCode = sodiumJna.sodium_pad( + newPadSizeReference.pointer, + paddedArray.asByteArray(), + unpaddedData.size, + blocksize, + newSize + ) + if (resultCode != 0) { + throw RuntimeException("Padding failed") + } - return result - -// val newPadSizeReference = IntByReference(0) -// val newSize = ((unpaddedData.size / blocksize) + 1) * blocksize -// val charArray = CharArray(newSize) { -// if (it < unpaddedData.size) { -// unpaddedData[it].toByte().toChar() -// } else { -// '\u0000' -// } -// } -// sodium.sodium_pad( -// newPadSizeReference.pointer, -// charArray, -// unpaddedData.size + 1, -// blocksize, -// newSize -// ) -// -// return charArray.slice(0 until newPadSizeReference.value).map { it.toByte().toUByte()}.toUByteArray() + return paddedArray.slice(0 until newPadSizeReference.value).map { it.toByte().toUByte()}.toUByteArray() } actual fun unpad(paddedData: UByteArray, blocksize: Int): UByteArray { - // Pad is invalid in lazysodium-java because it uses char arrays, which are 2 bytes in java - // while libsodium expects 1 byte char array - // See https://github.com/terl/lazysodium-java/issues/85 + val paddedDataCopy = paddedData.copyOf().asByteArray() + var unpaddedSize = IntByReference(0) - //This is temporary solution until lazysodium is fixed + sodiumJna.sodium_unpad( + unpaddedSize.pointer, + paddedDataCopy, + paddedData.size, + blocksize + ) - val unpaddedData = paddedData.dropLastWhile { it == 0U.toUByte() } - if (unpaddedData.last() != 0x80U.toUByte()) { - throw RuntimeException("Invalid padding!") - } - return unpaddedData.dropLast(1).toUByteArray() + val unpadded = paddedDataCopy.sliceArray(0 until unpaddedSize.value).asUByteArray() - -// val paddedDataCopy = paddedData.copyOf().asByteArray().map { it.toChar() }.toCharArray() -// var unpaddedSize = IntByReference(0) -// -// sodium.sodium_unpad( -// unpaddedSize.pointer, -// paddedDataCopy, -// paddedData.size, -// blocksize -// ) -// -// val unpadded = paddedDataCopy.sliceArray(0 until unpaddedSize.value).map { it.toByte().toUByte() }.toUByteArray() -// -// return unpadded + return unpadded } actual fun toBase64( data: UByteArray, variant: Base64Variants ): String { - val maxlen = sodium.sodium_base64_encoded_len(data.size, variant.value) + val maxlen = sodiumJna.sodium_base64_encoded_len(data.size, variant.value) val result = ByteArray(maxlen) { 0 } - sodium.sodium_bin2base64( + sodiumJna.sodium_bin2base64( result, maxlen, data.asByteArray(), @@ -116,49 +80,66 @@ actual object LibsodiumUtil { actual fun toHex(data: UByteArray): String { val hexLen = (data.size * 2) + 1 // +1 for terminator char val result = ByteArray(hexLen) - sodium.sodium_bin2hex( + sodiumJna.sodium_bin2hex( result, hexLen, data.asByteArray(), data.size ) + //Drop terminating char \0 return String(result.sliceArray(0 until result.size - 1)) } + actual fun fromHex(data: String): UByteArray { + val binLenReference = IntByReference(0) + val binSize = (data.length + 1) / 2 // -1 for terminator char + val hex = data.toCharArray().map { it.toByte() }.toByteArray() + val result = ByteArray(binSize) + val resultCode = sodiumJna.sodium_hex2bin( + result, + binSize, + hex, + hex.size, + null, + binLenReference.pointer, + null + ) + if (resultCode != 0) { + throw ConversionException() + } + return result.slice(0 until binLenReference.value).toByteArray().asUByteArray() + } + actual fun fromBase64( data: String, variant: Base64Variants ): UByteArray { - // from base64 is currently broken in lazysodium-java - // see https://github.com/terl/lazysodium-java/issues/83 -// val maxLength = (data.length * 3) / 4 -// val intermediaryResult = UByteArray(maxLength) { 0U } -// -// sodium.sodium_base642bin( -// intermediaryResult.asByteArray(), -// maxLength, -// data.encodeToByteArray(), -// data.length, -// null, -// binLenPinned.addressOf(0), -// null, -// variant.value -// -// ) - val decoder = when(variant) { - Base64Variants.ORIGINAL -> Base64.getDecoder() - Base64Variants.ORIGINAL_NO_PADDING -> Base64.getDecoder() - Base64Variants.URLSAFE -> Base64.getUrlDecoder() - Base64Variants.URLSAFE_NO_PADDING -> Base64.getUrlDecoder() + val binLengthReference = IntByReference(0) + val maxLength = (data.length * 3) / 4 + val intermediaryResult = UByteArray(maxLength) { 0U } + + val resultCode = sodiumJna.sodium_base642bin( + intermediaryResult.asByteArray(), + maxLength, + data.encodeToByteArray(), + data.length, + null, + binLengthReference.pointer, + null, + variant.value + ) + + if (resultCode != 0) { + throw ConversionException() } - return decoder.decode(data).asUByteArray() + + return intermediaryResult.sliceArray(0 until binLengthReference.value) + + + } - actual fun fromHex(data: String): UByteArray { - // from hex is currently broken in lazysodium-java - // see https://github.com/terl/lazysodium-java/issues/83 - return data.hexStringToUByteArray() - } + } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-linux-x86-64-libsodium.so b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-linux-x86-64-libsodium.so new file mode 100755 index 0000000..041b6e4 Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-linux-x86-64-libsodium.so differ diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-macos-x86-64.dylib b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-macos-x86-64.dylib new file mode 100755 index 0000000..2557c8a Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-macos-x86-64.dylib differ diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-mingw-x86-64-libsodium.dll.a b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-mingw-x86-64-libsodium.dll.a new file mode 100644 index 0000000..bbbdd72 Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-mingw-x86-64-libsodium.dll.a differ diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-msvc-x86-64-libsodium.dll b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-msvc-x86-64-libsodium.dll new file mode 100644 index 0000000..d5f0e67 Binary files /dev/null and b/multiplatform-crypto-libsodium-bindings/src/jvmMain/resources/dynamic-msvc-x86-64-libsodium.dll differ diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmSpecific/com/ionspin/kotlin/crypto/JvmSodiumWrapper.kt b/multiplatform-crypto-libsodium-bindings/src/jvmSpecific/com/ionspin/kotlin/crypto/JvmSodiumWrapper.kt index eb62fc6..3e38013 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmSpecific/com/ionspin/kotlin/crypto/JvmSodiumWrapper.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmSpecific/com/ionspin/kotlin/crypto/JvmSodiumWrapper.kt @@ -1,11 +1,2 @@ package com.ionspin.kotlin.crypto -import com.goterl.lazycode.lazysodium.LazySodiumJava -import com.goterl.lazycode.lazysodium.SodiumJava - -/** - * Created by Ugljesa Jovanovic - * ugljesa.jovanovic@ionspin.com - * on 22-Aug-2020 - */ -typealias SodiumWrapper = SodiumJava diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmTest/kotlin/com/ionspin/kotlin/crypto/jnitest/JnaLibraryLoaderTest.kt b/multiplatform-crypto-libsodium-bindings/src/jvmTest/kotlin/com/ionspin/kotlin/crypto/jnitest/JnaLibraryLoaderTest.kt new file mode 100644 index 0000000..8032781 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jvmTest/kotlin/com/ionspin/kotlin/crypto/jnitest/JnaLibraryLoaderTest.kt @@ -0,0 +1,23 @@ +package com.ionspin.kotlin.crypto.jnitest + +import com.ionspin.kotlin.crypto.LibsodiumInitializer +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna +import com.ionspin.kotlin.crypto.util.runTest +import org.junit.Test +import kotlin.test.assertEquals + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 20-Feb-2021 + */ +class JnaLibraryLoaderTest { + + @Test + fun testIfLibraryIsLoaded() = runTest { + LibsodiumInitializer.initialize() + val version = sodiumJna.sodium_version_string() + println("Got loaded sodium version: $version") + assertEquals("1.0.18", version) + } +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmTest/kotlin/com/ionspin/kotlin/crypto/secretstream/modifyState.kt b/multiplatform-crypto-libsodium-bindings/src/jvmTest/kotlin/com/ionspin/kotlin/crypto/secretstream/modifyState.kt index 46ec50b..c852d3d 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmTest/kotlin/com/ionspin/kotlin/crypto/secretstream/modifyState.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmTest/kotlin/com/ionspin/kotlin/crypto/secretstream/modifyState.kt @@ -1,6 +1,6 @@ package com.ionspin.kotlin.crypto.secretstream actual fun modifyState(state: SecretStreamState, forceNonce: UByteArray) { - state.nonce = forceNonce.sliceArray(12 until 24).asByteArray() + forceNonce.sliceArray(12 until 24).asByteArray().copyInto(state.nonce) println("Nonce modified ${state.nonce}") } diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt index ff37390..74e980b 100644 --- a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/stream/Stream.kt @@ -3,7 +3,6 @@ package com.ionspin.kotlin.crypto.stream import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.convert import kotlinx.cinterop.pin -import libsodium.crypto_stream_KEYBYTES import libsodium.crypto_stream_chacha20 import libsodium.crypto_stream_chacha20_ietf_xor import libsodium.crypto_stream_chacha20_ietf_xor_ic @@ -11,6 +10,10 @@ import libsodium.crypto_stream_chacha20_keygen import libsodium.crypto_stream_chacha20_xor import libsodium.crypto_stream_chacha20_xor_ic +//import libsodium.crypto_stream_xchacha20_keygen +//import libsodium.crypto_stream_xchacha20_xor +//import libsodium.crypto_stream_xchacha20_xor_ic + actual object Stream { actual fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray): UByteArray { val result = UByteArray(clen) @@ -149,4 +152,71 @@ actual object Stream { return result } + +// actual fun xChacha20Keygen(): UByteArray { +// val result = UByteArray(crypto_stream_xchacha20_KEYBYTES) +// val resultPinned = result.pin() +// +// crypto_stream_xchacha20_keygen(resultPinned.toPtr()) +// +// resultPinned.unpin() +// +// return result +// } +// +// actual fun xChacha20Xor( +// message: UByteArray, +// nonce: UByteArray, +// key: UByteArray +// ): UByteArray { +// val result = UByteArray(message.size) +// val messagePinned = message.pin() +// val resultPinned = result.pin() +// val noncePinned = nonce.pin() +// val keyPinned = key.pin() +// +// crypto_stream_xchacha20_xor( +// resultPinned.toPtr(), +// messagePinned.toPtr(), +// message.size.convert(), +// noncePinned.toPtr(), +// keyPinned.toPtr() +// ) +// +// messagePinned.unpin() +// resultPinned.unpin() +// noncePinned.unpin() +// keyPinned.unpin() +// +// return result +// } +// +// actual fun xChacha20XorIc( +// message: UByteArray, +// nonce: UByteArray, +// initialCounter: ULong, +// key: UByteArray +// ): UByteArray { +// val result = UByteArray(message.size) +// val messagePinned = message.pin() +// val resultPinned = result.pin() +// val noncePinned = nonce.pin() +// val keyPinned = key.pin() +// +// crypto_stream_xchacha20_xor_ic( +// resultPinned.toPtr(), +// messagePinned.toPtr(), +// message.size.convert(), +// noncePinned.toPtr(), +// initialCounter.convert(), +// keyPinned.toPtr() +// ) +// +// messagePinned.unpin() +// resultPinned.unpin() +// noncePinned.unpin() +// keyPinned.unpin() +// +// return result +// } } diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index 295d20b..f304232 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -63,7 +63,7 @@ kotlin { android() runningOnLinuxx86_64 { jvm() - js { + js(IR) { browser { webpackTask { @@ -188,7 +188,7 @@ kotlin { implementation(kotlin(Deps.Common.test)) implementation(Deps.Common.kotlinBigNum) implementation(Deps.Common.serialization) - api(Deps.Common.libsodiumBindings) + api(project(":multiplatform-crypto-libsodium-bindings")) } } val commonTest by getting { diff --git a/sample/src/androidMain/kotlin/com/ionspin/kotlin/crypto/sample/MainActivity.kt b/sample/src/androidMain/kotlin/com/ionspin/kotlin/crypto/sample/MainActivity.kt index f484737..6b492f3 100644 --- a/sample/src/androidMain/kotlin/com/ionspin/kotlin/crypto/sample/MainActivity.kt +++ b/sample/src/androidMain/kotlin/com/ionspin/kotlin/crypto/sample/MainActivity.kt @@ -6,10 +6,19 @@ package com.ionspin.kotlin.crypto.sample import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna +import com.ionspin.kotlin.crypto.TmpAccessor +import com.ionspin.kotlin.crypto.box.Box +import com.ionspin.kotlin.crypto.box.BoxCorruptedOrTamperedDataException +import com.ionspin.kotlin.crypto.box.crypto_box_NONCEBYTES import com.ionspin.kotlin.crypto.hash.Hash +import com.ionspin.kotlin.crypto.util.decodeFromUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.toHexString import kotlinx.android.synthetic.main.activity_main.* +import java.lang.StringBuilder +import kotlin.random.Random +import kotlin.random.nextUBytes class MainActivity : AppCompatActivity() { @@ -18,9 +27,25 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val hash = Hash.sha512("123".encodeToUByteArray()) - helloWorldTextView.setText("Hash (SHA512) of 123: ${hash.toHexString()}") + val message = "Message message message".encodeToUByteArray() + val senderKeypair = Box.keypair() + val recipientKeypair = Box.keypair() + val messageNonce = Random(0).nextUBytes(crypto_box_NONCEBYTES) + val builder = StringBuilder() + val encrypted = Box.easy(message, messageNonce, recipientKeypair.publicKey, senderKeypair.secretKey) + builder.appendLine("Encrypted: ${encrypted.toHexString()}") + val decrypted = Box.openEasy(encrypted, messageNonce, senderKeypair.publicKey, recipientKeypair.secretKey) + builder.appendLine("Decrypted: ${decrypted.decodeFromUByteArray()}") + try { + val tampered = encrypted.copyOf() + tampered[1] = 0U + Box.openEasy(tampered, messageNonce, senderKeypair.publicKey, recipientKeypair.secretKey) + } catch (exception : Exception) { + builder.appendLine("And caught tamper") + } + helloWorldTextView.setText(builder.toString()) } } diff --git a/sample/src/jsMain/kotlin/com/ionspin/kotlin/crypto/sample/Main.kt b/sample/src/jsMain/kotlin/com/ionspin/kotlin/crypto/sample/Main.kt index 1b2174c..f5e426d 100644 --- a/sample/src/jsMain/kotlin/com/ionspin/kotlin/crypto/sample/Main.kt +++ b/sample/src/jsMain/kotlin/com/ionspin/kotlin/crypto/sample/Main.kt @@ -7,11 +7,12 @@ import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.toHexString import react.dom.render import kotlinx.browser.document -import kotlin.browser.window +import kotlinx.browser.window + fun main() { val runningOnNode = jsTypeOf(window) == "undefined" - if (!runningOnNode) = runTest { +// if (!runningOnNode) = runTest { LibsodiumInitializer.initializeWithCallback { render(document.getElementById("root")) { app { @@ -19,10 +20,10 @@ fun main() { } } } - } else = runTest { - LibsodiumInitializer.initializeWithCallback { - val hash = Hash.sha512("123".encodeToUByteArray()) - println("Hash (SHA512) of 123: ${hash.toHexString()}") - } - } +// } else = runTest { +// LibsodiumInitializer.initializeWithCallback { +// val hash = Hash.sha512("123".encodeToUByteArray()) +// println("Hash (SHA512) of 123: ${hash.toHexString()}") +// } +// } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 98649a6..d0a5cf9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,5 +37,5 @@ enableFeaturePreview("GRADLE_METADATA") rootProject.name = "KotlinMultiplatformLibsodium" include("multiplatform-crypto-api") include("multiplatform-crypto-libsodium-bindings") -//include("sample") +include("sample") diff --git a/supported_bindings_list.md b/supported_bindings_list.md index ca958d0..9ebd0a7 100644 --- a/supported_bindings_list.md +++ b/supported_bindings_list.md @@ -143,9 +143,9 @@ native libsodium library. | crypto_stream_chacha20_xor | :heavy_check_mark: | | crypto_stream_chacha20_xor_ic | :heavy_check_mark: | | crypto_stream_keygen | Other XSalsa20 primitives are not available, so I'm leaving this out as well| -| crypto_stream_xchacha20_keygen | not present in LazySodium Android | -| crypto_stream_xchacha20_xor | not present in LazySodium Android| -| crypto_stream_xchacha20_xor_ic | not present in LazySodium Android | +| crypto_stream_xchacha20_keygen | Not at the moment | +| crypto_stream_xchacha20_xor | Not at the moment | +| crypto_stream_xchacha20_xor_ic | Not at the moment | | randombytes_buf | :heavy_check_mark: | | randombytes_buf_deterministic | :heavy_check_mark: | | randombytes_close | not present in LazySodium |