From c66fde85022b735c75ab08b0853bfdb8837ee164 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Thu, 15 Oct 2020 20:38:30 +0200 Subject: [PATCH] Adding scalrmult_ native impl, starting work on sample --- .../scalarmut/ScalarMultiplication.kt | 34 +++++++++++ .../crypto/scalarmut/ScalarMultiplication.kt | 58 +++++++++++++++++++ sample/build.gradle.kts | 2 +- .../ionspin/kotlin/crypto/sample/Sample.kt | 24 ++------ .../ionspin/kotlin/crypto/sample/Runner.kt | 1 - .../ionspin/kotlin/crypto/sample/Runner.kt | 2 - supported_bindings_list.md | 1 + 7 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/scalarmut/ScalarMultiplication.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/scalarmut/ScalarMultiplication.kt diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/scalarmut/ScalarMultiplication.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/scalarmut/ScalarMultiplication.kt new file mode 100644 index 0000000..cd5b214 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/scalarmut/ScalarMultiplication.kt @@ -0,0 +1,34 @@ +package com.ionspin.kotlin.crypto.scalarmut + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 15-Oct-2020 + */ +const val crypto_scalarmult_BYTES = 32 +const val crypto_scalarmult_SCALARBYTES = 32 + +expect object ScalarMultiplication { + + /** + * This function can be used to compute a shared secret q given a user's secret key and another user's public key. + * n is crypto_scalarmult_SCALARBYTES bytes long, p and the output are crypto_scalarmult_BYTES bytes long. + * q represents the X coordinate of a point on the curve. As a result, the number of possible keys is limited to + * the group size (≈2^252), which is smaller than the key space. + * For this reason, and to mitigate subtle attacks due to the fact many (p, n) pairs produce the same result, + * using the output of the multiplication q directly as a shared key is not recommended. + * A better way to compute a shared key is h(q ‖ pk1 ‖ pk2), with pk1 and pk2 being the public keys. + * By doing so, each party can prove what exact public key they intended to perform a key exchange with + * (for a given public key, 11 other public keys producing the same shared secret can be trivially computed). + * This can be achieved with the following code snippet: + */ + fun scalarMultiplication(secretKeyN : UByteArray, publicKeyP: UByteArray) : UByteArray + + /** + * Given a user's secret key n (crypto_scalarmult_SCALARBYTES bytes), the crypto_scalarmult_base() function + * computes the user's public key and puts it into q (crypto_scalarmult_BYTES bytes). + * crypto_scalarmult_BYTES and crypto_scalarmult_SCALARBYTES are provided for consistency, + * but it is safe to assume that crypto_scalarmult_BYTES == crypto_scalarmult_SCALARBYTES. + */ + fun scalarMultiplicationBase(secretKeyN : UByteArray) : UByteArray +} diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/scalarmut/ScalarMultiplication.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/scalarmut/ScalarMultiplication.kt new file mode 100644 index 0000000..a8196b5 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/scalarmut/ScalarMultiplication.kt @@ -0,0 +1,58 @@ +package com.ionspin.kotlin.crypto.scalarmut + +import com.ionspin.kotlin.crypto.util.toPtr +import kotlinx.cinterop.pin +import libsodium.crypto_scalarmult +import libsodium.crypto_scalarmult_base + +actual object ScalarMultiplication { + + /** + * This function can be used to compute a shared secret q given a user's secret key and another user's public key. + * n is crypto_scalarmult_SCALARBYTES bytes long, p and the output are crypto_scalarmult_BYTES bytes long. + * q represents the X coordinate of a point on the curve. As a result, the number of possible keys is limited to + * the group size (≈2^252), which is smaller than the key space. + * For this reason, and to mitigate subtle attacks due to the fact many (p, n) pairs produce the same result, + * using the output of the multiplication q directly as a shared key is not recommended. + * A better way to compute a shared key is h(q ‖ pk1 ‖ pk2), with pk1 and pk2 being the public keys. + * By doing so, each party can prove what exact public key they intended to perform a key exchange with + * (for a given public key, 11 other public keys producing the same shared secret can be trivially computed). + * This can be achieved with the following code snippet: + */ + actual fun scalarMultiplication(secretKeyN: UByteArray, publicKeyP: UByteArray): UByteArray { + val result = UByteArray(crypto_scalarmult_BYTES) + val resultPinned = result.pin() + val secretKeyNPinned = secretKeyN.pin() + val publicKeyPPinned = publicKeyP.pin() + + crypto_scalarmult(resultPinned.toPtr(), secretKeyNPinned.toPtr(), publicKeyPPinned.toPtr()) + + resultPinned.unpin() + secretKeyNPinned.unpin() + publicKeyPPinned.unpin() + + return result + } + + /** + * Given a user's secret key n (crypto_scalarmult_SCALARBYTES bytes), the crypto_scalarmult_base() function + * computes the user's public key and puts it into q (crypto_scalarmult_BYTES bytes). + * crypto_scalarmult_BYTES and crypto_scalarmult_SCALARBYTES are provided for consistency, + * but it is safe to assume that crypto_scalarmult_BYTES == crypto_scalarmult_SCALARBYTES. + */ + actual fun scalarMultiplicationBase( + secretKeyN: UByteArray + ): UByteArray { + val result = UByteArray(crypto_scalarmult_BYTES) + val resultPinned = result.pin() + val secretKeyNPinned = secretKeyN.pin() + + crypto_scalarmult_base(resultPinned.toPtr(), secretKeyNPinned.toPtr()) + + resultPinned.unpin() + secretKeyNPinned.unpin() + + return result + } + +} diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index 8fc774b..50171a8 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -144,7 +144,7 @@ kotlin { implementation(kotlin(Deps.Common.stdLib)) implementation(kotlin(Deps.Common.test)) implementation(Deps.Common.kotlinBigNum) - implementation(project(":multiplatform-crypto-delegated")) + implementation(project(":multiplatform-crypto-libsodium-bindings")) } } val commonTest by getting { diff --git a/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt b/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt index fb7f634..dd58382 100644 --- a/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt +++ b/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt @@ -1,28 +1,12 @@ package com.ionspin.kotlin.crypto.sample -import com.ionspin.kotlin.crypto.Crypto -import com.ionspin.kotlin.crypto.CryptoInitializerDelegated -import com.ionspin.kotlin.crypto.CryptoPrimitives -import com.ionspin.kotlin.crypto.hash.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.LibsodiumRandom import com.ionspin.kotlin.crypto.util.toHexString + object Sample { fun runSample() { - println("Initializing crypto library") - CryptoInitializerDelegated.initializeWithCallback { - blake2b() - } - - - } - - fun blake2b() { - println("Blake2b updateable") - val blake2bUpdateable = CryptoPrimitives.Blake2b.updateable() - blake2bUpdateable.update("test".encodeToUByteArray()) - println(blake2bUpdateable.digest().toHexString()) - println("Blake2b stateless") - val statelessResult = CryptoPrimitives.Blake2b.stateless("test".encodeToUByteArray()) - println("Blake2b stateless: ${statelessResult.toHexString()}") + val random = LibsodiumRandom.buf(32) + println("Random: ${random.toHexString()}") } } diff --git a/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt b/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt index 22b3ead..bdb06de 100644 --- a/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt +++ b/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt @@ -2,7 +2,6 @@ import com.ionspin.kotlin.crypto.sample.Sample import kotlin.time.ExperimentalTime @ExperimentalTime - fun main() { Sample.runSample() diff --git a/sample/src/linuxMain/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt b/sample/src/linuxMain/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt index 1d3c298..3343ed0 100644 --- a/sample/src/linuxMain/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt +++ b/sample/src/linuxMain/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt @@ -1,7 +1,5 @@ import com.ionspin.kotlin.crypto.sample.Sample - - fun main() { Sample.runSample() } diff --git a/supported_bindings_list.md b/supported_bindings_list.md index 976beb2..97345b3 100644 --- a/supported_bindings_list.md +++ b/supported_bindings_list.md @@ -156,6 +156,7 @@ native libsodium library. ## Constants | Constant name| Implemented | +|-------------|-------------| | SODIUM_LIBRARY_VERSION_MAJOR | | | SODIUM_LIBRARY_VERSION_MINOR | | | crypto_aead_chacha20poly1305_ABYTES | |