Starting jna implementation

This commit is contained in:
Ugljesa Jovanovic 2021-02-21 12:07:20 +01:00
parent 86cdc0da8f
commit b976bb62a0
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
10 changed files with 321 additions and 84 deletions

View File

@ -445,7 +445,7 @@ kotlin {
kotlin.srcDirs("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")

View File

@ -1,8 +1,6 @@
package com.ionspin.kotlin.crypto
import com.goterl.lazycode.lazysodium.SodiumAndroid
import com.ionspin.kotlin.crypto.jnitest.SodiumVersion
import com.sun.jna.Native
/**

View File

@ -0,0 +1,242 @@
package com.ionspin.kotlin.crypto
import com.sun.jna.Library
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 21-Feb-2021
*/
interface JnaLibsodiumInterface : Library {
fun sodium_version_string() : String
fun randombytes_buf(buffer: ByteArray, bufferSize : Int)
// fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array, key: Uint8Array): Uint8Array
//
// fun crypto_hash_sha256(message: Uint8Array): Uint8Array
//
// fun crypto_hash_sha512(message: Uint8Array): Uint8Array
//
// // ---- Generic hash ---- // Updateable
//
// fun crypto_generichash_init(key : Uint8Array, hashLength: Int) : dynamic
//
// fun crypto_generichash_update(state: dynamic, inputMessage: Uint8Array)
//
// fun crypto_generichash_final(state: dynamic, hashLength: Int) : Uint8Array
//
// fun crypto_generichash_keygen() : Uint8Array
//
// // ---- Generic hash end ---- // Updateable
//
// // ---- Blake2b ----
//
// fun crypto_generichash_blake2b(hashLength: Int, inputMessage: Uint8Array, key: Uint8Array): Uint8Array
//
// fun crypto_generichash_blake2b_init(key : Uint8Array, hashLength: Int) : dynamic
//
// fun crypto_generichash_blake2b_update(state: dynamic, inputMessage: Uint8Array)
//
// fun crypto_generichash_blake2b_final(state: dynamic, hashLength: Int) : Uint8Array
//
// fun crypto_generichash_blake2b_keygen() : Uint8Array
//
// // ---- Blake2b end ----
//
// // ---- Short hash ----
// fun crypto_shorthash(data : Uint8Array, key: Uint8Array) : Uint8Array
//
// fun crypto_shorthash_keygen() : Uint8Array
// // ---- Short hash end ----
//
// fun crypto_hash_sha256_init() : dynamic
//
// fun crypto_hash_sha256_update(state: dynamic, message: Uint8Array)
//
// fun crypto_hash_sha256_final(state: dynamic): Uint8Array
//
// fun crypto_hash_sha512_init() : dynamic
//
// fun crypto_hash_sha512_update(state: dynamic, message: Uint8Array)
//
// fun crypto_hash_sha512_final(state: dynamic): Uint8Array
//
// //XChaCha20Poly1305 - also in bindings
// //fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, associatedData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
// //fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, associatedData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
//
// //XChaCha20Poly1305
// //encrypt
// fun crypto_secretstream_xchacha20poly1305_init_push(key: Uint8Array) : dynamic
// fun crypto_secretstream_xchacha20poly1305_push(state: dynamic, message: Uint8Array, associatedData: Uint8Array, tag: UByte) : Uint8Array
//
// //decrypt
// fun crypto_secretstream_xchacha20poly1305_init_pull(header: Uint8Array, key: Uint8Array) : dynamic
// fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, associatedData: Uint8Array) : dynamic
//
// //keygen and rekey
// fun crypto_secretstream_xchacha20poly1305_keygen() : Uint8Array
// fun crypto_secretstream_xchacha20poly1305_rekey(state: dynamic)
//
// // ---- SecretBox ----
// fun crypto_secretbox_detached(message: Uint8Array, nonce: Uint8Array, key: Uint8Array) : dynamic
// fun crypto_secretbox_easy(message: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_secretbox_keygen() : Uint8Array
// fun crypto_secretbox_open_detached(ciphertext : Uint8Array, tag : Uint8Array, nonce: Uint8Array, key: Uint8Array) : dynamic
// fun crypto_secretbox_open_easy(ciphertext : Uint8Array, nonce: Uint8Array, key: Uint8Array) : dynamic
//
//
// // ---- SecretBox End ----
//
//
// // ---- AEAD ----
// fun crypto_aead_chacha20poly1305_decrypt(nsec : Uint8Array?, ciphertext: Uint8Array, associatedData: Uint8Array, npub: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_aead_chacha20poly1305_decrypt_detached(nsec: Uint8Array?, ciphertext: Uint8Array, mac: Uint8Array, associatedData: Uint8Array, npub: Uint8Array, key: Uint8Array): Uint8Array
// fun crypto_aead_chacha20poly1305_encrypt(message: Uint8Array, associatedData: Uint8Array, nsec: Uint8Array?, npub: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_aead_chacha20poly1305_encrypt_detached(message: Uint8Array, associatedData: Uint8Array, nsec: Uint8Array?, npub: Uint8Array, key: Uint8Array) : dynamic
// fun crypto_aead_chacha20poly1305_ietf_decrypt(nsec : Uint8Array?, ciphertext: Uint8Array, associatedData: Uint8Array, npub: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_aead_chacha20poly1305_ietf_decrypt_detached(nsec: Uint8Array?, ciphertext: Uint8Array, mac: Uint8Array, associatedData: Uint8Array, npub: Uint8Array, key: Uint8Array): Uint8Array
// fun crypto_aead_chacha20poly1305_ietf_encrypt(message: Uint8Array, associatedData: Uint8Array, nsec: Uint8Array?, npub: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_aead_chacha20poly1305_ietf_encrypt_detached(message: Uint8Array, associatedData: Uint8Array, nsec: Uint8Array?, npub: Uint8Array, key: Uint8Array) : dynamic
// fun crypto_aead_chacha20poly1305_ietf_keygen() : Uint8Array
// fun crypto_aead_chacha20poly1305_keygen() : Uint8Array
// fun crypto_aead_xchacha20poly1305_ietf_decrypt(nsec : Uint8Array?, ciphertext: Uint8Array, associatedData: Uint8Array, npub: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_aead_xchacha20poly1305_ietf_decrypt_detached(nsec: Uint8Array?, ciphertext: Uint8Array, mac: Uint8Array, associatedData: Uint8Array, npub: Uint8Array, key: Uint8Array): Uint8Array
// fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, associatedData: Uint8Array, nsec: Uint8Array?, npub: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_aead_xchacha20poly1305_ietf_encrypt_detached(message: Uint8Array, associatedData: Uint8Array, nsec: Uint8Array?, npub: Uint8Array, key: Uint8Array) : dynamic
// fun crypto_aead_xchacha20poly1305_ietf_keygen(): Uint8Array
//
// // ---- AEAD end ----
//
// // ---- Auth ----
//
// fun crypto_auth(message: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_auth_keygen() : Uint8Array
// fun crypto_auth_verify(tag: Uint8Array, message: Uint8Array, key: Uint8Array) : Boolean
// fun crypto_auth_hmacsha256(message: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_auth_hmacsha256_keygen() : Uint8Array
// fun crypto_auth_hmacsha256_verify(tag: Uint8Array, message: Uint8Array, key: Uint8Array) : Boolean
// fun crypto_auth_hmacsha512(message: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_auth_hmacsha512_keygen() : Uint8Array
// fun crypto_auth_hmacsha512_verify(tag: Uint8Array, message: Uint8Array, key: Uint8Array) : Boolean
//
// // ---- Auth end ----
//
// // ---- Box ----
//
// fun crypto_box_keypair() : dynamic
// fun crypto_box_seed_keypair(seed : Uint8Array) : dynamic
// fun crypto_box_easy(message: Uint8Array,
// nonce: Uint8Array,
// recipientsPublicKey: Uint8Array,
// sendersSecretKey: Uint8Array) : Uint8Array
// fun crypto_box_open_easy(ciphertext: Uint8Array,
// nonce: Uint8Array,
// sendersPublicKey: Uint8Array,
// recipientsSecretKey: Uint8Array) : Uint8Array
// fun crypto_box_detached(message: Uint8Array,
// nonce: Uint8Array,
// recipientsPublicKey: Uint8Array,
// sendersSecretKey: Uint8Array) : dynamic
// fun crypto_box_open_detached(ciphertext: Uint8Array,
// tag: Uint8Array,
// nonce: Uint8Array,
// sendersPublicKey: Uint8Array,
// recipientsSecretKey: Uint8Array) : Uint8Array
// fun crypto_box_beforenm(publicKey: Uint8Array, secretKey: Uint8Array) : Uint8Array
// fun crypto_box_easy_afternm(message: Uint8Array,
// nonce: Uint8Array,
// precomputedKey: Uint8Array) : Uint8Array
// fun crypto_box_open_easy_afternm(ciphertext: Uint8Array,
// nonce: Uint8Array,
// precomputedKey: Uint8Array) : Uint8Array
// fun crypto_box_seal(message: Uint8Array, recipientsPublicKey: Uint8Array) : Uint8Array
// fun crypto_box_seal_open(ciphertext: Uint8Array, recipientsPublicKey: Uint8Array, recipientsSecretKey: Uint8Array) : Uint8Array
//
// // ---- Box end ----
//
// // ---- Sign start ----
// fun crypto_sign(message: Uint8Array, secretKey: Uint8Array) : Uint8Array
// fun crypto_sign_detached(message: Uint8Array, secretKey: Uint8Array) : Uint8Array
// fun crypto_sign_ed25519_pk_to_curve25519(ed25519PublicKey: Uint8Array) : Uint8Array
// fun crypto_sign_ed25519_sk_to_curve25519(ed25519SecretKey: Uint8Array) : Uint8Array
// fun crypto_sign_ed25519_sk_to_pk(ed25519SecretKey: Uint8Array) : Uint8Array
// fun crypto_sign_ed25519_sk_to_seed(ed25519SecretKey: Uint8Array) : Uint8Array
// fun crypto_sign_final_create(state: dynamic, secretKey: Uint8Array) : Uint8Array
// fun crypto_sign_final_verify(state: dynamic, signature: Uint8Array, publicKey: Uint8Array) : Boolean
// fun crypto_sign_init() : dynamic
// fun crypto_sign_keypair() : dynamic
// fun crypto_sign_open(signedMessage: Uint8Array, publicKey: Uint8Array) : Uint8Array
// fun crypto_sign_seed_keypair(seed: Uint8Array) : dynamic
// fun crypto_sign_update(state: dynamic, message: Uint8Array)
// fun crypto_sign_verify_detached(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array) : Boolean
//
//
// // ---- Sign end ----
//
//
// // ---- KDF ----
//
// fun crypto_kdf_derive_from_key(subkey_len: UInt, subkeyId : UInt, ctx: String, key: Uint8Array) : Uint8Array
// fun crypto_kdf_keygen() : Uint8Array
//
// // ---- KDF end -----
//
// // ---- Password hashing ----
//
// fun crypto_pwhash(keyLength : UInt, password : Uint8Array, salt: Uint8Array, opsLimit: UInt, memLimit: UInt, algorithm: UInt) : Uint8Array
// fun crypto_pwhash_str(password: Uint8Array, opsLimit: UInt, memLimit: UInt) : String
// fun crypto_pwhash_str_needs_rehash(hashedPassword: String, opsLimit: UInt, memLimit: UInt) : Boolean
// fun crypto_pwhash_str_verify(hashedPassword: String, password: Uint8Array) : Boolean
//
//
// // ---- Password hashing end ----
//
// // ---- Utils ----
//
// fun memcmp(first: Uint8Array, second: Uint8Array) : Boolean
// fun memzero(data: Uint8Array)
// fun pad(data : Uint8Array, blocksize: Int) : Uint8Array
// fun unpad(data: Uint8Array, blocksize: Int) : Uint8Array
// fun to_base64(data: Uint8Array, variant: Int) : String
// fun to_hex(data: Uint8Array) : String
// fun to_string(data: Uint8Array) : String
// fun from_base64(data: String, variant: Int): Uint8Array
// fun from_hex(data : String): Uint8Array
// fun from_string(data : String): Uint8Array
//
// // ---- > ---- Random ---- < -----
//
// fun randombytes_buf(length: UInt) : Uint8Array
// fun randombytes_buf_deterministic(length: UInt, seed : Uint8Array) : Uint8Array
// fun randombytes_random() : UInt
// fun randombytes_uniform(upper_bound: UInt) : UInt
//
// // ---- Utils end ----
//
// // ---- Key exchange ----
// fun crypto_kx_client_session_keys(clientPublicKey: Uint8Array, clientSecretKey: Uint8Array, serverPublicKey: Uint8Array) : dynamic
// fun crypto_kx_keypair() : dynamic
// fun crypto_kx_seed_keypair(seed: Uint8Array) : dynamic
// fun crypto_kx_server_session_keys(serverPublicKey: Uint8Array, serverSecretKey: Uint8Array, clientPublicKey: Uint8Array) : dynamic
//
// // ---- Key exchange end ----
//
// // -- Stream ----
// fun crypto_stream_chacha20(outLength: UInt, key: Uint8Array, nonce: Uint8Array) : Uint8Array
// fun crypto_stream_chacha20_ietf_xor(message : Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
// fun crypto_stream_chacha20_ietf_xor_ic(message : Uint8Array, nonce: Uint8Array, initialCounter: UInt, key: Uint8Array) : Uint8Array
// fun crypto_stream_chacha20_keygen() : Uint8Array
// 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
//
// // ---- Stream end ----
//
// // ---- Scalar multiplication ----
//
// fun crypto_scalarmult(privateKey: Uint8Array, publicKey: Uint8Array) : Uint8Array
// fun crypto_scalarmult_base(privateKey: Uint8Array) : Uint8Array
//
// // ---- Scalar multiplication end ----
}

View File

@ -1,19 +1,61 @@
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
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 sodium : SodiumWrapper
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()
}

