Use random bytes provided by libsodium on js, add with callback load for sodium, more progress
This commit is contained in:
parent
781c9c1b61
commit
f51374ce15
@ -74,7 +74,7 @@ kotlin {
|
|||||||
js {
|
js {
|
||||||
browser {
|
browser {
|
||||||
testTask {
|
testTask {
|
||||||
enabled = false //Until I sort out testing on travis
|
enabled = true //Until I sort out testing on travis
|
||||||
useKarma {
|
useKarma {
|
||||||
useChrome()
|
useChrome()
|
||||||
}
|
}
|
||||||
|
@ -23,5 +23,7 @@ object Crypto : CryptoProvider {
|
|||||||
|
|
||||||
expect object Initializer {
|
expect object Initializer {
|
||||||
suspend fun initialize()
|
suspend fun initialize()
|
||||||
|
|
||||||
|
fun initializeWithCallback(done : () -> (Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader
|
|||||||
lateinit var sodiumPointer : JsSodiumInterface
|
lateinit var sodiumPointer : JsSodiumInterface
|
||||||
var sodiumLoaded: Boolean = false
|
var sodiumLoaded: Boolean = false
|
||||||
|
|
||||||
fun getSodiumPointer() : JsSodiumInterface = sodiumPointer
|
fun getSodium() : JsSodiumInterface = sodiumPointer
|
||||||
|
|
||||||
fun setSodiumPointer(jsSodiumInterface: JsSodiumInterface) {
|
fun setSodiumPointer(jsSodiumInterface: JsSodiumInterface) {
|
||||||
js("sodiumPointer = jsSodiumInterface")
|
js("sodiumPointer = jsSodiumInterface")
|
||||||
@ -22,4 +22,10 @@ actual object Initializer {
|
|||||||
actual suspend fun initialize() {
|
actual suspend fun initialize() {
|
||||||
JsSodiumLoader.load()
|
JsSodiumLoader.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun initializeWithCallback(done: () -> Unit) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,17 @@
|
|||||||
package ext.libsodium.com.ionspin.kotlin.crypto
|
package ext.libsodium.com.ionspin.kotlin.crypto
|
||||||
|
|
||||||
|
import org.khronos.webgl.Uint8Array
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
* ugljesa.jovanovic@ionspin.com
|
* ugljesa.jovanovic@ionspin.com
|
||||||
* on 27-May-2020
|
* on 27-May-2020
|
||||||
*/
|
*/
|
||||||
interface JsSodiumInterface {
|
interface JsSodiumInterface {
|
||||||
fun crypto_generichash(hashLength: Int, inputMessage: String) : String
|
|
||||||
|
fun crypto_generichash(hashLength: Int, inputMessage: String) : Uint8Array
|
||||||
|
|
||||||
|
fun randombytes_buf(numberOfBytes: Int) : Uint8Array
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package ext.libsodium.com.ionspin.kotlin.crypto
|
package ext.libsodium.com.ionspin.kotlin.crypto
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.getSodiumLoaded
|
import com.ionspin.kotlin.crypto.getSodiumLoaded
|
||||||
import com.ionspin.kotlin.crypto.getSodiumPointer
|
|
||||||
import com.ionspin.kotlin.crypto.setSodiumPointer
|
import com.ionspin.kotlin.crypto.setSodiumPointer
|
||||||
import com.ionspin.kotlin.crypto.sodiumLoaded
|
import com.ionspin.kotlin.crypto.sodiumLoaded
|
||||||
import ext.libsodium._libsodiumPromise
|
import ext.libsodium._libsodiumPromise
|
||||||
@ -15,19 +14,33 @@ import kotlin.coroutines.suspendCoroutine
|
|||||||
*/
|
*/
|
||||||
object JsSodiumLoader {
|
object JsSodiumLoader {
|
||||||
|
|
||||||
fun storeSodium(promisedSodium: dynamic, continuation: Continuation<JsSodiumInterface>) {
|
fun storeSodium(promisedSodium: dynamic, continuation: Continuation<Unit>) {
|
||||||
setSodiumPointer(promisedSodium)
|
setSodiumPointer(promisedSodium)
|
||||||
sodiumLoaded = true
|
sodiumLoaded = true
|
||||||
continuation.resumeWith(Result.success(getSodiumPointer()))
|
continuation.resumeWith(Result.success(Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun load(): JsSodiumInterface = suspendCoroutine { continuation ->
|
suspend fun load() = suspendCoroutine<Unit> { continuation ->
|
||||||
console.log(getSodiumLoaded())
|
console.log(getSodiumLoaded())
|
||||||
if (!getSodiumLoaded()) {
|
if (!getSodiumLoaded()) {
|
||||||
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
|
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
|
||||||
_libsodiumPromise.then<dynamic> { storeSodium(libsodiumModule, continuation) }
|
_libsodiumPromise.then<dynamic> { storeSodium(libsodiumModule, continuation) }
|
||||||
} else {
|
} else {
|
||||||
continuation.resumeWith(Result.success(getSodiumPointer()))
|
continuation.resumeWith(Result.success(Unit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadWithCallback(doneCallback: () -> (Unit)) {
|
||||||
|
console.log(getSodiumLoaded())
|
||||||
|
if (!getSodiumLoaded()) {
|
||||||
|
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
|
||||||
|
_libsodiumPromise.then<dynamic> {
|
||||||
|
setSodiumPointer(libsodiumModule)
|
||||||
|
sodiumLoaded = true
|
||||||
|
doneCallback.invoke()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
doneCallback.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
package com.ionspin.kotlin.crypto
|
||||||
|
|
||||||
import kotlin.browser.window
|
import org.khronos.webgl.get
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
@ -27,22 +27,7 @@ actual object SRNG {
|
|||||||
var counter = 0
|
var counter = 0
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
actual fun getRandomBytes(amount: Int): UByteArray {
|
actual fun getRandomBytes(amount: Int): UByteArray {
|
||||||
val runningOnNode = jsTypeOf(window) == "undefined"
|
val randomBytes = getSodium().randombytes_buf(amount)
|
||||||
val randomBytes = if (runningOnNode) {
|
|
||||||
println("Running on node")
|
|
||||||
js("require('crypto')").randomBytes(amount).toJSON().data
|
|
||||||
} else {
|
|
||||||
println("Running in browser")
|
|
||||||
js(
|
|
||||||
"""
|
|
||||||
var randomArray = new Uint8Array(amount);
|
|
||||||
var crypto = (self.crypto || self.msCrypto);
|
|
||||||
crypto.getRandomValues(randomArray);
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
var randomArrayResult = js("Array.prototype.slice.call(randomArray);")
|
|
||||||
randomArrayResult
|
|
||||||
}
|
|
||||||
println("Random bytes: $randomBytes")
|
println("Random bytes: $randomBytes")
|
||||||
print("Byte at ${randomBytes[0]}")
|
print("Byte at ${randomBytes[0]}")
|
||||||
val randomBytesUByteArray = UByteArray(amount) {
|
val randomBytesUByteArray = UByteArray(amount) {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.blake2b
|
package com.ionspin.kotlin.crypto.hash.blake2b
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.getSodium
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumInterface
|
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader
|
|
||||||
import ext.libsodium.crypto_generichash
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
@ -39,8 +37,7 @@ actual object Blake2bStateless : Blake2bStatelessInterface {
|
|||||||
override val MAX_HASH_BYTES: Int = 64
|
override val MAX_HASH_BYTES: Int = 64
|
||||||
|
|
||||||
override suspend fun digest(inputString: String, key: String?, hashLength: Int): UByteArray {
|
override suspend fun digest(inputString: String, key: String?, hashLength: Int): UByteArray {
|
||||||
val sodium = JsSodiumLoader.load()
|
val hashed = getSodium().crypto_generichash(64, inputString)
|
||||||
val hashed = sodium.crypto_generichash(64, inputString)
|
|
||||||
val hash = UByteArray(MAX_HASH_BYTES)
|
val hash = UByteArray(MAX_HASH_BYTES)
|
||||||
for (i in 0 until MAX_HASH_BYTES) {
|
for (i in 0 until MAX_HASH_BYTES) {
|
||||||
js(
|
js(
|
||||||
@ -50,7 +47,21 @@ actual object Blake2bStateless : Blake2bStatelessInterface {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
println("Hash ${hash.toHexString()}")
|
println("Hash ${hash.toHexString()}")
|
||||||
return ubyteArrayOf(0U)
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
fun digestBlocking(inputString: String, key: String?, hashLength: Int): UByteArray {
|
||||||
|
val hashed = getSodium().crypto_generichash(hashLength, inputString)
|
||||||
|
val hash = UByteArray(MAX_HASH_BYTES)
|
||||||
|
for (i in 0 until MAX_HASH_BYTES) {
|
||||||
|
js(
|
||||||
|
"""
|
||||||
|
hash[i] = hashed[i]
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
println("Hash ${hash.toHexString()}")
|
||||||
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
package com.ionspin.kotlin.crypto
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.util.testBlocking
|
||||||
|
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
@ -28,14 +30,15 @@ import kotlin.test.assertTrue
|
|||||||
class SRNGJsTest {
|
class SRNGJsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testJsSrng() {
|
fun testJsSrng() = testBlocking {
|
||||||
|
JsSodiumLoader.load()
|
||||||
val bytes1 = SRNG.getRandomBytes(10)
|
val bytes1 = SRNG.getRandomBytes(10)
|
||||||
val bytes2 = SRNG.getRandomBytes(10)
|
val bytes2 = SRNG.getRandomBytes(10)
|
||||||
println("BYTES1")
|
println("BYTES1\n")
|
||||||
bytes1.forEach {
|
bytes1.forEach {
|
||||||
print(it.toString(16).padStart(2, '0'))
|
print(it.toString(16).padStart(2, '0'))
|
||||||
}
|
}
|
||||||
println("BYTES2")
|
println("BYTES2\n")
|
||||||
bytes2.forEach {
|
bytes2.forEach {
|
||||||
print(it.toString(16).padStart(2, '0'))
|
print(it.toString(16).padStart(2, '0'))
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ package com.ionspin.kotlin.crypto.hash.blake2b
|
|||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Crypto
|
import com.ionspin.kotlin.crypto.Crypto
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
import com.ionspin.kotlin.crypto.util.testBlocking
|
||||||
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
import kotlin.test.BeforeTest
|
import kotlin.test.BeforeTest
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
@ -14,13 +16,21 @@ import kotlin.test.Test
|
|||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
class Blake2bJsTest {
|
class Blake2bJsTest {
|
||||||
|
|
||||||
@BeforeTest
|
@Test
|
||||||
fun setup() = testBlocking {
|
fun testBlake2BSodiumInterop() = testBlocking {
|
||||||
Crypto.initialize()
|
Crypto.initialize()
|
||||||
|
val hash = Blake2bStateless.digest("test")
|
||||||
|
assertEquals(hash.toHexString(), "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a4" +
|
||||||
|
"83aa9bc33b582f77d30a65e6f29a896c0411f38312e1d66e0bf16386c86a89bea572")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBlake2BSodiumInterop() = testBlocking {
|
fun testBlake2BSodiumBlockingInterop() = testBlocking {
|
||||||
Blake2bStateless.digest("test")
|
Crypto.initialize()
|
||||||
|
val hash = Blake2bStateless.digestBlocking("test", null, 64)
|
||||||
|
assertEquals(hash.toHexString(), "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a4" +
|
||||||
|
"83aa9bc33b582f77d30a65e6f29a896c0411f38312e1d66e0bf16386c86a89bea572")
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user