Merge pull request #8 from ionspin/jna-android-and-java
Jna android and java
This commit is contained in:
commit
6db7a828ac
46
README.md
46
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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86/libsodium.so
Executable file
BIN
multiplatform-crypto-libsodium-bindings/src/androidMain/jniLibs/x86/libsodium.so
Executable file
Binary file not shown.
Binary file not shown.
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@ -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 ----
|
||||
|
@ -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()
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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()
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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()
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
// }
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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}")
|
||||
}
|
||||
|
@ -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
|
||||
// }
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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()}")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@ -37,5 +37,5 @@ enableFeaturePreview("GRADLE_METADATA")
|
||||
rootProject.name = "KotlinMultiplatformLibsodium"
|
||||
include("multiplatform-crypto-api")
|
||||
include("multiplatform-crypto-libsodium-bindings")
|
||||
//include("sample")
|
||||
include("sample")
|
||||
|
||||
|
@ -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 |
|
||||
|
Loading…
x
Reference in New Issue
Block a user