From 87e580a4f2b1f0089e27cf43e27f0e0b6c39c6b0 Mon Sep 17 00:00:00 2001 From: Curtis Date: Fri, 21 Jul 2023 14:20:41 +0100 Subject: [PATCH] feat: X25519 jsMain (#74) Co-authored-by: Ahmed Moussa Signed-off-by: Curtis --- base-asymmetric-encryption/build.gradle.kts | 3 ++ .../prism/apollo/utils/KMMX25519KeyPair.kt | 2 +- .../apollo/utils/X25519KeyPairGeneration.kt | 7 ++++- .../apollo/utils/KMMX25519KeyPairTests.kt | 15 ++++++++++ .../prism/apollo/utils/KMMX25519KeyPair.kt | 2 +- .../prism/apollo/utils/KMMX25519KeyPair.kt | 20 +++++++++---- .../prism/apollo/utils/KMMX25519PrivateKey.kt | 8 ++---- .../prism/apollo/utils/KMMX25519PublicKey.kt | 8 ++---- .../prism/apollo/utils/external/Stabelib.kt | 28 +++++++++++++++++++ .../prism/apollo/utils/KMMX25519KeyPair.kt | 2 +- 10 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 base-asymmetric-encryption/src/commonTest/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPairTests.kt create mode 100644 base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/external/Stabelib.kt diff --git a/base-asymmetric-encryption/build.gradle.kts b/base-asymmetric-encryption/build.gradle.kts index 41881afe9..e42694c2c 100644 --- a/base-asymmetric-encryption/build.gradle.kts +++ b/base-asymmetric-encryption/build.gradle.kts @@ -172,9 +172,12 @@ kotlin { } val jsMain by getting { dependencies { + implementation(project(":base64")) + implementation(npm("elliptic", "6.5.4")) implementation(npm("@types/elliptic", "6.4.14")) implementation(npm("@noble/secp256k1", "2.0.0")) + implementation(npm("@stablelib/x25519", "1.0.3")) // Polyfill dependencies implementation(npm("stream-browserify", "3.0.0")) diff --git a/base-asymmetric-encryption/src/androidMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt b/base-asymmetric-encryption/src/androidMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt index 707133a4e..89f10828c 100644 --- a/base-asymmetric-encryption/src/androidMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt +++ b/base-asymmetric-encryption/src/androidMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt @@ -9,7 +9,7 @@ actual class KMMX25519KeyPair actual constructor( actual val publicKey: KMMX25519PublicKey ) { actual companion object : X25519KeyPairGeneration { - override fun generateX25519KeyPair(): KMMX25519KeyPair { + override fun generateKeyPair(): KMMX25519KeyPair { val provider = BouncyCastleProvider() val kpg = KeyPairGenerator.getInstance("X25519", provider) kpg.initialize(XDHParameterSpec(XDHParameterSpec.X25519)) diff --git a/base-asymmetric-encryption/src/commonMain/kotlin/io/iohk/atala/prism/apollo/utils/X25519KeyPairGeneration.kt b/base-asymmetric-encryption/src/commonMain/kotlin/io/iohk/atala/prism/apollo/utils/X25519KeyPairGeneration.kt index cde404954..19b443936 100644 --- a/base-asymmetric-encryption/src/commonMain/kotlin/io/iohk/atala/prism/apollo/utils/X25519KeyPairGeneration.kt +++ b/base-asymmetric-encryption/src/commonMain/kotlin/io/iohk/atala/prism/apollo/utils/X25519KeyPairGeneration.kt @@ -1,5 +1,10 @@ package io.iohk.atala.prism.apollo.utils +import kotlin.js.ExperimentalJsExport +import kotlin.js.JsExport + +@ExperimentalJsExport +@JsExport interface X25519KeyPairGeneration { - fun generateX25519KeyPair(): KMMX25519KeyPair + fun generateKeyPair(): KMMX25519KeyPair } diff --git a/base-asymmetric-encryption/src/commonTest/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPairTests.kt b/base-asymmetric-encryption/src/commonTest/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPairTests.kt new file mode 100644 index 000000000..aefb50b48 --- /dev/null +++ b/base-asymmetric-encryption/src/commonTest/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPairTests.kt @@ -0,0 +1,15 @@ +package io.iohk.atala.prism.apollo.utils + +import kotlin.test.Test +import kotlin.test.assertNotNull + +class KMMX25519KeyPairTests { + @Test + fun testGenerateKeyPair() { + val keyPair = KMMX25519KeyPair.generateKeyPair() + + assertNotNull(keyPair) + assertNotNull(keyPair.privateKey) + assertNotNull(keyPair.publicKey) + } +} diff --git a/base-asymmetric-encryption/src/iosMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt b/base-asymmetric-encryption/src/iosMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt index f1bfdafdb..4294b92c9 100644 --- a/base-asymmetric-encryption/src/iosMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt +++ b/base-asymmetric-encryption/src/iosMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt @@ -5,7 +5,7 @@ actual class KMMX25519KeyPair actual constructor( actual val publicKey: KMMX25519PublicKey ) { actual companion object : X25519KeyPairGeneration { - override fun generateX25519KeyPair(): KMMX25519KeyPair { + override fun generateKeyPair(): KMMX25519KeyPair { val privateKey = KMMX25519PrivateKey() return KMMX25519KeyPair(privateKey, privateKey.publicKey()) } diff --git a/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt index f70a389e9..e8fa1386d 100644 --- a/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt +++ b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt @@ -1,16 +1,24 @@ package io.iohk.atala.prism.apollo.utils +import io.iohk.atala.prism.apollo.base64.base64UrlEncoded +import io.iohk.atala.prism.apollo.utils.external.generateKeyPair as stableLibGenerateKeyPair + +@ExperimentalJsExport +@JsExport actual class KMMX25519KeyPair actual constructor( actual val privateKey: KMMX25519PrivateKey, actual val publicKey: KMMX25519PublicKey ) { - init { - throw NotImplementedError("X25519 is yet to be implemented in JS") - } - actual companion object : X25519KeyPairGeneration { - override fun generateX25519KeyPair(): KMMX25519KeyPair { - throw NotImplementedError("X25519 is yet to be implemented in JS") + override fun generateKeyPair(): KMMX25519KeyPair { + val keyPair = stableLibGenerateKeyPair() + val secretBytes = keyPair.secretKey.buffer.toByteArray().base64UrlEncoded.encodeToByteArray() + val publicBytes = keyPair.publicKey.buffer.toByteArray().base64UrlEncoded.encodeToByteArray() + + return KMMX25519KeyPair( + KMMX25519PrivateKey(secretBytes), + KMMX25519PublicKey(publicBytes) + ) } } } diff --git a/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PrivateKey.kt b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PrivateKey.kt index 51a261605..28ee02f9f 100644 --- a/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PrivateKey.kt +++ b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PrivateKey.kt @@ -1,7 +1,5 @@ package io.iohk.atala.prism.apollo.utils -actual class KMMX25519PrivateKey { - init { - throw NotImplementedError("X25519 is yet to be implemented in JS") - } -} +@ExperimentalJsExport +@JsExport +actual class KMMX25519PrivateKey(val raw: ByteArray) diff --git a/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PublicKey.kt b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PublicKey.kt index 101c6d1d8..f2dbcbd4d 100644 --- a/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PublicKey.kt +++ b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519PublicKey.kt @@ -1,7 +1,5 @@ package io.iohk.atala.prism.apollo.utils -actual class KMMX25519PublicKey { - init { - throw NotImplementedError("X25519 is yet to be implemented in JS") - } -} +@ExperimentalJsExport +@JsExport +actual class KMMX25519PublicKey(val raw: ByteArray) diff --git a/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/external/Stabelib.kt b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/external/Stabelib.kt new file mode 100644 index 000000000..9897fcb6c --- /dev/null +++ b/base-asymmetric-encryption/src/jsMain/kotlin/io/iohk/atala/prism/apollo/utils/external/Stabelib.kt @@ -0,0 +1,28 @@ +// Automatically generated by dukat and then slightly adjusted manually to make it compile +@file:JsModule("@stablelib/x25519") +@file:Suppress("SpellCheckingInspection") + +package io.iohk.atala.prism.apollo.utils.external + +import js.typedarrays.Uint8Array + +external var PUBLIC_KEY_LENGTH: Any + +external var SECRET_KEY_LENGTH: Any + +external var SHARED_KEY_LENGTH: Any + +external fun scalarMult(n: Uint8Array, p: Uint8Array): Uint8Array + +external fun scalarMultBase(n: Uint8Array): Uint8Array + +external interface KeyPair { + var publicKey: Uint8Array + var secretKey: Uint8Array +} + +external fun generateKeyPairFromSeed(seed: Uint8Array): KeyPair + +external fun generateKeyPair(prng: dynamic = definedExternally): KeyPair + +external fun sharedKey(mySecretKey: Uint8Array, theirPublicKey: Uint8Array, rejectZero: Boolean = definedExternally): Uint8Array diff --git a/base-asymmetric-encryption/src/jvmMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt b/base-asymmetric-encryption/src/jvmMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt index 707133a4e..89f10828c 100644 --- a/base-asymmetric-encryption/src/jvmMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt +++ b/base-asymmetric-encryption/src/jvmMain/kotlin/io/iohk/atala/prism/apollo/utils/KMMX25519KeyPair.kt @@ -9,7 +9,7 @@ actual class KMMX25519KeyPair actual constructor( actual val publicKey: KMMX25519PublicKey ) { actual companion object : X25519KeyPairGeneration { - override fun generateX25519KeyPair(): KMMX25519KeyPair { + override fun generateKeyPair(): KMMX25519KeyPair { val provider = BouncyCastleProvider() val kpg = KeyPairGenerator.getInstance("X25519", provider) kpg.initialize(XDHParameterSpec(XDHParameterSpec.X25519))