Skip to content

Commit

Permalink
feature: ED25519 jsMain
Browse files Browse the repository at this point in the history
  • Loading branch information
curtis-h committed Jul 10, 2023
1 parent 31a913f commit ae0242a
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 22 deletions.
9 changes: 6 additions & 3 deletions base-asymmetric-encryption/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ kotlin {
if (os.isWindows) {
this.enabled = false
}
this.useKarma {
this.useChromeHeadless()
}
// this.useKarma {
// this.use
// this.useChromeHeadless()
// }
}
}
}
Expand Down Expand Up @@ -158,6 +159,8 @@ kotlin {
}
val jsMain by getting {
dependencies {
implementation(project(":base64"))

implementation(npm("elliptic", "6.5.4"))
implementation(npm("@types/elliptic", "6.4.14"))
implementation(npm("bip32", "2.0.6"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package io.iohk.atala.prism.apollo.utils

interface Ed25519KeyPairGeneration {
fun generateEd25519KeyPair(): KMMEdKeyPair
fun generateKeyPair(): KMMEdKeyPair
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ expect class KMMEdKeyPair(privateKey: KMMEdPrivateKey, publicKey: KMMEdPublicKey
val publicKey: KMMEdPublicKey

companion object : Ed25519KeyPairGeneration

fun sign(message: ByteArray): ByteArray

fun verify(message: ByteArray, sig: ByteArray): Boolean
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package io.iohk.atala.prism.apollo.utils

expect class KMMEdPrivateKey
expect class KMMEdPrivateKey {
fun getEncoded(): ByteArray

fun sign(message: ByteArray): ByteArray
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package io.iohk.atala.prism.apollo.utils

expect class KMMEdPublicKey
expect class KMMEdPublicKey {
fun getEncoded(): ByteArray

fun verify(message: ByteArray, sig: ByteArray): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.iohk.atala.prism.apollo.utils

import kotlin.test.Test
import kotlin.test.assertNotNull

class KMMEdKeyPairTests {
@Test
fun testGenerateKeyPair() {
val keyPair = KMMEdKeyPair.generateKeyPair()

assertNotNull(keyPair)
assertNotNull(keyPair.privateKey)
assertNotNull(keyPair.publicKey)
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
package io.iohk.atala.prism.apollo.utils

import io.iohk.atala.prism.apollo.base64.base64UrlEncoded
import io.iohk.atala.prism.apollo.utils.external.eddsa
import io.iohk.atala.prism.apollo.utils.external.rand
import node.buffer.Buffer

actual class KMMEdKeyPair actual constructor(
actual val privateKey: KMMEdPrivateKey,
actual val publicKey: KMMEdPublicKey
) {
init {
// TODO: we will use this lib for JS https://github.com/indutny/elliptic
throw NotImplementedError("Ed25519 is yet to be implemented in JS")
actual fun sign(message: ByteArray): ByteArray {
return privateKey.sign(message)
}

actual fun verify(message: ByteArray, sig: ByteArray): Boolean {
return publicKey.verify(message, sig)
}

actual companion object : Ed25519KeyPairGeneration {
override fun generateEd25519KeyPair(): KMMEdKeyPair {
// TODO: we will use this lib for JS https://github.com/indutny/elliptic
throw NotImplementedError("Ed25519 is yet to be implemented in JS")
override fun generateKeyPair(): KMMEdKeyPair {
val ed25519 = eddsa("ed25519")
val rnd = rand(32)
val secret = Buffer.from(rnd)
val keypair = ed25519.keyFromSecret(secret)
val secretBytes = secret.toByteArray().base64UrlEncoded.encodeToByteArray()
val public = Buffer.from(keypair.getPublic())
val publicBytes = public.toByteArray().base64UrlEncoded.encodeToByteArray()

return KMMEdKeyPair(KMMEdPrivateKey(secretBytes), KMMEdPublicKey(publicBytes))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
package io.iohk.atala.prism.apollo.utils

actual class KMMEdPrivateKey {
import io.iohk.atala.prism.apollo.base64.base64UrlDecodedBytes
import io.iohk.atala.prism.apollo.base64.base64UrlEncoded
import io.iohk.atala.prism.apollo.utils.external.eddsa
import node.buffer.Buffer

actual class KMMEdPrivateKey(val nativeValue: ByteArray) {
private val keyPair: eddsa.KeyPair

init {
// TODO: we will use this lib for JS https://github.com/indutny/elliptic
throw NotImplementedError("Ed25519 is yet to be implemented in JS")
val ed25519 = eddsa("ed25519")
val decoded = nativeValue.decodeToString().base64UrlDecodedBytes
val secret = Buffer.from(decoded)

keyPair = ed25519.keyFromSecret(secret)
}

actual fun getEncoded(): ByteArray {
val secret = Buffer.from(keyPair.getSecret()).toByteArray()
val secretBytes = secret.base64UrlEncoded.encodeToByteArray()
return Buffer.from(secretBytes).toByteArray()
}

actual fun sign(message: ByteArray): ByteArray {
val sig = keyPair.sign(Buffer.from(message))
return Buffer.from(sig.toBytes()).toByteArray()
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
package io.iohk.atala.prism.apollo.utils

actual class KMMEdPublicKey {
import io.iohk.atala.prism.apollo.base64.base64UrlDecodedBytes
import io.iohk.atala.prism.apollo.base64.base64UrlEncoded
import io.iohk.atala.prism.apollo.utils.external.eddsa
import node.buffer.Buffer

actual class KMMEdPublicKey(val nativeValue: ByteArray) {
private val keyPair: eddsa.KeyPair

init {
// TODO: we will use this lib for JS https://github.com/indutny/elliptic
throw NotImplementedError("Ed25519 is yet to be implemented in JS")
val ed25519 = eddsa("ed25519")
val decoded = nativeValue.decodeToString().base64UrlDecodedBytes

keyPair = ed25519.keyFromPublic(decoded)
}

actual fun getEncoded(): ByteArray {
val secret = Buffer.from(keyPair.getSecret()).toByteArray()
val secretBytes = secret.base64UrlEncoded.encodeToByteArray()
return Buffer.from(secretBytes).toByteArray()
}

actual fun verify(message: ByteArray, sig: ByteArray): Boolean {
return keyPair.verify(Buffer.from(message), sig)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
/* ktlint-disable */
package io.iohk.atala.prism.apollo.utils.external

import node.buffer.Buffer
import org.khronos.webgl.Uint8Array
import io.iohk.atala.prism.apollo.utils.external.eddsa.KeyPair as _eddsa_KeyPair
import io.iohk.atala.prism.apollo.utils.external.eddsa.KeyPairOptions as _eddsa_KeyPairOptions
import io.iohk.atala.prism.apollo.utils.external.eddsa.Signature as _eddsa_Signature
import org.khronos.webgl.Uint8Array

external var utils: Any

external var rand: Any
external fun rand(len: Number): dynamic

external var version: Number

Expand Down Expand Up @@ -223,9 +224,11 @@ open external class eddsa(name: String /* "ed25519" */) {
open fun verify(message: String, sig: _eddsa_Signature, pub: Any /* String | Buffer | eddsa.Point | eddsa.KeyPair */): Boolean
open fun hashInt(): BN
open fun keyFromPublic(pub: String): _eddsa_KeyPair
open fun keyFromPublic(pub: ByteArray): _eddsa_KeyPair
open fun keyFromPublic(pub: _eddsa_KeyPair): _eddsa_KeyPair
open fun keyFromPublic(pub: base.BasePoint): _eddsa_KeyPair
open fun keyFromSecret(secret: String): _eddsa_KeyPair
open fun keyFromSecret(secret: Buffer): _eddsa_KeyPair
open fun makeSignature(sig: _eddsa_Signature): _eddsa_Signature
open fun makeSignature(sig: String): _eddsa_Signature
open fun decodePoint(bytes: String): base.BasePoint
Expand All @@ -238,14 +241,17 @@ open external class eddsa(name: String /* "ed25519" */) {
open class Signature {
constructor(eddsa: eddsa, sig: _eddsa_Signature)
constructor(eddsa: eddsa, sig: String)
open fun toBytes(): Buffer
open fun toHex(): String
}
open class KeyPair(eddsa: eddsa, params: _eddsa_KeyPairOptions) {
open fun sign(message: String): _eddsa_Signature
open fun sign(message: Buffer): _eddsa_Signature
open fun verify(message: String, sig: _eddsa_Signature): Boolean
open fun verify(message: String, sig: String): Boolean
open fun getSecret(enc: String /* "hex" */): String
open fun getPublic(enc: String /* "hex" */): String
open fun verify(message: Buffer, sig: Any): Boolean
open fun getSecret(enc: String? = definedExternally /* "hex" */): String
open fun getPublic(enc: String? = definedExternally /* "hex" */): String

companion object {
fun fromPublic(eddsa: eddsa, pub: String): _eddsa_KeyPair
Expand Down

0 comments on commit ae0242a

Please sign in to comment.