From c66fde85022b735c75ab08b0853bfdb8837ee164 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Thu, 15 Oct 2020 20:38:30 +0200 Subject: [PATCH 1/4] 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 | | From 2f62c6011bcd1f40aa400c4834a22ee365e477a1 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Thu, 15 Oct 2020 20:50:09 +0200 Subject: [PATCH 2/4] Added scalarult tests, used case from libsodium scalamult.c test --- .../ScalarMultiplication.kt | 2 +- .../scalarmult/ScalarMultiplicationTest.kt | 50 +++++++++++++++++++ .../ScalarMultiplication.kt | 2 +- 3 files changed, 52 insertions(+), 2 deletions(-) rename multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/{scalarmut => scalarmult}/ScalarMultiplication.kt (97%) create mode 100644 multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt rename multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/{scalarmut => scalarmult}/ScalarMultiplication.kt (98%) 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/scalarmult/ScalarMultiplication.kt similarity index 97% rename from multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/scalarmut/ScalarMultiplication.kt rename to multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/scalarmult/ScalarMultiplication.kt index cd5b214..1d1c93a 100644 --- 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/scalarmult/ScalarMultiplication.kt @@ -1,4 +1,4 @@ -package com.ionspin.kotlin.crypto.scalarmut +package com.ionspin.kotlin.crypto.scalarmult /** * Created by Ugljesa Jovanovic diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt new file mode 100644 index 0000000..813fbd6 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt @@ -0,0 +1,50 @@ +package com.ionspin.kotlin.crypto.scalarmult + +import com.ionspin.kotlin.crypto.util.toHexString +import kotlin.test.Test +import kotlin.test.assertTrue + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 15-Oct-2020 + */ +class ScalarMultiplicationTest { + val aliceSecretKey = ubyteArrayOf( + 0x77U, 0x07U, 0x6dU, 0x0aU, 0x73U, 0x18U, 0xa5U, 0x7dU, 0x3cU, 0x16U, 0xc1U, + 0x72U, 0x51U, 0xb2U, 0x66U, 0x45U, 0xdfU, 0x4cU, 0x2fU, 0x87U, 0xebU, 0xc0U, + 0x99U, 0x2aU, 0xb1U, 0x77U, 0xfbU, 0xa5U, 0x1dU, 0xb9U, 0x2cU, 0x2aU + ) + + val bobSecretKey = ubyteArrayOf( + 0x5dU, 0xabU, 0x08U, 0x7eU, 0x62U, 0x4aU, 0x8aU, 0x4bU, 0x79U, 0xe1U, 0x7fU, + 0x8bU, 0x83U, 0x80U, 0x0eU, 0xe6U, 0x6fU, 0x3bU, 0xb1U, 0x29U, 0x26U, 0x18U, + 0xb6U, 0xfdU, 0x1cU, 0x2fU, 0x8bU, 0x27U, 0xffU, 0x88U, 0xe0U, 0xebU + ) + + + val expectedAlicePublicKeyString = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" + val expectedBobPublickKeyString = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f" + val expectedSharedSecretString = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" + + @Test + fun testScalarMultiplication() { + val alicePublicKey = ScalarMultiplication.scalarMultiplicationBase(aliceSecretKey) + assertTrue { + alicePublicKey.toHexString().equals(expectedAlicePublicKeyString) + } + val bobPublickKey = ScalarMultiplication.scalarMultiplicationBase(bobSecretKey) + assertTrue { + bobPublickKey.toHexString().equals(expectedBobPublickKeyString) + } + val aliceToBobSecret = ScalarMultiplication.scalarMultiplication(aliceSecretKey, bobPublickKey) + val bobToAliceSecret = ScalarMultiplication.scalarMultiplication(bobSecretKey, alicePublicKey) + assertTrue { + aliceToBobSecret.toHexString().equals(expectedSharedSecretString) + } + assertTrue { + bobToAliceSecret.toHexString().equals(expectedSharedSecretString) + } + println(aliceToBobSecret.toHexString()) + } +} 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/scalarmult/ScalarMultiplication.kt similarity index 98% rename from multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/scalarmut/ScalarMultiplication.kt rename to multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt index a8196b5..090354b 100644 --- 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/scalarmult/ScalarMultiplication.kt @@ -1,4 +1,4 @@ -package com.ionspin.kotlin.crypto.scalarmut +package com.ionspin.kotlin.crypto.scalarmult import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.pin From 6c940fe6f29a3e7a976137507c46ae1b51c06fc0 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Thu, 15 Oct 2020 20:58:55 +0200 Subject: [PATCH 3/4] Added js and jvm _scalarmult_ --- .../scalarmult/ScalarMultiplicationTest.kt | 35 ++++++++------- .../kotlin/crypto/JsSodiumInterface.kt | 6 +++ .../crypto/scalarmult/ScalarMultiplication.kt | 40 +++++++++++++++++ .../crypto/scalarmult/ScalarMultiplication.kt | 43 +++++++++++++++++++ 4 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt index 813fbd6..6b60495 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplicationTest.kt @@ -1,5 +1,6 @@ package com.ionspin.kotlin.crypto.scalarmult +import com.ionspin.kotlin.crypto.LibsodiumInitializer import com.ionspin.kotlin.crypto.util.toHexString import kotlin.test.Test import kotlin.test.assertTrue @@ -29,22 +30,24 @@ class ScalarMultiplicationTest { @Test fun testScalarMultiplication() { - val alicePublicKey = ScalarMultiplication.scalarMultiplicationBase(aliceSecretKey) - assertTrue { - alicePublicKey.toHexString().equals(expectedAlicePublicKeyString) + LibsodiumInitializer.initializeWithCallback { + val alicePublicKey = ScalarMultiplication.scalarMultiplicationBase(aliceSecretKey) + assertTrue { + alicePublicKey.toHexString().equals(expectedAlicePublicKeyString) + } + val bobPublickKey = ScalarMultiplication.scalarMultiplicationBase(bobSecretKey) + assertTrue { + bobPublickKey.toHexString().equals(expectedBobPublickKeyString) + } + val aliceToBobSecret = ScalarMultiplication.scalarMultiplication(aliceSecretKey, bobPublickKey) + val bobToAliceSecret = ScalarMultiplication.scalarMultiplication(bobSecretKey, alicePublicKey) + assertTrue { + aliceToBobSecret.toHexString().equals(expectedSharedSecretString) + } + assertTrue { + bobToAliceSecret.toHexString().equals(expectedSharedSecretString) + } + println(aliceToBobSecret.toHexString()) } - val bobPublickKey = ScalarMultiplication.scalarMultiplicationBase(bobSecretKey) - assertTrue { - bobPublickKey.toHexString().equals(expectedBobPublickKeyString) - } - val aliceToBobSecret = ScalarMultiplication.scalarMultiplication(aliceSecretKey, bobPublickKey) - val bobToAliceSecret = ScalarMultiplication.scalarMultiplication(bobSecretKey, alicePublicKey) - assertTrue { - aliceToBobSecret.toHexString().equals(expectedSharedSecretString) - } - assertTrue { - bobToAliceSecret.toHexString().equals(expectedSharedSecretString) - } - println(aliceToBobSecret.toHexString()) } } 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 1bbdf21..a3aa2c5 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 @@ -232,8 +232,14 @@ interface JsSodiumInterface { fun crypto_stream_chacha20_xor(message : Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array fun crypto_stream_chacha20_xor_ic(message : Uint8Array, nonce: Uint8Array, initialCounter: UInt, key: Uint8Array) : Uint8Array + // ---- Stream end ---- + // ---- Scalar multiplication ---- + fun crypto_scalarmult(privateKey: Uint8Array, publicKey: Uint8Array) : Uint8Array + fun crypto_scalarmult_base(privateKey: Uint8Array) : Uint8Array + + // ---- Scalar multiplication end ---- diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt new file mode 100644 index 0000000..ce98b3b --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt @@ -0,0 +1,40 @@ +package com.ionspin.kotlin.crypto.scalarmult + +import com.ionspin.kotlin.crypto.getSodium +import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray +import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array + +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 = getSodium().crypto_scalarmult(secretKeyN.toUInt8Array(), publicKeyP.toUInt8Array()) + + return result.toUByteArray() + } + + /** + * 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 = getSodium().crypto_scalarmult_base( secretKeyN.toUInt8Array()) + + return result.toUByteArray() + } + +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt new file mode 100644 index 0000000..b936a28 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/scalarmult/ScalarMultiplication.kt @@ -0,0 +1,43 @@ +package com.ionspin.kotlin.crypto.scalarmult + +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium + +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) + + sodium.crypto_scalarmult(result.asByteArray(), secretKeyN.asByteArray(), publicKeyP.asByteArray()) + + + 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) + + sodium.crypto_scalarmult_base(result.asByteArray(), secretKeyN.asByteArray()) + + return result + } + +} From d7fa3a3b72a5797f0a903fd4ad0bea76d6c82d2d Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Thu, 15 Oct 2020 21:00:38 +0200 Subject: [PATCH 4/4] Update funciton and constants list --- supported_bindings_list.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/supported_bindings_list.md b/supported_bindings_list.md index 97345b3..ca958d0 100644 --- a/supported_bindings_list.md +++ b/supported_bindings_list.md @@ -104,8 +104,8 @@ native libsodium library. | crypto_pwhash_str | :heavy_check_mark: | | crypto_pwhash_str_needs_rehash | :heavy_check_mark: | | crypto_pwhash_str_verify | :heavy_check_mark: | -| crypto_scalarmult | | -| crypto_scalarmult_base | | +| crypto_scalarmult | :heavy_check_mark: | +| crypto_scalarmult_base | :heavy_check_mark: | | crypto_scalarmult_ristretto255 | not present in LazySodium | | crypto_scalarmult_ristretto255_base | not present in LazySodium | | crypto_secretbox_detached | :heavy_check_mark: | @@ -312,8 +312,8 @@ native libsodium library. | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE | | | crypto_pwhash_scryptsalsa208sha256_SALTBYTES | | | crypto_pwhash_scryptsalsa208sha256_STRBYTES | | -| crypto_scalarmult_BYTES | | -| crypto_scalarmult_SCALARBYTES | | +| crypto_scalarmult_BYTES | :heavy_check_mark: | +| crypto_scalarmult_SCALARBYTES | :heavy_check_mark: | | crypto_scalarmult_curve25519_BYTES | :heavy_check_mark: | | crypto_scalarmult_curve25519_SCALARBYTES | | | crypto_scalarmult_ed25519_BYTES | |