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 {
 | 
			
		||||
        browser {
 | 
			
		||||
            testTask {
 | 
			
		||||
                enabled = false //Until I sort out testing on travis
 | 
			
		||||
                enabled = true //Until I sort out testing on travis
 | 
			
		||||
                useKarma {
 | 
			
		||||
                    useChrome()
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -23,5 +23,7 @@ object Crypto : CryptoProvider {
 | 
			
		||||
 | 
			
		||||
expect object Initializer {
 | 
			
		||||
    suspend fun initialize()
 | 
			
		||||
 | 
			
		||||
    fun initializeWithCallback(done : () -> (Unit))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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'))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user