View File

@ -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()
}

View File

@ -1,58 +0,0 @@
package com.ionspin.kotlin.crypto.jnitest
import co.libly.resourceloader.FileLoader
import co.libly.resourceloader.ResourceLoader
import com.sun.jna.Library
import com.sun.jna.Native
import com.sun.jna.Platform
import java.io.File
import java.lang.RuntimeException
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 20-Feb-2021
*/
object JniTest {
fun work() : String {
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 loaded = if (Platform.isAndroid()) {
Native.load("sodium", SodiumVersion::class.java) as SodiumVersion
} else {
Native.load(libraryFile.absolutePath, SodiumVersion::class.java) as SodiumVersion
}
println(libraryFile.absoluteFile)
val version = loaded.sodium_version_string()
println("Loaded ${loaded.sodium_version_string()}")
return version
}
}
interface SodiumVersion : Library {
fun sodium_version_string() : String
}

View File

@ -2,8 +2,6 @@ package com.ionspin.kotlin.crypto
import com.goterl.lazycode.lazysodium.LazySodiumJava
import com.goterl.lazycode.lazysodium.SodiumJava
import com.ionspin.kotlin.crypto.jnitest.JniTest
import com.ionspin.kotlin.crypto.jnitest.SodiumVersion
/**
* Created by Ugljesa Jovanovic
@ -11,4 +9,3 @@ import com.ionspin.kotlin.crypto.jnitest.SodiumVersion
* on 22-Aug-2020
*/
typealias SodiumWrapper = SodiumJava
typealias JniTestWrapper = SodiumVersion

View File

@ -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)
}
}

View File

@ -1,18 +0,0 @@
package com.ionspin.kotlin.crypto.jnitest
import org.junit.Test
import kotlin.test.assertEquals
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 20-Feb-2021
*/
class JniTestTest {
@Test
fun testJniTest() {
val result = JniTest.work()
assertEquals("1.0.18", result)
}
}

View File

@ -6,8 +6,9 @@ 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.hash.Hash
import com.ionspin.kotlin.crypto.jnitest.JniTest
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString
import kotlinx.android.synthetic.main.activity_main.*
@ -19,7 +20,7 @@ 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()} \nSodium version: ${JniTest.work()}")
helloWorldTextView.setText("Hash (SHA512) of 123: ${hash.toHexString()} \nSodium version: ${TmpAccessor.getVersion()}")
}