Use random bytes provided by libsodium on js, add with callback load for sodium, more progress

This commit is contained in:
Ugljesa Jovanovic 2020-05-28 19:00:33 +02:00 committed by Ugljesa Jovanovic
parent 781c9c1b61
commit f51374ce15
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
9 changed files with 75 additions and 38 deletions

View File

@ -74,7 +74,7 @@ kotlin {
js {
browser {
testTask {
enabled = false //Until I sort out testing on travis
enabled = true //Until I sort out testing on travis
useKarma {
useChrome()
}

View File

@ -23,5 +23,7 @@ object Crypto : CryptoProvider {
expect object Initializer {
suspend fun initialize()
fun initializeWithCallback(done : () -> (Unit))
}

View File

@ -6,7 +6,7 @@ import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader
lateinit var sodiumPointer : JsSodiumInterface
var sodiumLoaded: Boolean = false
fun getSodiumPointer() : JsSodiumInterface = sodiumPointer
fun getSodium() : JsSodiumInterface = sodiumPointer
fun setSodiumPointer(jsSodiumInterface: JsSodiumInterface) {
js("sodiumPointer = jsSodiumInterface")
@ -22,4 +22,10 @@ actual object Initializer {
actual suspend fun initialize() {
JsSodiumLoader.load()
}
actual fun initializeWithCallback(done: () -> Unit) {
}
}

View File

@ -1,10 +1,17 @@
package ext.libsodium.com.ionspin.kotlin.crypto
import org.khronos.webgl.Uint8Array
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 27-May-2020
*/
interface JsSodiumInterface {
fun crypto_generichash(hashLength: Int, inputMessage: String) : String
fun crypto_generichash(hashLength: Int, inputMessage: String) : Uint8Array
fun randombytes_buf(numberOfBytes: Int) : Uint8Array
}

View File

@ -1,7 +1,6 @@
package ext.libsodium.com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.getSodiumLoaded
import com.ionspin.kotlin.crypto.getSodiumPointer
import com.ionspin.kotlin.crypto.setSodiumPointer
import com.ionspin.kotlin.crypto.sodiumLoaded
import ext.libsodium._libsodiumPromise
@ -15,19 +14,33 @@ import kotlin.coroutines.suspendCoroutine
*/
object JsSodiumLoader {
fun storeSodium(promisedSodium: dynamic, continuation: Continuation<JsSodiumInterface>) {
fun storeSodium(promisedSodium: dynamic, continuation: Continuation<Unit>) {
setSodiumPointer(promisedSodium)
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())
if (!getSodiumLoaded()) {
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
_libsodiumPromise.then<dynamic> { storeSodium(libsodiumModule, continuation) }
} 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()
}
}
}

View File

@ -16,7 +16,7 @@
package com.ionspin.kotlin.crypto
import kotlin.browser.window
import org.khronos.webgl.get
/**
* Created by Ugljesa Jovanovic
@ -27,22 +27,7 @@ actual object SRNG {
var counter = 0
@ExperimentalUnsignedTypes
actual fun getRandomBytes(amount: Int): UByteArray {
val runningOnNode = jsTypeOf(window) == "undefined"
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
}
val randomBytes = getSodium().randombytes_buf(amount)
println("Random bytes: $randomBytes")
print("Byte at ${randomBytes[0]}")
val randomBytesUByteArray = UByteArray(amount) {

View File

@ -1,9 +1,7 @@
package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.crypto.getSodium
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
@ -39,8 +37,7 @@ actual object Blake2bStateless : Blake2bStatelessInterface {
override val MAX_HASH_BYTES: Int = 64
override suspend fun digest(inputString: String, key: String?, hashLength: Int): UByteArray {
val sodium = JsSodiumLoader.load()
val hashed = sodium.crypto_generichash(64, inputString)
val hashed = getSodium().crypto_generichash(64, inputString)
val hash = UByteArray(MAX_HASH_BYTES)
for (i in 0 until MAX_HASH_BYTES) {
js(
@ -50,7 +47,21 @@ actual object Blake2bStateless : Blake2bStatelessInterface {
)
}
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 {

View File

@ -16,6 +16,8 @@
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.assertTrue
@ -28,14 +30,15 @@ import kotlin.test.assertTrue
class SRNGJsTest {
@Test
fun testJsSrng() {
fun testJsSrng() = testBlocking {
JsSodiumLoader.load()
val bytes1 = SRNG.getRandomBytes(10)
val bytes2 = SRNG.getRandomBytes(10)
println("BYTES1")
println("BYTES1\n")
bytes1.forEach {
print(it.toString(16).padStart(2, '0'))
}
println("BYTES2")
println("BYTES2\n")
bytes2.forEach {
print(it.toString(16).padStart(2, '0'))
}

View File

@ -2,8 +2,10 @@ package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.crypto.Crypto
import com.ionspin.kotlin.crypto.util.testBlocking
import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
/**
* Created by Ugljesa Jovanovic
@ -14,13 +16,21 @@ import kotlin.test.Test
@ExperimentalStdlibApi
class Blake2bJsTest {
@BeforeTest
fun setup() = testBlocking {
@Test
fun testBlake2BSodiumInterop() = testBlocking {
Crypto.initialize()
val hash = Blake2bStateless.digest("test")
assertEquals(hash.toHexString(), "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a4" +
"83aa9bc33b582f77d30a65e6f29a896c0411f38312e1d66e0bf16386c86a89bea572")
}
@Test
fun testBlake2BSodiumInterop() = testBlocking {
Blake2bStateless.digest("test")
fun testBlake2BSodiumBlockingInterop() = testBlocking {
Crypto.initialize()
val hash = Blake2bStateless.digestBlocking("test", null, 64)
assertEquals(hash.toHexString(), "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a4" +
"83aa9bc33b582f77d30a65e6f29a896c0411f38312e1d66e0bf16386c86a89bea572")
}
}