From 4af1477c908791fd4b44bf69d3ab37a4051f4a43 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Sat, 26 Sep 2020 23:58:45 +0200 Subject: [PATCH] Added js _util functions --- .../util/LibsodiumUtil.kt | 3 +- .../kotlin/crypto/util/LibsodiumUtilTest.kt | 154 +++++++++++------- .../kotlin/crypto/JsSodiumInterface.kt | 15 +- .../kotlin/crypto/util/LibsodiumUtil.kt | 50 ++++++ .../kotlin/crypto/util/LibsodiumUtil.kt | 8 - 5 files changed, 161 insertions(+), 69 deletions(-) create mode 100644 multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt index c8df280..d8360f0 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/LibsodiumUtil.kt @@ -20,9 +20,8 @@ expect object LibsodiumUtil { fun toBase64(data: UByteArray, variant : Base64Variants = Base64Variants.URLSAFE_NO_PADDING) : String fun toHex(data: UByteArray) : String - fun toString(data : UByteArray) : String fun fromBase64(data: String, variant : Base64Variants = Base64Variants.URLSAFE_NO_PADDING) : UByteArray fun fromHex(data: String) : UByteArray - fun fromString(data: String) : UByteArray + } diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtilTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtilTest.kt index ec2e100..7dc61c7 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtilTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtilTest.kt @@ -1,8 +1,10 @@ package com.ionspin.kotlin.crypto.util import com.ionspin.kotlin.bignum.integer.util.hexColumsPrint +import com.ionspin.kotlin.crypto.LibsodiumInitializer import kotlin.math.exp import kotlin.test.Test +import kotlin.test.assertFalse import kotlin.test.assertTrue /** @@ -13,91 +15,129 @@ import kotlin.test.assertTrue class LibsodiumUtilTest { @Test - fun testPadding() { - val input = ubyteArrayOf(1U, 2U) - val blocksize = 16 - val padded = LibsodiumUtil.pad(input, blocksize) - println(padded.hexColumsPrint()) - val unpadded = LibsodiumUtil.unpad(padded, blocksize) - println(unpadded.hexColumsPrint()) + fun testMemzero() { + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U) + LibsodiumUtil.memzero(input) + assertTrue { + input.contentEquals(UByteArray(9) { 0U }) + } + } + } - assertTrue { - input.contentEquals(unpadded) + @Test + fun testMemcmp() { + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U) + val input2 = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U) + val input3 = ubyteArrayOf(2U, 2U, 2U, 2U, 2U, 2U, 21U, 2U, 2U) + assertTrue { + LibsodiumUtil.memcmp(input, input2) + } + assertFalse { + LibsodiumUtil.memcmp(input, input3) + } + } + } + + @Test + fun testPadding() { + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U) + val blocksize = 16 + val padded = LibsodiumUtil.pad(input, blocksize) + println(padded.hexColumsPrint()) + val unpadded = LibsodiumUtil.unpad(padded, blocksize) + println(unpadded.hexColumsPrint()) + + assertTrue { + input.contentEquals(unpadded) + } } } @Test fun testPaddingAligned() { - val input = ubyteArrayOf(1U, 2U) - val blocksize = 2 - val padded = LibsodiumUtil.pad(input, blocksize) - println(padded.hexColumsPrint()) - val unpadded = LibsodiumUtil.unpad(padded, blocksize) - println(unpadded.hexColumsPrint()) + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U) + val blocksize = 2 + val padded = LibsodiumUtil.pad(input, blocksize) + println(padded.hexColumsPrint()) + val unpadded = LibsodiumUtil.unpad(padded, blocksize) + println(unpadded.hexColumsPrint()) - assertTrue { - input.contentEquals(unpadded) + assertTrue { + input.contentEquals(unpadded) + } } } @Test fun testPaddingMultiblock() { - val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 6U) - val blocksize = 4 - val padded = LibsodiumUtil.pad(input, blocksize) - println(padded.hexColumsPrint()) - val unpadded = LibsodiumUtil.unpad(padded, blocksize) - println(unpadded.hexColumsPrint()) + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 6U) + val blocksize = 4 + val padded = LibsodiumUtil.pad(input, blocksize) + println(padded.hexColumsPrint()) + val unpadded = LibsodiumUtil.unpad(padded, blocksize) + println(unpadded.hexColumsPrint()) - assertTrue { - input.contentEquals(unpadded) + assertTrue { + input.contentEquals(unpadded) + } } } @Test fun testToBase64() { - val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U) - val expected = "AQIDBAUgQID_" - val output = LibsodiumUtil.toBase64(input) - println("Output: |$output|") - println("Expected|$expected| ") - assertTrue { - output == expected - } - val reconstructed = LibsodiumUtil.fromBase64(output) - println("Reconstructed: ${reconstructed.toHexString()}") - assertTrue { - reconstructed.contentEquals(input) + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U) + val expected = "AQIDBAUgQID_" + val output = LibsodiumUtil.toBase64(input) + println("Output: |$output|") + println("Expected|$expected| ") + assertTrue { + output == expected + } + val reconstructed = LibsodiumUtil.fromBase64(output) + println("Reconstructed: ${reconstructed.toHexString()}") + assertTrue { + reconstructed.contentEquals(input) + } } } @Test fun testToBase64Unaligned() { - val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U, 128U) - val expected = "AQIDBAUgQID_gA" - val output = LibsodiumUtil.toBase64(input) - println("Output: |$output|") - println("Expected|$expected| ") - assertTrue { - output == expected - } - val reconstructed = LibsodiumUtil.fromBase64(output) - println("Reconstructed: ${reconstructed.toHexString()}") - assertTrue { - reconstructed.contentEquals(input) + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U, 128U) + val expected = "AQIDBAUgQID_gA" + val output = LibsodiumUtil.toBase64(input) + println("Output: |$output|") + println("Expected|$expected| ") + assertTrue { + output == expected + } + val reconstructed = LibsodiumUtil.fromBase64(output) + println("Reconstructed: ${reconstructed.toHexString()}") + assertTrue { + reconstructed.contentEquals(input) + } } } @Test fun toHex() { - val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U, 128U) - val hex = LibsodiumUtil.toHex(input) - assertTrue { - hex == input.toHexString() - } - val reconstructed = LibsodiumUtil.fromHex(hex) - assertTrue { - reconstructed.contentEquals(input) + LibsodiumInitializer.initializeWithCallback { + val input = ubyteArrayOf(1U, 2U, 3U, 4U, 5U, 32U, 64U, 128U, 255U, 128U) + val hex = LibsodiumUtil.toHex(input) + assertTrue { + hex == input.toHexString() + } + val reconstructed = LibsodiumUtil.fromHex(hex) + assertTrue { + reconstructed.contentEquals(input) + } } } } diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt index a6b9b7a..ebe0be0 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt @@ -194,9 +194,20 @@ interface JsSodiumInterface { // ---- Password hashing end ---- + // ---- Utils ---- - //util - fun memzero(array: Uint8Array) + fun memcmp(first: Uint8Array, second: Uint8Array) : Boolean + fun memzero(data: Uint8Array) + fun pad(data : Uint8Array, blocksize: Int) : Uint8Array + fun unpad(data: Uint8Array, blocksize: Int) : Uint8Array + fun to_base64(data: Uint8Array, variant: Int) : String + fun to_hex(data: Uint8Array) : String + fun to_string(data: Uint8Array) : String + fun from_base64(data: String, variant: Int): Uint8Array + fun from_hex(data : String): Uint8Array + fun from_string(data : String): Uint8Array + + // ---- Utils end ---- diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt new file mode 100644 index 0000000..5ee7278 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt @@ -0,0 +1,50 @@ +package com.ionspin.kotlin.crypto.util + +import com.ionspin.kotlin.crypto.getSodium +import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray +import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array + +actual object LibsodiumUtil { + actual fun memcmp(first: UByteArray, second: UByteArray): Boolean { + return getSodium().memcmp(first.toUInt8Array(), second.toUInt8Array()) + } + + actual fun memzero(target: UByteArray) { + // libsodium.js does this as well, and theres no clear way at the moment of casting ubytearray to uint8array + //although I feel like there should be a way to work around it + target.forEachIndexed { + index, _ -> target[index] = 0U + } + } + + actual fun pad(unpaddedData: UByteArray, blocksize: Int): UByteArray { + return getSodium().pad(unpaddedData.toUInt8Array(), blocksize).toUByteArray() + } + + actual fun unpad(paddedData: UByteArray, blocksize: Int): UByteArray { + return getSodium().unpad(paddedData.toUInt8Array(), blocksize).toUByteArray() + } + + actual fun toBase64( + data: UByteArray, + variant: Base64Variants + ): String { + return getSodium().to_base64(data.toUInt8Array(), variant.value) + } + + actual fun toHex(data: UByteArray): String { + return getSodium().to_hex(data.toUInt8Array()) + } + + actual fun fromBase64( + data: String, + variant: Base64Variants + ): UByteArray { + return getSodium().from_base64(data, variant.value).toUByteArray() + } + + actual fun fromHex(data: String): UByteArray { + return getSodium().from_hex(data).toUByteArray() + } + +} diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt index 5948f00..fe16466 100644 --- a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt @@ -113,10 +113,6 @@ actual object LibsodiumUtil { return result.map { it.toChar() }.dropLast(1).joinToString("") } - actual fun toString(data: UByteArray): String { - TODO("not implemented yet") - } - actual fun fromBase64(data: String, variant : Base64Variants): UByteArray { val maxLength = (data.length * 3) / 4 val intermediaryResult = UByteArray(maxLength) { 0U } @@ -162,8 +158,4 @@ actual object LibsodiumUtil { return result } - actual fun fromString(data: String): UByteArray { - TODO("not implemented yet") - } - }