From 7d3fe70d4d564f2ca4f691df9877bb2c67b0cabb Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Fri, 25 Sep 2020 19:02:45 +0200 Subject: [PATCH] Started working on sodium_ utility functions --- .../util/LibsodiumUtil.kt | 19 +++- .../kotlin/crypto/util/LibsodiumUtilTest.kt | 27 +++++ .../kotlin/crypto/util/LibsodiumUtil.kt | 102 ++++++++++++++++++ 3 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtilTest.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/nativeMain/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 5f88538..51564e3 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 @@ -5,6 +5,19 @@ package com.ionspin.kotlin.crypto.util * ugljesa.jovanovic@ionspin.com * on 31-Aug-2020 */ -//expect object LibsodiumUtil { -// -//} +expect object LibsodiumUtil { + + fun memcmp(first: UByteArray, second: UByteArray) : Boolean + fun memzero(target: UByteArray) + + fun pad(unpaddedData : UByteArray, blocksize: Int) : UByteArray + fun unpad(paddedData: UByteArray, blocksize: Int) : UByteArray + + fun toBase64(data: UByteArray) : String + fun toHex(data: UByteArray) : String + fun toString(data : UByteArray) : String + + fun fromBase64(data: String) : 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 new file mode 100644 index 0000000..b84bd76 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtilTest.kt @@ -0,0 +1,27 @@ +package com.ionspin.kotlin.crypto.util + +import com.ionspin.kotlin.bignum.integer.util.hexColumsPrint +import kotlin.test.Test +import kotlin.test.assertTrue + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 25-Sep-2020 + */ + +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()) + + assertTrue { + input.contentEquals(unpadded) + } + } +} 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 new file mode 100644 index 0000000..4c49823 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/LibsodiumUtil.kt @@ -0,0 +1,102 @@ +package com.ionspin.kotlin.crypto.util + +import kotlinx.cinterop.StableRef +import kotlinx.cinterop.addressOf +import kotlinx.cinterop.convert +import kotlinx.cinterop.pin +import kotlinx.cinterop.reinterpret +import libsodium.sodium_memcmp +import libsodium.sodium_memzero +import libsodium.sodium_pad +import libsodium.sodium_unpad +import platform.posix.size_t + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 31-Aug-2020 + */ +actual object LibsodiumUtil { + + + actual fun memcmp(first: UByteArray, second: UByteArray): Boolean { + val firstPinned = first.pin() + val secondPinned = second.pin() + val result = sodium_memcmp(firstPinned.toPtr(), secondPinned.toPtr(), first.size.convert()) + firstPinned.unpin() + secondPinned.unpin() + return result == 0 + } + + actual fun memzero(target: UByteArray) { + val targetPinned = target.pin() + sodium_memzero(targetPinned.toPtr(), target.size.convert()) + } + + actual fun pad(unpaddedData : UByteArray, blocksize: Int) : UByteArray { + val resultingSize = if (unpaddedData.size % blocksize != 0 ) { + ((unpaddedData.size / blocksize) + 1 ) * blocksize + } else { + unpaddedData.size + 1 + } + val paddedData = UByteArray(resultingSize) + unpaddedData.copyInto(paddedData, 0, 0) + val paddedDataPinned = paddedData.pin() + + sodium_pad( + null, + paddedDataPinned.toPtr(), + unpaddedData.size.convert(), + blocksize.convert(), + resultingSize.convert() + ) + paddedDataPinned.unpin() + return paddedData + } + + actual fun unpad(paddedData: UByteArray, blocksize: Int) : UByteArray { + val paddedDataCopy = paddedData.copyOf() + val paddedDataCopyPinned = paddedDataCopy.pin() + var newSize = ULongArray(1) { 99UL } + val newSizePinned = newSize.pin() + sodium_unpad( + newSizePinned.addressOf(0), + paddedDataCopyPinned.toPtr(), + paddedData.size.convert(), + blocksize.convert() + ) + val unpaddedSize = newSize[0] + if (unpaddedSize > Int.MAX_VALUE.toULong()) { + throw RuntimeException("Unsupported array size (larger than Integer max value) $unpaddedSize") + } + val unpadded = paddedDataCopy.sliceArray(0 until unpaddedSize.toInt()) + paddedDataCopyPinned.unpin() + newSizePinned.unpin() + return unpadded + } + + actual fun toBase64(data: UByteArray): String { + TODO("not implemented yet") + } + + actual fun toHex(data: UByteArray): String { + TODO("not implemented yet") + } + + actual fun toString(data: UByteArray): String { + TODO("not implemented yet") + } + + actual fun fromBase64(data: String): UByteArray { + TODO("not implemented yet") + } + + actual fun fromHex(data: String): UByteArray { + TODO("not implemented yet") + } + + actual fun fromString(data: String): UByteArray { + TODO("not implemented yet") + } + +}