Built and included modified libsodium with additional wrappers, working blake, sha256/512 hashes

This commit is contained in:
Ugljesa Jovanovic 2020-06-09 20:30:12 +02:00 committed by Ugljesa Jovanovic
parent 710ac43e8c
commit 197aacac33
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
30 changed files with 170 additions and 89 deletions

View File

@ -21,3 +21,23 @@ Libsodium, licensed under ISC License
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
Libsodium.js (temporarily included libsodium-wrappers-sumo-0.7.6.tgz packed npm package with additional sha256 and sha512 multipart wrappers)
Copyright (c) 2015-2020
Ahmad Ben Mrad <batikhsouri at gmail dot org>
Frank Denis <j at pureftpd dot org>
Ryan Lester <ryan at cyph dot com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -58,8 +58,9 @@ object Deps {
val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:${Versions.kotlinSerialization}"
object Npm {
val libsodium = Pair("libsodium-sumo", "0.7.6")
val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "0.7.6")
val libsodium = Pair("libsodium-wrappers-sumo", "0.7.6")
// val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "0.7.6")
val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "file:/home/ionspin/Projects/Future/kotlin-multiplatform-crypto/multiplatform-crypto-delegated/libsodium-wrappers-sumo-0.7.6.tgz")
}
}

View File

@ -30,8 +30,6 @@ interface Hash {
interface UpdatableHash : Hash {
fun update(data : UByteArray)
fun update(data : String)
fun digest() : UByteArray
}

View File

@ -17,7 +17,7 @@ interface Sha512 : UpdatableHash {
}
interface StatelessSha512 : StatelessHash {
override val MAX_HASH_BYTES: Int
get() = Sha256Properties.MAX_HASH_BYTES
get() = Sha512Properties.MAX_HASH_BYTES
fun digest(
inputMessage: UByteArray = ubyteArrayOf()

View File

@ -435,7 +435,6 @@ kotlin {
dependencies {
implementation(kotlin(Deps.Js.stdLib))
implementation(Deps.Js.coroutines)
implementation(npm(Deps.Js.Npm.libsodium.first, Deps.Js.Npm.libsodium.second))
implementation(npm(Deps.Js.Npm.libsodiumWrappers.first, Deps.Js.Npm.libsodiumWrappers.second))
}
}
@ -443,7 +442,7 @@ kotlin {
dependencies {
implementation(Deps.Js.coroutines)
implementation(kotlin(Deps.Js.test))
implementation(npm(Deps.Js.Npm.libsodium.first, Deps.Js.Npm.libsodium.second))
implementation(npm(Deps.Js.Npm.libsodiumWrappers.first, Deps.Js.Npm.libsodiumWrappers.second))
}
}
val linuxX64Main by getting {
@ -529,14 +528,6 @@ kotlin {
task<Copy>("copyPackageJson") {
dependsOn("compileKotlinJs")
println("Copying package.json from $projectDir/core/src/jsMain/npm")
from("$projectDir/src/jsMain/npm")
println("Node modules dir ${node.nodeModulesDir}")
into("${node.nodeModulesDir}")
}
tasks {
@ -547,17 +538,6 @@ tasks {
}
dokka {
println("Dokka !")
impliedPlatforms = mutableListOf("Common")
kotlinTasks {
listOf()
}
sourceRoot {
println("Common !")
path =
"/home/ionspin/Projects/Future/kotlin-multiplatform-crypto/crypto/src/commonMain" //TODO remove static path!
platforms = listOf("Common")
}
}
if (getHostOsName() == "linux" && getHostArchitecture() == "x86-64") {
val jvmTest by getting(Test::class) {

View File

@ -47,7 +47,7 @@ object Crypto : CryptoProvider {
}
fun stateless(message: UByteArray) : UByteArray {
TODO()
return Sha512StatelessDelegated.digest(inputMessage = message)
}
}

View File

@ -32,8 +32,6 @@ class SRNGTest {
//Just a sanity test, need to add better srng tests.
val randomBytes1 = SRNG.getRandomBytes(10)
val randomBytes2 = SRNG.getRandomBytes(10)
randomBytes1.forEach { println("RB1: $it")}
randomBytes2.forEach { println("RB2: $it")}
assertTrue { !randomBytes1.contentEquals(randomBytes2) }
}
}

View File

@ -19,4 +19,17 @@ class Sha256Test {
println("Result: $result")
assertTrue { result == expected }
}
//This is a bad test since it's not larger than one block
//but for now I'm testing that the platform library is being correctly called
@Test
fun updateableSimpleTest() {
val expected = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
val sha256 = Crypto.Sha256.updateable()
sha256.update("t".encodeToUByteArray())
sha256.update(("est".encodeToUByteArray()))
val result = sha256.digest().toHexString()
println("Result: $result")
assertTrue { result == expected }
}
}

View File

@ -0,0 +1,37 @@
package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.Crypto
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 07-Jun-2020
*/
class Sha512Test {
@Test
fun statelessSimpleTest() {
val expected = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67" +
"b143732c304cc5fa9ad8e6f57f50028a8ff"
val result = Crypto.Sha512.stateless("test".encodeToUByteArray()).toHexString()
println("Result: $result")
assertTrue { result == expected }
}
//This is a bad test since it's not larger than one block
//but for now I'm testing that the platform library is being correctly called
@Test
fun updateableSimpleTest() {
val expected = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67" +
"b143732c304cc5fa9ad8e6f57f50028a8ff"
val sha512 = Crypto.Sha512.updateable()
sha512.update("t".encodeToUByteArray())
sha512.update(("est".encodeToUByteArray()))
val result = sha512.digest().toHexString()
println("Result: $result")
assertTrue { result == expected }
}
}

View File

@ -8,6 +8,8 @@ var sodiumLoaded: Boolean = false
fun getSodium() : JsSodiumInterface = sodiumPointer
//fun getSodiumAdvanced() : JsSodiumAdvancedInterface = js("sodiumPointer.libsodium")
fun setSodiumPointer(jsSodiumInterface: JsSodiumInterface) {
js("sodiumPointer = jsSodiumInterface")
}

View File

@ -1,5 +1,6 @@
package ext.libsodium.com.ionspin.kotlin.crypto
import org.khronos.webgl.Uint8Array
/**
@ -9,11 +10,25 @@ import org.khronos.webgl.Uint8Array
*/
interface JsSodiumInterface {
fun crypto_hash_sha256(message: Uint8Array) : Uint8Array
fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array): Uint8Array
fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array) : Uint8Array
fun randombytes_buf(numberOfBytes: Int): Uint8Array
fun randombytes_buf(numberOfBytes: Int) : Uint8Array
fun crypto_hash_sha256(message: Uint8Array): Uint8Array
fun crypto_hash_sha512(message: Uint8Array): Uint8Array
fun crypto_hash_sha256_init() : dynamic
fun crypto_hash_sha256_update(state: dynamic, message: Uint8Array)
fun crypto_hash_sha256_final(state: dynamic): Uint8Array
fun crypto_hash_sha512_init() : dynamic
fun crypto_hash_sha512_update(state: dynamic, message: Uint8Array)
fun crypto_hash_sha512_final(state: dynamic): Uint8Array
}
}

View File

@ -3,7 +3,7 @@ package ext.libsodium.com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.getSodiumLoaded
import com.ionspin.kotlin.crypto.setSodiumPointer
import com.ionspin.kotlin.crypto.sodiumLoaded
import ext.libsodium._libsodiumPromise
import ext.libsodium.*
import kotlin.coroutines.Continuation
import kotlin.coroutines.suspendCoroutine
@ -14,6 +14,16 @@ import kotlin.coroutines.suspendCoroutine
*/
object JsSodiumLoader {
class _EmitJsSodiumFunction {
init {
println(::crypto_generichash)
println(::crypto_hash_sha256)
println(::crypto_hash_sha512)
println(::crypto_hash_sha256_init)
}
}
fun storeSodium(promisedSodium: dynamic, continuation: Continuation<Unit>) {
setSodiumPointer(promisedSodium)
sodiumLoaded = true

View File

@ -28,8 +28,6 @@ actual object SRNG {
actual fun getRandomBytes(amount: Int): UByteArray {
val randomBytes = getSodium().randombytes_buf(amount)
println("Random bytes: $randomBytes")
print("Byte at ${randomBytes[0]}")
val randomBytesUByteArray = UByteArray(amount) {
0U
}

View File

@ -3,6 +3,7 @@ package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.crypto.getSodium
import com.ionspin.kotlin.crypto.util.toHexString
import org.khronos.webgl.Uint8Array
import org.khronos.webgl.get
/**
* Created by Ugljesa Jovanovic
@ -19,9 +20,7 @@ actual class Blake2bDelegated actual constructor(key: UByteArray?, hashLength: I
TODO("not implemented yet")
}
override fun update(data: String) {
TODO("not implemented yet")
}
override fun digest(): UByteArray {
TODO("not implemented yet")
@ -38,11 +37,7 @@ actual object Blake2bDelegatedStateless : Blake2bStateless {
val hashed = getSodium().crypto_generichash(64, Uint8Array(inputMessage.toByteArray().toTypedArray()))
val hash = UByteArray(MAX_HASH_BYTES)
for (i in 0 until MAX_HASH_BYTES) {
js(
"""
hash[i] = hashed[i]
"""
)
hash[i] = hashed[i].toUByte()
}
return hash
}

View File

@ -2,7 +2,11 @@ package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.getSodium
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegatedStateless
import ext.libsodium.crypto_hash_sha256_init
import org.khronos.webgl.Uint8Array
import org.khronos.webgl.get
/**
* Created by Ugljesa Jovanovic
@ -12,16 +16,25 @@ import org.khronos.webgl.Uint8Array
actual class Sha256Delegated actual constructor(key: UByteArray?, hashLength: Int) : Sha256 {
override fun update(data: UByteArray) {
TODO("not implemented yet")
val state : dynamic
init {
state = getSodium().crypto_hash_sha256_init()
}
override fun update(data: String) {
TODO("not implemented yet")
override fun update(data: UByteArray) {
getSodium().crypto_hash_sha256_update(state, Uint8Array(data.toByteArray().toTypedArray()))
}
override fun digest(): UByteArray {
TODO("not implemented yet")
val hashed = getSodium().crypto_hash_sha256_final(state)
val hash = UByteArray(Sha256StatelessDelegated.MAX_HASH_BYTES)
console.log(hashed)
for (i in 0 until Sha256StatelessDelegated.MAX_HASH_BYTES) {
hash[i] = hashed[i].toUByte()
}
return hash
}
}
@ -32,11 +45,7 @@ actual object Sha256StatelessDelegated : StatelessSha256 {
val hashed = getSodium().crypto_hash_sha256(Uint8Array(inputMessage.toByteArray().toTypedArray()))
val hash = UByteArray(MAX_HASH_BYTES)
for (i in 0 until MAX_HASH_BYTES) {
js(
"""
hash[i] = hashed[i]
"""
)
hash[i] = hashed[i].toUByte()
}
return hash
}

View File

@ -1,5 +1,11 @@
package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.getSodium
import com.ionspin.kotlin.crypto.getSodium
import org.khronos.webgl.Uint8Array
import org.khronos.webgl.get
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
@ -8,16 +14,23 @@ package com.ionspin.kotlin.crypto.hash.sha
actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: Int) : Sha512 {
override fun update(data: UByteArray) {
TODO("not implemented yet")
val state : dynamic
init {
state = getSodium().crypto_hash_sha512_init()
}
override fun update(data: String) {
TODO("not implemented yet")
override fun update(data: UByteArray) {
getSodium().crypto_hash_sha512_update(state, Uint8Array(data.toByteArray().toTypedArray()))
}
override fun digest(): UByteArray {
TODO("not implemented yet")
val hashed = getSodium().crypto_hash_sha512_final(state)
val hash = UByteArray(Sha512StatelessDelegated.MAX_HASH_BYTES)
for (i in 0 until Sha512StatelessDelegated.MAX_HASH_BYTES) {
hash[i] = hashed[i].toUByte()
}
return hash
}
}
@ -25,6 +38,11 @@ actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: In
actual object Sha512StatelessDelegated : StatelessSha512 {
override fun digest(inputMessage: UByteArray): UByteArray {
TODO("not implemented yet")
val hashed = getSodium().crypto_hash_sha512(Uint8Array(inputMessage.toByteArray().toTypedArray()))
val hash = UByteArray(Sha512StatelessDelegated.MAX_HASH_BYTES)
for (i in 0 until Sha512StatelessDelegated.MAX_HASH_BYTES) {
hash[i] = hashed[i].toUByte()
}
return hash
}
}

View File

@ -18,4 +18,11 @@ external val _libsodiumPromise : Promise<dynamic>
external fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array) : Uint8Array
external fun crypto_hash_sha256(message: Uint8Array) : Uint8Array
external fun crypto_hash_sha512(message: Uint8Array) : Uint8Array
external fun crypto_hash_sha256_init(): dynamic

View File

@ -13,10 +13,6 @@ actual class Blake2bDelegated actual constructor(key: UByteArray?, hashLength: I
TODO("not implemented yet")
}
override fun update(data: String) {
TODO("not implemented yet")
}
override fun digest(): UByteArray {
TODO("not implemented yet")
}

View File

@ -15,10 +15,6 @@ actual class Sha256Delegated actual constructor(key: UByteArray?, hashLength: In
TODO("not implemented yet")
}
override fun update(data: String) {
TODO("not implemented yet")
}
override fun digest(): UByteArray {
TODO("not implemented yet")
}

View File

@ -12,10 +12,6 @@ actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: In
TODO("not implemented yet")
}
override fun update(data: String) {
TODO("not implemented yet")
}
override fun digest(): UByteArray {
TODO("not implemented yet")
}

View File

@ -32,11 +32,6 @@ actual class Blake2bDelegated actual constructor(key: UByteArray?, hashLength: I
crypto_generichash_update(state.ptr, data.toCValues(), data.size.convert())
}
override fun update(data: String) {
val ubyteArray = data.encodeToByteArray().toUByteArray()
crypto_generichash_update(state.ptr, ubyteArray.toCValues(), ubyteArray.size.convert())
}
override fun digest(): UByteArray {
val hashResult = UByteArray(requestedHashLength)
val hashResultPinned = hashResult.pin()

View File

@ -20,9 +20,7 @@ actual class Sha256Delegated actual constructor(key: UByteArray?, hashLength: In
TODO("not implemented yet")
}
override fun update(data: String) {
TODO("not implemented yet")
}
override fun digest(): UByteArray {
TODO("not implemented yet")

View File

@ -12,9 +12,7 @@ actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: In
TODO("not implemented yet")
}
override fun update(data: String) {
TODO("not implemented yet")
}
override fun digest(): UByteArray {
TODO("not implemented yet")

View File

@ -27,7 +27,7 @@ class Blake2bLinuxTest {
@Test
fun testBlake2bUpdateable() = testBlocking {
val blake2b = Crypto.Blake2b.updateable()
blake2b.update("test")
blake2b.update("test".encodeToUByteArray())
val result = blake2b.digest().toHexString()
println(result)
assertTrue { result.length > 2 }

View File

@ -27,7 +27,7 @@ class Sha512DelegatedLinuxTest {
@Test
fun testBlake2bUpdateable() = testBlocking {
val blake2b = Crypto.Blake2b.updateable()
blake2b.update("test")
blake2b.update("test".encodeToUByteArray())
val result = blake2b.digest().toHexString()
println(result)
assertTrue { result.length > 2 }

View File

@ -309,7 +309,7 @@ class Blake2bPure(val key: UByteArray? = null, val hashLength: Int = 64) : Blake
}
override fun update(data: String) {
fun update(data: String) {
update(data.encodeToByteArray().toUByteArray())
}

View File

@ -235,7 +235,7 @@ class Sha256Pure : Sha256 {
var buffer = UByteArray(BLOCK_SIZE_IN_BYTES) { 0U }
override fun update(data: String) {
fun update(data: String) {
return update(data.encodeToByteArray().toUByteArray())
}

View File

@ -309,7 +309,7 @@ class Sha512Pure : Sha512 {
var buffer = UByteArray(BLOCK_SIZE_IN_BYTES) { 0U }
override fun update(data: String) {
fun update(data: String) {
return update(data.encodeToByteArray().toUByteArray())
}

View File

@ -3,6 +3,7 @@ package com.ionspin.kotlin.crypto.sample
import com.ionspin.kotlin.crypto.Crypto
import com.ionspin.kotlin.crypto.CryptoProvider
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@ -20,7 +21,7 @@ object Sample {
fun blake2b() {
println("Blake2b updateable")
val blake2bUpdateable = Crypto.Blake2b.updateable()
blake2bUpdateable.update("test")
blake2bUpdateable.update("test".encodeToUByteArray())
println(blake2bUpdateable.digest().toHexString())
println("Blake2b stateless")
val statelessResult = Crypto.Blake2b.stateless("test".encodeToByteArray().toUByteArray())