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 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
|
## 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
|
#### Gradle
|
||||||
[progress here](https://github.com/ionspin/kotlin-multiplatform-crypto/blob/master/supported_bindings_list.md)
|
```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
|
## 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
|
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
|
// Libsodium initialized
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -125,31 +138,20 @@ Currently supported native platforms:
|
|||||||
|minGW X86 64| :heavy_check_mark: |
|
|minGW X86 64| :heavy_check_mark: |
|
||||||
|minGW X86 32| :x: |
|
|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:
|
### TODO:
|
||||||
- Copy/adapt code documentation, currently only some functions have documentation that is a copy-paste from libsodium website
|
- 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
|
- Android testing
|
||||||
- Fix browser testing, both locally and in CI/CD
|
- 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.
|
- 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
|
- 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:
|
#### Notes for Gitlab runners:
|
||||||
- At the moment all runners need to have android sdk
|
- At the moment all runners need to have android sdk
|
||||||
|
@ -24,14 +24,16 @@ object Versions {
|
|||||||
val dokkaPlugin = "1.4.20"
|
val dokkaPlugin = "1.4.20"
|
||||||
val taskTreePlugin = "1.5"
|
val taskTreePlugin = "1.5"
|
||||||
val kotlinBigNumVersion = "0.2.8-SNAPSHOT"
|
val kotlinBigNumVersion = "0.2.8-SNAPSHOT"
|
||||||
val lazySodium = "4.3.1-SNAPSHOT"
|
val jna = "5.7.0"
|
||||||
val jna = "5.5.0"
|
|
||||||
val kotlinPoet = "1.6.0"
|
val kotlinPoet = "1.6.0"
|
||||||
val libsodiumBindings = "0.1.1-SNAPSHOT"
|
val libsodiumBindings = "0.1.1-SNAPSHOT"
|
||||||
val ktor = "1.3.2"
|
val ktor = "1.3.2"
|
||||||
val timber = "4.7.1"
|
val timber = "4.7.1"
|
||||||
val kodeinVersion = "7.1.0"
|
val kodeinVersion = "7.1.0"
|
||||||
|
|
||||||
|
val resourceLoader = "1.3.10"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -39,7 +41,7 @@ object Versions {
|
|||||||
object ReleaseInfo {
|
object ReleaseInfo {
|
||||||
val group = "com.ionspin.kotlin"
|
val group = "com.ionspin.kotlin"
|
||||||
val version = "0.1.0-SNAPSHOT"
|
val version = "0.1.0-SNAPSHOT"
|
||||||
val bindingsVersion = "0.1.1-SNAPSHOT"
|
val bindingsVersion = "0.8.0-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|
||||||
object Deps {
|
object Deps {
|
||||||
@ -112,11 +114,9 @@ object Deps {
|
|||||||
|
|
||||||
val kotlinPoet = "com.squareup:kotlinpoet:${Versions.kotlinPoet}"
|
val kotlinPoet = "com.squareup:kotlinpoet:${Versions.kotlinPoet}"
|
||||||
|
|
||||||
|
val resourceLoader = "co.libly:resource-loader:${Versions.resourceLoader}"
|
||||||
|
|
||||||
object Delegated {
|
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}"
|
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 ktorClientSerialization = "io.ktor:ktor-client-serialization-jvm:${Versions.ktor}"
|
||||||
val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.kotlinSerialization}"
|
val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.kotlinSerialization}"
|
||||||
val timber = "com.jakewharton.timber:timber:${Versions.timber}"
|
val timber = "com.jakewharton.timber:timber:${Versions.timber}"
|
||||||
|
val jna = "net.java.dev.jna:jna:${Versions.jna}@aar"
|
||||||
}
|
}
|
||||||
|
|
||||||
object Desktop {
|
object Desktop {
|
||||||
|
@ -48,7 +48,6 @@ val sonatypeUsernameEnv: String? = System.getenv()["SONATYPE_USERNAME"]
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven("https://dl.bintray.com/terl/lazysodium-maven")
|
|
||||||
maven {
|
maven {
|
||||||
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
|
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
|
||||||
}
|
}
|
||||||
@ -73,6 +72,9 @@ android {
|
|||||||
isMinifyEnabled = false
|
isMinifyEnabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sourceSets.getByName("main") {
|
||||||
|
// jniLibs.srcDir("src/androidMain/libs")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,9 +82,10 @@ android {
|
|||||||
kotlin {
|
kotlin {
|
||||||
val hostOsName = getHostOsName()
|
val hostOsName = getHostOsName()
|
||||||
android()
|
android()
|
||||||
|
jvm()
|
||||||
runningOnLinuxx86_64 {
|
runningOnLinuxx86_64 {
|
||||||
println("Configuring Linux X86-64 targets")
|
println("Configuring Linux X86-64 targets")
|
||||||
jvm()
|
|
||||||
js(IR) {
|
js(IR) {
|
||||||
browser {
|
browser {
|
||||||
testTask {
|
testTask {
|
||||||
@ -438,14 +441,16 @@ kotlin {
|
|||||||
|
|
||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
isNotRunningInIdea {
|
isNotRunningInIdea {
|
||||||
kotlin.srcDirs("src/androidSpecific", "src/jvmMain/kotlin")
|
kotlin.srcDirs("src/androidMain", "src/androidSpecific", "src/jvmMain/kotlin")
|
||||||
}
|
}
|
||||||
isRunningInIdea {
|
isRunningInIdea {
|
||||||
kotlin.srcDirs("src/androidSpecific")
|
kotlin.srcDirs("src/androidSpecific", "src/jvmMain/kotlin")
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.goterl.lazycode:lazysodium-android:4.2.0@aar")
|
|
||||||
implementation("net.java.dev.jna:jna:5.5.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 {
|
runningOnLinuxx86_64 {
|
||||||
println("Configuring Linux 64 Bit source sets")
|
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 {
|
val jsMain by getting {
|
||||||
@ -678,6 +685,13 @@ tasks {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
tasks.withType(JavaCompile::class) {
|
||||||
|
sourceCompatibility = "1.8"
|
||||||
|
targetCompatibility = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
signing {
|
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
|
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_NONCEBYTES = 8
|
||||||
const val crypto_stream_chacha20_ietf_KEYBYTES = 32
|
const val crypto_stream_chacha20_ietf_KEYBYTES = 32
|
||||||
const val crypto_stream_chacha20_ietf_NONCEBYTES = 12
|
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 {
|
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 chacha20Keygen() : UByteArray
|
||||||
|
|
||||||
|
fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray) : UByteArray
|
||||||
fun chacha20Xor(message : UByteArray, 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 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)
|
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 {
|
expect object LibsodiumUtil {
|
||||||
|
|
||||||
fun memcmp(first: UByteArray, second: UByteArray) : Boolean
|
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(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_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 ----
|
// ---- Stream end ----
|
||||||
|
|
||||||
// ---- Scalar multiplication ----
|
// ---- Scalar multiplication ----
|
||||||
|
@ -79,4 +79,42 @@ actual object Stream {
|
|||||||
|
|
||||||
return result.toUByteArray()
|
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
|
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
|
* Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 02/Aug/2020
|
||||||
*/
|
*/
|
||||||
actual object LibsodiumInitializer {
|
actual object LibsodiumInitializer {
|
||||||
private var isPlatformInitialized = false
|
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() {
|
actual suspend fun initialize() {
|
||||||
sodium = SodiumWrapper()
|
sodiumJna = loadLibrary()
|
||||||
isPlatformInitialized = true
|
isPlatformInitialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun initializeWithCallback(done: () -> Unit) {
|
actual fun initializeWithCallback(done: () -> Unit) {
|
||||||
sodium = SodiumWrapper()
|
sodiumJna = loadLibrary()
|
||||||
isPlatformInitialized = true
|
isPlatformInitialized = true
|
||||||
done()
|
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
|
package com.ionspin.kotlin.crypto.aead
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object AuthenticatedEncryptionWithAssociatedData {
|
actual object AuthenticatedEncryptionWithAssociatedData {
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val ciphertext = UByteArray(message.size + crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
val ciphertext = UByteArray(message.size + crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
||||||
sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
sodiumJna.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
null,
|
null,
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
@ -35,7 +35,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertextAndTag.size - crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
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(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -60,7 +60,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
): AeadEncryptedDataAndTag {
|
): AeadEncryptedDataAndTag {
|
||||||
val ciphertext = UByteArray(message.size)
|
val ciphertext = UByteArray(message.size)
|
||||||
val authenticationTag = UByteArray(crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
val authenticationTag = UByteArray(crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
||||||
sodium.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
|
sodiumJna.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
authenticationTag.asByteArray(),
|
authenticationTag.asByteArray(),
|
||||||
null,
|
null,
|
||||||
@ -83,7 +83,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size)
|
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(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
@ -107,7 +107,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val ciphertext = UByteArray(message.size + crypto_aead_chacha20poly1305_ietf_ABYTES)
|
val ciphertext = UByteArray(message.size + crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
sodium.crypto_aead_chacha20poly1305_ietf_encrypt(
|
sodiumJna.crypto_aead_chacha20poly1305_ietf_encrypt(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
null,
|
null,
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
@ -128,7 +128,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertextAndTag.size - crypto_aead_chacha20poly1305_ietf_ABYTES)
|
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(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -153,7 +153,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
): AeadEncryptedDataAndTag {
|
): AeadEncryptedDataAndTag {
|
||||||
val ciphertext = UByteArray(message.size)
|
val ciphertext = UByteArray(message.size)
|
||||||
val authenticationTag = UByteArray(crypto_aead_chacha20poly1305_ietf_ABYTES)
|
val authenticationTag = UByteArray(crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(
|
sodiumJna.crypto_aead_chacha20poly1305_ietf_encrypt_detached(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
authenticationTag.asByteArray(),
|
authenticationTag.asByteArray(),
|
||||||
null,
|
null,
|
||||||
@ -176,7 +176,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size)
|
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(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
@ -200,7 +200,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val ciphertext = UByteArray(message.size + crypto_aead_chacha20poly1305_ABYTES)
|
val ciphertext = UByteArray(message.size + crypto_aead_chacha20poly1305_ABYTES)
|
||||||
sodium.crypto_aead_chacha20poly1305_encrypt(
|
sodiumJna.crypto_aead_chacha20poly1305_encrypt(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
null,
|
null,
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
@ -221,7 +221,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertextAndTag.size - crypto_aead_chacha20poly1305_ABYTES)
|
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(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -246,7 +246,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
): AeadEncryptedDataAndTag {
|
): AeadEncryptedDataAndTag {
|
||||||
val ciphertext = UByteArray(message.size)
|
val ciphertext = UByteArray(message.size)
|
||||||
val authenticationTag = UByteArray(crypto_aead_chacha20poly1305_ABYTES)
|
val authenticationTag = UByteArray(crypto_aead_chacha20poly1305_ABYTES)
|
||||||
sodium.crypto_aead_chacha20poly1305_encrypt_detached(
|
sodiumJna.crypto_aead_chacha20poly1305_encrypt_detached(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
authenticationTag.asByteArray(),
|
authenticationTag.asByteArray(),
|
||||||
null,
|
null,
|
||||||
@ -269,7 +269,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size)
|
val message = UByteArray(ciphertext.size)
|
||||||
val validationResult = sodium.crypto_aead_chacha20poly1305_decrypt_detached(
|
val validationResult = sodiumJna.crypto_aead_chacha20poly1305_decrypt_detached(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
@ -288,19 +288,19 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
|
|
||||||
actual fun xChaCha20Poly1305IetfKeygen(): UByteArray {
|
actual fun xChaCha20Poly1305IetfKeygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_aead_xchacha20poly1305_ietf_KEYBYTES)
|
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
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun chaCha20Poly1305IetfKeygen(): UByteArray {
|
actual fun chaCha20Poly1305IetfKeygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
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
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun chaCha20Poly1305Keygen(): UByteArray {
|
actual fun chaCha20Poly1305Keygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_aead_chacha20poly1305_KEYBYTES)
|
val generatedKey = UByteArray(crypto_aead_chacha20poly1305_KEYBYTES)
|
||||||
sodium.crypto_aead_chacha20poly1305_keygen(generatedKey.asByteArray())
|
sodiumJna.crypto_aead_chacha20poly1305_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
package com.ionspin.kotlin.crypto.auth
|
package com.ionspin.kotlin.crypto.auth
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object Auth {
|
actual object Auth {
|
||||||
actual fun authKeygen(): UByteArray {
|
actual fun authKeygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_auth_KEYBYTES)
|
val generatedKey = UByteArray(crypto_auth_KEYBYTES)
|
||||||
sodium.crypto_auth_keygen(generatedKey.asByteArray())
|
sodiumJna.crypto_auth_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun auth(message: UByteArray, key: UByteArray): UByteArray {
|
actual fun auth(message: UByteArray, key: UByteArray): UByteArray {
|
||||||
val mac = UByteArray(crypto_auth_BYTES)
|
val mac = UByteArray(crypto_auth_BYTES)
|
||||||
sodium.crypto_auth(
|
sodiumJna.crypto_auth(
|
||||||
mac.asByteArray(),
|
mac.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -21,7 +21,7 @@ actual object Auth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun authVerify(tag: UByteArray, message: UByteArray, key: UByteArray): Boolean {
|
actual fun authVerify(tag: UByteArray, message: UByteArray, key: UByteArray): Boolean {
|
||||||
return sodium.crypto_auth_verify(
|
return sodiumJna.crypto_auth_verify(
|
||||||
tag.asByteArray(),
|
tag.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -31,13 +31,13 @@ actual object Auth {
|
|||||||
|
|
||||||
actual fun authHmacSha256Keygen(): UByteArray {
|
actual fun authHmacSha256Keygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_auth_hmacsha256_KEYBYTES)
|
val generatedKey = UByteArray(crypto_auth_hmacsha256_KEYBYTES)
|
||||||
sodium.crypto_auth_hmacsha256_keygen(generatedKey.asByteArray())
|
sodiumJna.crypto_auth_hmacsha256_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun authHmacSha256(message: UByteArray, key: UByteArray): UByteArray {
|
actual fun authHmacSha256(message: UByteArray, key: UByteArray): UByteArray {
|
||||||
val mac = UByteArray(crypto_auth_hmacsha256_BYTES)
|
val mac = UByteArray(crypto_auth_hmacsha256_BYTES)
|
||||||
sodium.crypto_auth_hmacsha256(
|
sodiumJna.crypto_auth_hmacsha256(
|
||||||
mac.asByteArray(),
|
mac.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -51,7 +51,7 @@ actual object Auth {
|
|||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return sodium.crypto_auth_hmacsha256_verify(
|
return sodiumJna.crypto_auth_hmacsha256_verify(
|
||||||
tag.asByteArray(),
|
tag.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -61,13 +61,13 @@ actual object Auth {
|
|||||||
|
|
||||||
actual fun authHmacSha512Keygen(): UByteArray {
|
actual fun authHmacSha512Keygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_auth_hmacsha512_KEYBYTES)
|
val generatedKey = UByteArray(crypto_auth_hmacsha512_KEYBYTES)
|
||||||
sodium.crypto_auth_hmacsha512_keygen(generatedKey.asByteArray())
|
sodiumJna.crypto_auth_hmacsha512_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun authHmacSha512(message: UByteArray, key: UByteArray): UByteArray {
|
actual fun authHmacSha512(message: UByteArray, key: UByteArray): UByteArray {
|
||||||
val mac = UByteArray(crypto_auth_hmacsha512_BYTES)
|
val mac = UByteArray(crypto_auth_hmacsha512_BYTES)
|
||||||
sodium.crypto_auth_hmacsha512(
|
sodiumJna.crypto_auth_hmacsha512(
|
||||||
mac.asByteArray(),
|
mac.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -81,7 +81,7 @@ actual object Auth {
|
|||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return sodium.crypto_auth_hmacsha512_verify(
|
return sodiumJna.crypto_auth_hmacsha512_verify(
|
||||||
tag.asByteArray(),
|
tag.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.ionspin.kotlin.crypto.box
|
package com.ionspin.kotlin.crypto.box
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object Box {
|
actual object Box {
|
||||||
/**
|
/**
|
||||||
@ -11,7 +11,7 @@ actual object Box {
|
|||||||
actual fun keypair(): BoxKeyPair {
|
actual fun keypair(): BoxKeyPair {
|
||||||
val publicKey = UByteArray(crypto_box_PUBLICKEYBYTES)
|
val publicKey = UByteArray(crypto_box_PUBLICKEYBYTES)
|
||||||
val secretKey = UByteArray(crypto_box_SECRETKEYBYTES)
|
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)
|
return BoxKeyPair(publicKey, secretKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ actual object Box {
|
|||||||
actual fun seedKeypair(seed: UByteArray): BoxKeyPair {
|
actual fun seedKeypair(seed: UByteArray): BoxKeyPair {
|
||||||
val publicKey = UByteArray(crypto_box_PUBLICKEYBYTES)
|
val publicKey = UByteArray(crypto_box_PUBLICKEYBYTES)
|
||||||
val secretKey = UByteArray(crypto_box_SECRETKEYBYTES)
|
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)
|
return BoxKeyPair(publicKey, secretKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ actual object Box {
|
|||||||
sendersSecretKey: UByteArray
|
sendersSecretKey: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val ciphertext = UByteArray(message.size + crypto_box_MACBYTES)
|
val ciphertext = UByteArray(message.size + crypto_box_MACBYTES)
|
||||||
sodium.crypto_box_easy(
|
sodiumJna.crypto_box_easy(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -64,7 +64,7 @@ actual object Box {
|
|||||||
recipientsSecretKey: UByteArray
|
recipientsSecretKey: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size - crypto_box_MACBYTES)
|
val message = UByteArray(ciphertext.size - crypto_box_MACBYTES)
|
||||||
val validationResult = sodium.crypto_box_open_easy(
|
val validationResult = sodiumJna.crypto_box_open_easy(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertext.size.toLong(),
|
||||||
@ -85,7 +85,7 @@ actual object Box {
|
|||||||
*/
|
*/
|
||||||
actual fun beforeNM(publicKey: UByteArray, secretKey: UByteArray): UByteArray {
|
actual fun beforeNM(publicKey: UByteArray, secretKey: UByteArray): UByteArray {
|
||||||
val sessionKey = UByteArray(crypto_box_BEFORENMBYTES)
|
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
|
return sessionKey
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ actual object Box {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val ciphertext = UByteArray(message.size + crypto_box_MACBYTES)
|
val ciphertext = UByteArray(message.size + crypto_box_MACBYTES)
|
||||||
|
|
||||||
sodium.crypto_box_easy_afternm(
|
sodiumJna.crypto_box_easy_afternm(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -119,7 +119,7 @@ actual object Box {
|
|||||||
precomputedKey: UByteArray
|
precomputedKey: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size - crypto_box_MACBYTES)
|
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(),
|
message.asByteArray(),
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertext.size.toLong(),
|
||||||
@ -149,7 +149,7 @@ actual object Box {
|
|||||||
val ciphertext = UByteArray(message.size)
|
val ciphertext = UByteArray(message.size)
|
||||||
val tag = UByteArray(crypto_box_MACBYTES)
|
val tag = UByteArray(crypto_box_MACBYTES)
|
||||||
|
|
||||||
sodium.crypto_box_detached(
|
sodiumJna.crypto_box_detached(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
tag.asByteArray(),
|
tag.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
@ -177,7 +177,7 @@ actual object Box {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size)
|
val message = UByteArray(ciphertext.size)
|
||||||
|
|
||||||
val validationResult = sodium.crypto_box_open_detached(
|
val validationResult = sodiumJna.crypto_box_open_detached(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
tag.asByteArray(),
|
tag.asByteArray(),
|
||||||
@ -196,7 +196,7 @@ actual object Box {
|
|||||||
|
|
||||||
actual fun seal(message: UByteArray, recipientsPublicKey: UByteArray): UByteArray {
|
actual fun seal(message: UByteArray, recipientsPublicKey: UByteArray): UByteArray {
|
||||||
val ciphertextWithPublicKey = UByteArray(message.size + crypto_box_SEALBYTES)
|
val ciphertextWithPublicKey = UByteArray(message.size + crypto_box_SEALBYTES)
|
||||||
sodium.crypto_box_seal(
|
sodiumJna.crypto_box_seal(
|
||||||
ciphertextWithPublicKey.asByteArray(),
|
ciphertextWithPublicKey.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -207,7 +207,7 @@ actual object Box {
|
|||||||
|
|
||||||
actual fun sealOpen(ciphertext: UByteArray, recipientsPublicKey: UByteArray, recipientsSecretKey: UByteArray): UByteArray {
|
actual fun sealOpen(ciphertext: UByteArray, recipientsPublicKey: UByteArray, recipientsSecretKey: UByteArray): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size - crypto_box_SEALBYTES)
|
val message = UByteArray(ciphertext.size - crypto_box_SEALBYTES)
|
||||||
val validationResult = sodium.crypto_box_seal_open(
|
val validationResult = sodiumJna.crypto_box_seal_open(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertext.size.toLong(),
|
||||||
@ -223,4 +223,4 @@ actual object Box {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package com.ionspin.kotlin.crypto.generichash
|
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
|
* Created by Ugljesa Jovanovic
|
||||||
* ugljesa.jovanovic@ionspin.com
|
* ugljesa.jovanovic@ionspin.com
|
||||||
* on 21-Aug-2020
|
* on 21-Aug-2020
|
||||||
*/
|
*/
|
||||||
actual class GenericHashStateInternal(internal val data: ByteArray)
|
actual typealias GenericHashStateInternal = Blake2bState
|
||||||
|
|
||||||
actual object GenericHash {
|
actual object GenericHash {
|
||||||
actual fun genericHash(
|
actual fun genericHash(
|
||||||
@ -16,12 +17,12 @@ actual object GenericHash {
|
|||||||
key: UByteArray?
|
key: UByteArray?
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val hash = UByteArray(requestedHashLength)
|
val hash = UByteArray(requestedHashLength)
|
||||||
sodium.crypto_generichash(
|
sodiumJna.crypto_generichash(
|
||||||
hash.asByteArray(),
|
hash.asByteArray(),
|
||||||
requestedHashLength,
|
requestedHashLength,
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
key?.asByteArray(),
|
key?.asByteArray() ?: ByteArray(0),
|
||||||
(key?.size ?: 0)
|
(key?.size ?: 0)
|
||||||
)
|
)
|
||||||
return hash
|
return hash
|
||||||
@ -31,8 +32,8 @@ actual object GenericHash {
|
|||||||
requestedHashLength: Int,
|
requestedHashLength: Int,
|
||||||
key: UByteArray?
|
key: UByteArray?
|
||||||
): GenericHashState {
|
): GenericHashState {
|
||||||
val state = GenericHashStateInternal(ByteArray(sodium.crypto_generichash_statebytes()))
|
val state = GenericHashStateInternal()
|
||||||
sodium.crypto_generichash_init(state.data, key?.asByteArray(), key?.size ?: 0, requestedHashLength)
|
sodiumJna.crypto_generichash_init(state, key?.asByteArray() ?: ByteArray(0), key?.size ?: 0, requestedHashLength)
|
||||||
return GenericHashState(requestedHashLength, state)
|
return GenericHashState(requestedHashLength, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,18 +41,18 @@ actual object GenericHash {
|
|||||||
state: GenericHashState,
|
state: GenericHashState,
|
||||||
messagePart: UByteArray
|
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 {
|
actual fun genericHashFinal(state: GenericHashState): UByteArray {
|
||||||
val hashResult = ByteArray(state.hashLength)
|
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()
|
return hashResult.asUByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun genericHashKeygen(): UByteArray {
|
actual fun genericHashKeygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_generichash_BYTES)
|
val generatedKey = UByteArray(crypto_generichash_BYTES)
|
||||||
sodium.crypto_generichash_keygen(generatedKey.asByteArray())
|
sodiumJna.crypto_generichash_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
@ -1,54 +1,55 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash
|
package com.ionspin.kotlin.crypto.hash
|
||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.interfaces.Hash
|
import com.ionspin.kotlin.crypto.Hash256State
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.Hash512State
|
||||||
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual typealias Sha256State = Hash.State256
|
actual typealias Sha256State = Hash256State
|
||||||
actual typealias Sha512State = Hash.State512
|
actual typealias Sha512State = Hash512State
|
||||||
|
|
||||||
actual object Hash {
|
actual object Hash {
|
||||||
|
|
||||||
actual fun sha256(data: UByteArray): UByteArray {
|
actual fun sha256(data: UByteArray): UByteArray {
|
||||||
val resultHash = UByteArray(crypto_hash_sha256_BYTES)
|
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
|
return resultHash
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun sha256Init(): Sha256State {
|
actual fun sha256Init(): Sha256State {
|
||||||
val state = Hash.State256()
|
val state = Hash256State()
|
||||||
sodium.crypto_hash_sha256_init(state)
|
sodiumJna.crypto_hash_sha256_init(state)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun sha256Update(state: Sha256State, data: UByteArray) {
|
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 {
|
actual fun sha256Final(state: Sha256State): UByteArray {
|
||||||
val resultHash = UByteArray(crypto_hash_sha256_BYTES)
|
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
|
return resultHash
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun sha512(data: UByteArray): UByteArray {
|
actual fun sha512(data: UByteArray): UByteArray {
|
||||||
val resultHash = UByteArray(crypto_hash_sha512_BYTES)
|
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
|
return resultHash
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun sha512Init(): Sha512State {
|
actual fun sha512Init(): Sha512State {
|
||||||
val state = Hash.State512()
|
val state = Hash512State()
|
||||||
sodium.crypto_hash_sha512_init(state)
|
sodiumJna.crypto_hash_sha512_init(state)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun sha512Update(state: Sha512State, data: UByteArray) {
|
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 {
|
actual fun sha512Final(state: Sha512State): UByteArray {
|
||||||
val resultHash = UByteArray(crypto_hash_sha512_BYTES)
|
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
|
return resultHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.ionspin.kotlin.crypto.kdf
|
package com.ionspin.kotlin.crypto.kdf
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object Kdf {
|
actual object Kdf {
|
||||||
/**
|
/**
|
||||||
@ -26,7 +26,7 @@ actual object Kdf {
|
|||||||
val subkey = UByteArray(subkeyLength)
|
val subkey = UByteArray(subkeyLength)
|
||||||
val contextEncoded = context.encodeToByteArray()
|
val contextEncoded = context.encodeToByteArray()
|
||||||
|
|
||||||
sodium.crypto_kdf_derive_from_key(
|
sodiumJna.crypto_kdf_derive_from_key(
|
||||||
subkey.asByteArray(),
|
subkey.asByteArray(),
|
||||||
subkeyLength,
|
subkeyLength,
|
||||||
subkeyId.toLong(),
|
subkeyId.toLong(),
|
||||||
@ -42,8 +42,8 @@ actual object Kdf {
|
|||||||
*/
|
*/
|
||||||
actual fun keygen(): UByteArray {
|
actual fun keygen(): UByteArray {
|
||||||
val masterKey = UByteArray(crypto_kdf_KEYBYTES)
|
val masterKey = UByteArray(crypto_kdf_KEYBYTES)
|
||||||
sodium.crypto_kdf_keygen(masterKey.asByteArray())
|
sodiumJna.crypto_kdf_keygen(masterKey.asByteArray())
|
||||||
return masterKey
|
return masterKey
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package com.ionspin.kotlin.crypto.keyexchange
|
package com.ionspin.kotlin.crypto.keyexchange
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object KeyExchange {
|
actual object KeyExchange {
|
||||||
actual fun clientSessionKeys(clientPublicKey: UByteArray, clientSecretKey: UByteArray, serverPublicKey: UByteArray) : KeyExchangeSessionKeyPair {
|
actual fun clientSessionKeys(clientPublicKey: UByteArray, clientSecretKey: UByteArray, serverPublicKey: UByteArray) : KeyExchangeSessionKeyPair {
|
||||||
val receiveKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
val receiveKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
||||||
val sendKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
val sendKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
||||||
|
|
||||||
sodium.crypto_kx_client_session_keys(
|
sodiumJna.crypto_kx_client_session_keys(
|
||||||
receiveKey.asByteArray(),
|
receiveKey.asByteArray(),
|
||||||
sendKey.asByteArray(),
|
sendKey.asByteArray(),
|
||||||
clientPublicKey.asByteArray(),
|
clientPublicKey.asByteArray(),
|
||||||
@ -25,7 +25,7 @@ actual object KeyExchange {
|
|||||||
val secretKey = UByteArray(crypto_kx_SECRETKEYBYTES)
|
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)
|
return KeyExchangeKeyPair(publicKey, secretKey)
|
||||||
@ -35,7 +35,7 @@ actual object KeyExchange {
|
|||||||
val publicKey = UByteArray(crypto_kx_PUBLICKEYBYTES)
|
val publicKey = UByteArray(crypto_kx_PUBLICKEYBYTES)
|
||||||
val secretKey = UByteArray(crypto_kx_SECRETKEYBYTES)
|
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)
|
return KeyExchangeKeyPair(publicKey, secretKey)
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ actual object KeyExchange {
|
|||||||
val receiveKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
val receiveKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
||||||
val sendKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
val sendKey = UByteArray(crypto_kx_SESSIONKEYBYTES)
|
||||||
|
|
||||||
sodium.crypto_kx_server_session_keys(
|
sodiumJna.crypto_kx_server_session_keys(
|
||||||
receiveKey.asByteArray(),
|
receiveKey.asByteArray(),
|
||||||
sendKey.asByteArray(),
|
sendKey.asByteArray(),
|
||||||
serverPublicKey.asByteArray(),
|
serverPublicKey.asByteArray(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.ionspin.kotlin.crypto.pwhash
|
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
|
import com.sun.jna.NativeLong
|
||||||
|
|
||||||
actual object PasswordHash {
|
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
|
* 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.
|
* 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(
|
actual fun pwhash(
|
||||||
outputLength: Int,
|
outputLength: Int,
|
||||||
@ -22,14 +22,14 @@ actual object PasswordHash {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val hashedPassword = UByteArray(outputLength)
|
val hashedPassword = UByteArray(outputLength)
|
||||||
|
|
||||||
sodium.crypto_pwhash(
|
sodiumJna.crypto_pwhash(
|
||||||
hashedPassword.asByteArray(),
|
hashedPassword.asByteArray(),
|
||||||
outputLength.toLong(),
|
outputLength.toLong(),
|
||||||
password.encodeToByteArray(),
|
password,
|
||||||
password.length.toLong(),
|
password.length.toLong(),
|
||||||
salt.asByteArray(),
|
salt.asByteArray(),
|
||||||
opsLimit.toLong(),
|
opsLimit.toLong(),
|
||||||
NativeLong(memLimit.toLong()),
|
memLimit.toLong(),
|
||||||
algorithm
|
algorithm
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,12 +48,12 @@ actual object PasswordHash {
|
|||||||
*/
|
*/
|
||||||
actual fun str(password: String, opslimit: ULong, memlimit: Int): UByteArray {
|
actual fun str(password: String, opslimit: ULong, memlimit: Int): UByteArray {
|
||||||
val output = ByteArray(crypto_pwhash_STRBYTES)
|
val output = ByteArray(crypto_pwhash_STRBYTES)
|
||||||
sodium.crypto_pwhash_str(
|
sodiumJna.crypto_pwhash_str(
|
||||||
output,
|
output,
|
||||||
password.encodeToByteArray(),
|
password,
|
||||||
password.length.toLong(),
|
password.length.toLong(),
|
||||||
opslimit.toLong(),
|
opslimit.toLong(),
|
||||||
NativeLong(memlimit.toLong())
|
memlimit.toLong()
|
||||||
)
|
)
|
||||||
return output.asUByteArray()
|
return output.asUByteArray()
|
||||||
}
|
}
|
||||||
@ -69,10 +69,10 @@ actual object PasswordHash {
|
|||||||
opslimit: ULong,
|
opslimit: ULong,
|
||||||
memlimit: Int
|
memlimit: Int
|
||||||
): Int {
|
): Int {
|
||||||
return sodium.crypto_pwhash_str_needs_rehash(
|
return sodiumJna.crypto_pwhash_str_needs_rehash(
|
||||||
passwordHash.asByteArray(),
|
passwordHash.asByteArray(),
|
||||||
opslimit.toLong(),
|
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.
|
* It returns 0 if the verification succeeds, and -1 on error.
|
||||||
*/
|
*/
|
||||||
actual fun strVerify(passwordHash: UByteArray, password: String): Boolean {
|
actual fun strVerify(passwordHash: UByteArray, password: String): Boolean {
|
||||||
val result = sodium.crypto_pwhash_str_verify(
|
val result = sodiumJna.crypto_pwhash_str_verify(
|
||||||
passwordHash.asByteArray(),
|
passwordHash.asByteArray(),
|
||||||
password.encodeToByteArray(),
|
password,
|
||||||
password.length.toLong()
|
password.length.toLong()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.ionspin.kotlin.crypto.scalarmult
|
package com.ionspin.kotlin.crypto.scalarmult
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object ScalarMultiplication {
|
actual object ScalarMultiplication {
|
||||||
/**
|
/**
|
||||||
@ -18,7 +18,7 @@ actual object ScalarMultiplication {
|
|||||||
actual fun scalarMultiplication(secretKeyN: UByteArray, publicKeyP: UByteArray): UByteArray {
|
actual fun scalarMultiplication(secretKeyN: UByteArray, publicKeyP: UByteArray): UByteArray {
|
||||||
val result = UByteArray(crypto_scalarmult_BYTES)
|
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
|
return result
|
||||||
@ -35,7 +35,7 @@ actual object ScalarMultiplication {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val result = UByteArray(crypto_scalarmult_BYTES)
|
val result = UByteArray(crypto_scalarmult_BYTES)
|
||||||
|
|
||||||
sodium.crypto_scalarmult_base(result.asByteArray(), secretKeyN.asByteArray())
|
sodiumJna.crypto_scalarmult_base(result.asByteArray(), secretKeyN.asByteArray())
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package com.ionspin.kotlin.crypto.secretbox
|
package com.ionspin.kotlin.crypto.secretbox
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object SecretBox {
|
actual object SecretBox {
|
||||||
actual fun easy(message: UByteArray, nonce: UByteArray, key: UByteArray): UByteArray {
|
actual fun easy(message: UByteArray, nonce: UByteArray, key: UByteArray): UByteArray {
|
||||||
val ciphertext = UByteArray(message.size + crypto_secretbox_MACBYTES)
|
val ciphertext = UByteArray(message.size + crypto_secretbox_MACBYTES)
|
||||||
sodium.crypto_secretbox_easy(
|
sodiumJna.crypto_secretbox_easy(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -21,7 +21,7 @@ actual object SecretBox {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val decrypted = UByteArray(ciphertext.size - crypto_secretbox_MACBYTES)
|
val decrypted = UByteArray(ciphertext.size - crypto_secretbox_MACBYTES)
|
||||||
val validationResult = sodium.crypto_secretbox_open_easy(
|
val validationResult = sodiumJna.crypto_secretbox_open_easy(
|
||||||
decrypted.asByteArray(),
|
decrypted.asByteArray(),
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertext.size.toLong(),
|
||||||
@ -41,7 +41,7 @@ actual object SecretBox {
|
|||||||
): SecretBoxEncryptedDataAndTag {
|
): SecretBoxEncryptedDataAndTag {
|
||||||
val ciphertext = UByteArray(message.size)
|
val ciphertext = UByteArray(message.size)
|
||||||
val authenticationTag = UByteArray(crypto_secretbox_MACBYTES)
|
val authenticationTag = UByteArray(crypto_secretbox_MACBYTES)
|
||||||
sodium.crypto_secretbox_detached(
|
sodiumJna.crypto_secretbox_detached(
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
authenticationTag.asByteArray(),
|
authenticationTag.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
@ -59,7 +59,7 @@ actual object SecretBox {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size)
|
val message = UByteArray(ciphertext.size)
|
||||||
val validationResult = sodium.crypto_secretbox_open_detached(
|
val validationResult = sodiumJna.crypto_secretbox_open_detached(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
tag.asByteArray(),
|
tag.asByteArray(),
|
||||||
@ -75,7 +75,7 @@ actual object SecretBox {
|
|||||||
|
|
||||||
actual fun keygen() : UByteArray {
|
actual fun keygen() : UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_secretbox_KEYBYTES)
|
val generatedKey = UByteArray(crypto_secretbox_KEYBYTES)
|
||||||
sodium.crypto_secretbox_keygen(generatedKey.asByteArray())
|
sodiumJna.crypto_secretbox_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package com.ionspin.kotlin.crypto.secretstream
|
package com.ionspin.kotlin.crypto.secretstream
|
||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.interfaces.SecretStream
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.SecretStreamXChaCha20Poly1305State
|
||||||
|
|
||||||
actual typealias SecretStreamState = SecretStream.State
|
actual typealias SecretStreamState = SecretStreamXChaCha20Poly1305State
|
||||||
|
|
||||||
actual object SecretStream {
|
actual object SecretStream {
|
||||||
actual fun xChaCha20Poly1305InitPush(key: UByteArray): SecretStreamStateAndHeader {
|
actual fun xChaCha20Poly1305InitPush(key: UByteArray): SecretStreamStateAndHeader {
|
||||||
val state = SecretStreamState()
|
val state = SecretStreamState()
|
||||||
val header = UByteArray(sodium.crypto_secretstream_xchacha20poly1305_headerbytes())
|
val header = UByteArray(sodiumJna.crypto_secretstream_xchacha20poly1305_headerbytes())
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray())
|
sodiumJna.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray())
|
||||||
return SecretStreamStateAndHeader(state, header)
|
return SecretStreamStateAndHeader(state, header)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ actual object SecretStream {
|
|||||||
tag: UByte
|
tag: UByte
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val ciphertext = UByteArray(message.size + crypto_secretstream_xchacha20poly1305_ABYTES)
|
val ciphertext = UByteArray(message.size + crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_push(
|
sodiumJna.crypto_secretstream_xchacha20poly1305_push(
|
||||||
state,
|
state,
|
||||||
ciphertext.asByteArray(),
|
ciphertext.asByteArray(),
|
||||||
null,
|
null,
|
||||||
@ -38,7 +38,7 @@ actual object SecretStream {
|
|||||||
header: UByteArray
|
header: UByteArray
|
||||||
): SecretStreamStateAndHeader {
|
): SecretStreamStateAndHeader {
|
||||||
val state = SecretStreamState()
|
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)
|
return SecretStreamStateAndHeader(state, header)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ actual object SecretStream {
|
|||||||
): DecryptedDataAndTag {
|
): DecryptedDataAndTag {
|
||||||
val result = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES)
|
val result = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
val tagArray = UByteArray(1) { 0U }
|
val tagArray = UByteArray(1) { 0U }
|
||||||
val validationResult = sodium.crypto_secretstream_xchacha20poly1305_pull(
|
val validationResult = sodiumJna.crypto_secretstream_xchacha20poly1305_pull(
|
||||||
state,
|
state,
|
||||||
result.asByteArray(),
|
result.asByteArray(),
|
||||||
null,
|
null,
|
||||||
@ -67,12 +67,12 @@ actual object SecretStream {
|
|||||||
|
|
||||||
actual fun xChaCha20Poly1305Keygen(): UByteArray {
|
actual fun xChaCha20Poly1305Keygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_secretstream_xchacha20poly1305_KEYBYTES)
|
val generatedKey = UByteArray(crypto_secretstream_xchacha20poly1305_KEYBYTES)
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_keygen(generatedKey.asByteArray())
|
sodiumJna.crypto_secretstream_xchacha20poly1305_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun xChaCha20Poly1305Rekey(state: SecretStreamState) {
|
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
|
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
|
* Created by Ugljesa Jovanovic
|
||||||
@ -12,13 +13,13 @@ import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
|||||||
actual object ShortHash {
|
actual object ShortHash {
|
||||||
actual fun shortHash(data: UByteArray, key: UByteArray): UByteArray {
|
actual fun shortHash(data: UByteArray, key: UByteArray): UByteArray {
|
||||||
val hashResult = UByteArray(crypto_shorthash_BYTES)
|
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
|
return hashResult
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun shortHashKeygen(): UByteArray {
|
actual fun shortHashKeygen(): UByteArray {
|
||||||
val key = UByteArray(crypto_shorthash_KEYBYTES)
|
val key = UByteArray(crypto_shorthash_KEYBYTES)
|
||||||
sodium.crypto_shorthash_keygen(key.asByteArray())
|
sodiumJna.crypto_shorthash_keygen(key.asByteArray())
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.ionspin.kotlin.crypto.signature
|
package com.ionspin.kotlin.crypto.signature
|
||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.interfaces.Sign
|
import com.ionspin.kotlin.crypto.Ed25519SignatureState
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual typealias SignatureState = Sign.StateCryptoSign
|
actual typealias SignatureState = Ed25519SignatureState
|
||||||
|
|
||||||
actual object Signature {
|
actual object Signature {
|
||||||
actual fun init(): SignatureState {
|
actual fun init(): SignatureState {
|
||||||
@ -11,7 +11,7 @@ actual object Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun update(state: SignatureState, data: UByteArray) {
|
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(
|
actual fun finalCreate(
|
||||||
@ -19,7 +19,7 @@ actual object Signature {
|
|||||||
secretKey: UByteArray
|
secretKey: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val signature = UByteArray(crypto_sign_BYTES)
|
val signature = UByteArray(crypto_sign_BYTES)
|
||||||
sodium.crypto_sign_final_create(
|
sodiumJna.crypto_sign_final_create(
|
||||||
state,
|
state,
|
||||||
signature.asByteArray(),
|
signature.asByteArray(),
|
||||||
null,
|
null,
|
||||||
@ -33,7 +33,7 @@ actual object Signature {
|
|||||||
signature: UByteArray,
|
signature: UByteArray,
|
||||||
publicKey: UByteArray
|
publicKey: UByteArray
|
||||||
) {
|
) {
|
||||||
val verificationResult = sodium.crypto_sign_final_verify(
|
val verificationResult = sodiumJna.crypto_sign_final_verify(
|
||||||
state,
|
state,
|
||||||
signature.asByteArray(),
|
signature.asByteArray(),
|
||||||
publicKey.asByteArray()
|
publicKey.asByteArray()
|
||||||
@ -50,7 +50,7 @@ actual object Signature {
|
|||||||
actual fun keypair(): SignatureKeyPair {
|
actual fun keypair(): SignatureKeyPair {
|
||||||
val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES)
|
val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES)
|
||||||
val secretKey = UByteArray(crypto_sign_SECRETKEYBYTES)
|
val secretKey = UByteArray(crypto_sign_SECRETKEYBYTES)
|
||||||
sodium.crypto_sign_keypair(
|
sodiumJna.crypto_sign_keypair(
|
||||||
publicKey.asByteArray(),
|
publicKey.asByteArray(),
|
||||||
secretKey.asByteArray(),
|
secretKey.asByteArray(),
|
||||||
)
|
)
|
||||||
@ -65,9 +65,9 @@ actual object Signature {
|
|||||||
actual fun seedKeypair(seed: UByteArray): SignatureKeyPair {
|
actual fun seedKeypair(seed: UByteArray): SignatureKeyPair {
|
||||||
val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES)
|
val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES)
|
||||||
val secretKey = UByteArray(crypto_sign_SECRETKEYBYTES)
|
val secretKey = UByteArray(crypto_sign_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
|
||||||
sodium.crypto_sign_seed_keypair(
|
sodiumJna.crypto_sign_seed_keypair(
|
||||||
publicKey.asByteArray(),
|
publicKey.asByteArray(),
|
||||||
secretKey.asByteArray(),
|
secretKey.asByteArray(),
|
||||||
seed.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 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 sodium.crypto_sign_BYTES + mlen bytes long.
|
* 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 {
|
actual fun sign(message: UByteArray, secretKey: UByteArray): UByteArray {
|
||||||
val signedMessage = UByteArray(message.size + crypto_sign_BYTES)
|
val signedMessage = UByteArray(message.size + crypto_sign_BYTES)
|
||||||
|
|
||||||
sodium.crypto_sign(
|
sodiumJna.crypto_sign(
|
||||||
signedMessage.asByteArray(),
|
signedMessage.asByteArray(),
|
||||||
null,
|
null,
|
||||||
message.asByteArray(),
|
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
|
* If the signature is doesn't appear to be valid, the function throws an exception
|
||||||
*/
|
*/
|
||||||
actual fun open(signedMessage: UByteArray, publicKey: UByteArray): UByteArray {
|
actual fun open(signedMessage: UByteArray, publicKey: UByteArray): UByteArray {
|
||||||
val message = UByteArray(signedMessage.size - crypto_sign_BYTES)
|
val message = UByteArray(signedMessage.size - crypto_sign_BYTES)
|
||||||
|
|
||||||
val verificationResult = sodium.crypto_sign_open(
|
val verificationResult = sodiumJna.crypto_sign_open(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
signedMessage.asByteArray(),
|
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.
|
* 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,
|
* 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 sodium.crypto_sign_BYTES bytes long.
|
* 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 {
|
actual fun detached(message: UByteArray, secretKey: UByteArray): UByteArray {
|
||||||
val signature = UByteArray(crypto_sign_BYTES)
|
val signature = UByteArray(crypto_sign_BYTES)
|
||||||
|
|
||||||
sodium.crypto_sign_detached(
|
sodiumJna.crypto_sign_detached(
|
||||||
signature.asByteArray(),
|
signature.asByteArray(),
|
||||||
null,
|
null,
|
||||||
message.asByteArray(),
|
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.
|
* is mlen bytes, using the signer's public key pk.
|
||||||
*/
|
*/
|
||||||
actual fun verifyDetached(
|
actual fun verifyDetached(
|
||||||
@ -142,7 +142,7 @@ actual object Signature {
|
|||||||
publicKey: UByteArray
|
publicKey: UByteArray
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val verificationResult = sodium.crypto_sign_verify_detached(
|
val verificationResult = sodiumJna.crypto_sign_verify_detached(
|
||||||
signature.asByteArray(),
|
signature.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
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 {
|
actual fun ed25519PkToCurve25519(ed25519PublicKey: UByteArray) : UByteArray {
|
||||||
val x25519PublicKey = UByteArray(crypto_scalarmult_curve25519_BYTES)
|
val x25519PublicKey = UByteArray(crypto_scalarmult_curve25519_BYTES)
|
||||||
sodium.crypto_sign_ed25519_sk_to_curve25519(
|
sodiumJna.crypto_sign_ed25519_sk_to_curve25519(
|
||||||
x25519PublicKey.asByteArray(),
|
x25519PublicKey.asByteArray(),
|
||||||
ed25519PublicKey.asByteArray()
|
ed25519PublicKey.asByteArray()
|
||||||
)
|
)
|
||||||
@ -168,7 +168,7 @@ actual object Signature {
|
|||||||
|
|
||||||
actual fun ed25519SkToCurve25519(ed25519SecretKey: UByteArray) : UByteArray {
|
actual fun ed25519SkToCurve25519(ed25519SecretKey: UByteArray) : UByteArray {
|
||||||
val x25519SecretKey = UByteArray(crypto_scalarmult_curve25519_BYTES)
|
val x25519SecretKey = UByteArray(crypto_scalarmult_curve25519_BYTES)
|
||||||
sodium.crypto_sign_ed25519_sk_to_curve25519(
|
sodiumJna.crypto_sign_ed25519_sk_to_curve25519(
|
||||||
x25519SecretKey.asByteArray(),
|
x25519SecretKey.asByteArray(),
|
||||||
ed25519SecretKey.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.
|
* 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 {
|
actual fun ed25519SkToSeed(secretKey: UByteArray): UByteArray {
|
||||||
val seed = UByteArray(crypto_sign_SEEDBYTES)
|
val seed = UByteArray(crypto_sign_SEEDBYTES)
|
||||||
|
|
||||||
sodium.crypto_sign_ed25519_sk_to_seed(
|
sodiumJna.crypto_sign_ed25519_sk_to_seed(
|
||||||
seed.asByteArray(),
|
seed.asByteArray(),
|
||||||
secretKey.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.
|
* 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 {
|
actual fun ed25519SkToPk(secretKey: UByteArray): UByteArray {
|
||||||
val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES)
|
val publicKey = UByteArray(crypto_sign_PUBLICKEYBYTES)
|
||||||
|
|
||||||
sodium.crypto_sign_ed25519_sk_to_pk(
|
sodiumJna.crypto_sign_ed25519_sk_to_pk(
|
||||||
publicKey.asByteArray(),
|
publicKey.asByteArray(),
|
||||||
secretKey.asByteArray()
|
secretKey.asByteArray()
|
||||||
)
|
)
|
||||||
@ -206,4 +206,4 @@ actual object Signature {
|
|||||||
return publicKey
|
return publicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package com.ionspin.kotlin.crypto.stream
|
package com.ionspin.kotlin.crypto.stream
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
actual object Stream {
|
actual object Stream {
|
||||||
actual fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray): UByteArray {
|
actual fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray): UByteArray {
|
||||||
val result = UByteArray(clen)
|
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
|
return result
|
||||||
}
|
}
|
||||||
@ -18,7 +18,7 @@ actual object Stream {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val result = UByteArray(message.size)
|
val result = UByteArray(message.size)
|
||||||
|
|
||||||
sodium.crypto_stream_chacha20_ietf_xor(
|
sodiumJna.crypto_stream_chacha20_ietf_xor(
|
||||||
result.asByteArray(),
|
result.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -37,7 +37,7 @@ actual object Stream {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val result = UByteArray(message.size)
|
val result = UByteArray(message.size)
|
||||||
|
|
||||||
sodium.crypto_stream_chacha20_ietf_xor_ic(
|
sodiumJna.crypto_stream_chacha20_ietf_xor_ic(
|
||||||
result.asByteArray(),
|
result.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -52,7 +52,7 @@ actual object Stream {
|
|||||||
actual fun chacha20Keygen(): UByteArray {
|
actual fun chacha20Keygen(): UByteArray {
|
||||||
val result = UByteArray(crypto_stream_chacha20_KEYBYTES)
|
val result = UByteArray(crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
sodium.crypto_stream_chacha20_keygen(result.asByteArray())
|
sodiumJna.crypto_stream_chacha20_keygen(result.asByteArray())
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ actual object Stream {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val result = UByteArray(message.size)
|
val result = UByteArray(message.size)
|
||||||
|
|
||||||
sodium.crypto_stream_chacha20_xor(
|
sodiumJna.crypto_stream_chacha20_xor(
|
||||||
result.asByteArray(),
|
result.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -83,7 +83,7 @@ actual object Stream {
|
|||||||
): UByteArray {
|
): UByteArray {
|
||||||
val result = UByteArray(message.size)
|
val result = UByteArray(message.size)
|
||||||
|
|
||||||
sodium.crypto_stream_chacha20_xor_ic(
|
sodiumJna.crypto_stream_chacha20_xor_ic(
|
||||||
result.asByteArray(),
|
result.asByteArray(),
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
message.size.toLong(),
|
message.size.toLong(),
|
||||||
@ -95,4 +95,50 @@ actual object Stream {
|
|||||||
|
|
||||||
return result
|
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
|
package com.ionspin.kotlin.crypto.util
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodiumJna
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
@ -13,7 +13,7 @@ actual object LibsodiumRandom {
|
|||||||
*/
|
*/
|
||||||
actual fun buf(size: Int): UByteArray {
|
actual fun buf(size: Int): UByteArray {
|
||||||
val result = ByteArray(size)
|
val result = ByteArray(size)
|
||||||
sodium.randombytes_buf(result, size)
|
sodiumJna.randombytes_buf(result, size)
|
||||||
return result.asUByteArray()
|
return result.asUByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ actual object LibsodiumRandom {
|
|||||||
*/
|
*/
|
||||||
actual fun bufDeterministic(size: Int, seed: UByteArray): UByteArray {
|
actual fun bufDeterministic(size: Int, seed: UByteArray): UByteArray {
|
||||||
val result = ByteArray(size)
|
val result = ByteArray(size)
|
||||||
sodium.randombytes_buf_deterministic(result, size, seed.asByteArray())
|
sodiumJna.randombytes_buf_deterministic(result, size, seed.asByteArray())
|
||||||
return result.asUByteArray()
|
return result.asUByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,9 +35,7 @@ actual object LibsodiumRandom {
|
|||||||
* The randombytes_random() function returns an unpredictable value between 0 and 0xffffffff (included).
|
* The randombytes_random() function returns an unpredictable value between 0 and 0xffffffff (included).
|
||||||
*/
|
*/
|
||||||
actual fun random(): UInt {
|
actual fun random(): UInt {
|
||||||
//Broken in lazysodium-java https://github.com/terl/lazysodium-java/issues/86
|
return sodiumJna.randombytes_random().toUInt()
|
||||||
//Using temporary forked and fixed build until pull request is accepted in original repo
|
|
||||||
return sodium.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
|
* 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 {
|
actual fun uniform(upperBound: UInt): UInt {
|
||||||
//Broken in lazysodium-java https://github.com/terl/lazysodium-java/issues/86
|
return sodiumJna.randombytes_uniform(upperBound.toLong()).toUInt()
|
||||||
//Using temporary fixed build until pull request is accepted
|
|
||||||
return sodium.randombytes_uniform(upperBound.toInt()).toUInt()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.ionspin.kotlin.crypto.util
|
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.lang.RuntimeException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -9,100 +10,63 @@ actual object LibsodiumUtil {
|
|||||||
if (first.size != second.size) {
|
if (first.size != second.size) {
|
||||||
throw RuntimeException("Sodium memcmp() only supports comparing same length arrays")
|
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) {
|
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 {
|
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
|
val newPadSizeReference = IntByReference(0)
|
||||||
// while libsodium expects 1 byte char array
|
val newSize = ((unpaddedData.size / blocksize) + 1) * blocksize
|
||||||
// See https://github.com/terl/lazysodium-java/issues/85
|
val paddedArray = UByteArray(newSize) {
|
||||||
|
if (it < unpaddedData.size) {
|
||||||
//This is temporary solution until lazysodium is fixed
|
unpaddedData[it]
|
||||||
if (blocksize == 0) {
|
} else {
|
||||||
throw RuntimeException("Invalid block size: $blocksize")
|
0U
|
||||||
}
|
|
||||||
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 resultCode = sodiumJna.sodium_pad(
|
||||||
|
newPadSizeReference.pointer,
|
||||||
|
paddedArray.asByteArray(),
|
||||||
|
unpaddedData.size,
|
||||||
|
blocksize,
|
||||||
|
newSize
|
||||||
|
)
|
||||||
|
if (resultCode != 0) {
|
||||||
|
throw RuntimeException("Padding failed")
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return paddedArray.slice(0 until newPadSizeReference.value).map { it.toByte().toUByte()}.toUByteArray()
|
||||||
|
|
||||||
// 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()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun unpad(paddedData: UByteArray, blocksize: Int): UByteArray {
|
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
|
val paddedDataCopy = paddedData.copyOf().asByteArray()
|
||||||
// while libsodium expects 1 byte char array
|
var unpaddedSize = IntByReference(0)
|
||||||
// See https://github.com/terl/lazysodium-java/issues/85
|
|
||||||
|
|
||||||
//This is temporary solution until lazysodium is fixed
|
sodiumJna.sodium_unpad(
|
||||||
|
unpaddedSize.pointer,
|
||||||
|
paddedDataCopy,
|
||||||
|
paddedData.size,
|
||||||
|
blocksize
|
||||||
|
)
|
||||||
|
|
||||||
val unpaddedData = paddedData.dropLastWhile { it == 0U.toUByte() }
|
val unpadded = paddedDataCopy.sliceArray(0 until unpaddedSize.value).asUByteArray()
|
||||||
if (unpaddedData.last() != 0x80U.toUByte()) {
|
|
||||||
throw RuntimeException("Invalid padding!")
|
|
||||||
}
|
|
||||||
return unpaddedData.dropLast(1).toUByteArray()
|
|
||||||
|
|
||||||
|
return unpadded
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun toBase64(
|
actual fun toBase64(
|
||||||
data: UByteArray,
|
data: UByteArray,
|
||||||
variant: Base64Variants
|
variant: Base64Variants
|
||||||
): String {
|
): 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 }
|
val result = ByteArray(maxlen) { 0 }
|
||||||
sodium.sodium_bin2base64(
|
sodiumJna.sodium_bin2base64(
|
||||||
result,
|
result,
|
||||||
maxlen,
|
maxlen,
|
||||||
data.asByteArray(),
|
data.asByteArray(),
|
||||||
@ -116,49 +80,66 @@ actual object LibsodiumUtil {
|
|||||||
actual fun toHex(data: UByteArray): String {
|
actual fun toHex(data: UByteArray): String {
|
||||||
val hexLen = (data.size * 2) + 1 // +1 for terminator char
|
val hexLen = (data.size * 2) + 1 // +1 for terminator char
|
||||||
val result = ByteArray(hexLen)
|
val result = ByteArray(hexLen)
|
||||||
sodium.sodium_bin2hex(
|
sodiumJna.sodium_bin2hex(
|
||||||
result,
|
result,
|
||||||
hexLen,
|
hexLen,
|
||||||
data.asByteArray(),
|
data.asByteArray(),
|
||||||
data.size
|
data.size
|
||||||
)
|
)
|
||||||
|
|
||||||
//Drop terminating char \0
|
//Drop terminating char \0
|
||||||
return String(result.sliceArray(0 until result.size - 1))
|
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(
|
actual fun fromBase64(
|
||||||
data: String,
|
data: String,
|
||||||
variant: Base64Variants
|
variant: Base64Variants
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
// from base64 is currently broken in lazysodium-java
|
val binLengthReference = IntByReference(0)
|
||||||
// see https://github.com/terl/lazysodium-java/issues/83
|
val maxLength = (data.length * 3) / 4
|
||||||
// val maxLength = (data.length * 3) / 4
|
val intermediaryResult = UByteArray(maxLength) { 0U }
|
||||||
// val intermediaryResult = UByteArray(maxLength) { 0U }
|
|
||||||
//
|
val resultCode = sodiumJna.sodium_base642bin(
|
||||||
// sodium.sodium_base642bin(
|
intermediaryResult.asByteArray(),
|
||||||
// intermediaryResult.asByteArray(),
|
maxLength,
|
||||||
// maxLength,
|
data.encodeToByteArray(),
|
||||||
// data.encodeToByteArray(),
|
data.length,
|
||||||
// data.length,
|
null,
|
||||||
// null,
|
binLengthReference.pointer,
|
||||||
// binLenPinned.addressOf(0),
|
null,
|
||||||
// null,
|
variant.value
|
||||||
// variant.value
|
)
|
||||||
//
|
|
||||||
// )
|
if (resultCode != 0) {
|
||||||
val decoder = when(variant) {
|
throw ConversionException()
|
||||||
Base64Variants.ORIGINAL -> Base64.getDecoder()
|
|
||||||
Base64Variants.ORIGINAL_NO_PADDING -> Base64.getDecoder()
|
|
||||||
Base64Variants.URLSAFE -> Base64.getUrlDecoder()
|
|
||||||
Base64Variants.URLSAFE_NO_PADDING -> Base64.getUrlDecoder()
|
|
||||||
}
|
}
|
||||||
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
|
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
|
package com.ionspin.kotlin.crypto.secretstream
|
||||||
|
|
||||||
actual fun modifyState(state: SecretStreamState, forceNonce: UByteArray) {
|
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}")
|
println("Nonce modified ${state.nonce}")
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package com.ionspin.kotlin.crypto.stream
|
|||||||
import com.ionspin.kotlin.crypto.util.toPtr
|
import com.ionspin.kotlin.crypto.util.toPtr
|
||||||
import kotlinx.cinterop.convert
|
import kotlinx.cinterop.convert
|
||||||
import kotlinx.cinterop.pin
|
import kotlinx.cinterop.pin
|
||||||
import libsodium.crypto_stream_KEYBYTES
|
|
||||||
import libsodium.crypto_stream_chacha20
|
import libsodium.crypto_stream_chacha20
|
||||||
import libsodium.crypto_stream_chacha20_ietf_xor
|
import libsodium.crypto_stream_chacha20_ietf_xor
|
||||||
import libsodium.crypto_stream_chacha20_ietf_xor_ic
|
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
|
||||||
import libsodium.crypto_stream_chacha20_xor_ic
|
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 object Stream {
|
||||||
actual fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray): UByteArray {
|
actual fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray): UByteArray {
|
||||||
val result = UByteArray(clen)
|
val result = UByteArray(clen)
|
||||||
@ -149,4 +152,71 @@ actual object Stream {
|
|||||||
|
|
||||||
return result
|
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()
|
android()
|
||||||
runningOnLinuxx86_64 {
|
runningOnLinuxx86_64 {
|
||||||
jvm()
|
jvm()
|
||||||
js {
|
js(IR) {
|
||||||
browser {
|
browser {
|
||||||
webpackTask {
|
webpackTask {
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ kotlin {
|
|||||||
implementation(kotlin(Deps.Common.test))
|
implementation(kotlin(Deps.Common.test))
|
||||||
implementation(Deps.Common.kotlinBigNum)
|
implementation(Deps.Common.kotlinBigNum)
|
||||||
implementation(Deps.Common.serialization)
|
implementation(Deps.Common.serialization)
|
||||||
api(Deps.Common.libsodiumBindings)
|
api(project(":multiplatform-crypto-libsodium-bindings"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val commonTest by getting {
|
val commonTest by getting {
|
||||||
|
@ -6,10 +6,19 @@ package com.ionspin.kotlin.crypto.sample
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
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.hash.Hash
|
||||||
|
import com.ionspin.kotlin.crypto.util.decodeFromUByteArray
|
||||||
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
|
import java.lang.StringBuilder
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.random.nextUBytes
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@ -18,9 +27,25 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
val hash = Hash.sha512("123".encodeToUByteArray())
|
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 com.ionspin.kotlin.crypto.util.toHexString
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlin.browser.window
|
import kotlinx.browser.window
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val runningOnNode = jsTypeOf(window) == "undefined"
|
val runningOnNode = jsTypeOf(window) == "undefined"
|
||||||
if (!runningOnNode) = runTest {
|
// if (!runningOnNode) = runTest {
|
||||||
LibsodiumInitializer.initializeWithCallback {
|
LibsodiumInitializer.initializeWithCallback {
|
||||||
render(document.getElementById("root")) {
|
render(document.getElementById("root")) {
|
||||||
app {
|
app {
|
||||||
@ -19,10 +20,10 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else = runTest {
|
// } else = runTest {
|
||||||
LibsodiumInitializer.initializeWithCallback {
|
// LibsodiumInitializer.initializeWithCallback {
|
||||||
val hash = Hash.sha512("123".encodeToUByteArray())
|
// val hash = Hash.sha512("123".encodeToUByteArray())
|
||||||
println("Hash (SHA512) of 123: ${hash.toHexString()}")
|
// println("Hash (SHA512) of 123: ${hash.toHexString()}")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -37,5 +37,5 @@ enableFeaturePreview("GRADLE_METADATA")
|
|||||||
rootProject.name = "KotlinMultiplatformLibsodium"
|
rootProject.name = "KotlinMultiplatformLibsodium"
|
||||||
include("multiplatform-crypto-api")
|
include("multiplatform-crypto-api")
|
||||||
include("multiplatform-crypto-libsodium-bindings")
|
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 | :heavy_check_mark: |
|
||||||
| crypto_stream_chacha20_xor_ic | :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_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_keygen | Not at the moment |
|
||||||
| crypto_stream_xchacha20_xor | not present in LazySodium Android|
|
| crypto_stream_xchacha20_xor | Not at the moment |
|
||||||
| crypto_stream_xchacha20_xor_ic | not present in LazySodium Android |
|
| crypto_stream_xchacha20_xor_ic | Not at the moment |
|
||||||
| randombytes_buf | :heavy_check_mark: |
|
| randombytes_buf | :heavy_check_mark: |
|
||||||
| randombytes_buf_deterministic | :heavy_check_mark: |
|
| randombytes_buf_deterministic | :heavy_check_mark: |
|
||||||
| randombytes_close | not present in LazySodium |
|
| randombytes_close | not present in LazySodium |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user