Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement derivableKey an include it into Secp256k1PrivateKey #112

Merged
merged 2 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ on:
required: false
description: Authorization key
default: 1gnp5fzLTwNBvLBXLk9THLgxe9SLoh+7
pull_request:
branches:
- main
push:
branches:
- main
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ class ApolloImpl : Apollo {

val hdKey = HDKey(seedByteArray, 0, 0)
val derivedHdKey = hdKey.derive(derivationPath)
return Secp256k1PrivateKey(derivedHdKey.getKMMSecp256k1PrivateKey().raw)
val private = Secp256k1PrivateKey(derivedHdKey.getKMMSecp256k1PrivateKey().raw)
private.keySpecification[SeedKey().property] = seed
private.keySpecification[DerivationPathKey().property] = derivationPath
private.keySpecification[IndexKey().property] = "0"
return private
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
package io.iohk.atala.prism.walletsdk.apollo.utils

import io.iohk.atala.prism.apollo.base64.base64UrlEncoded
import io.iohk.atala.prism.apollo.derivation.DerivationPath
import io.iohk.atala.prism.apollo.derivation.HDKey
import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey
import io.iohk.atala.prism.walletsdk.apollo.helpers.BytesOps
import io.iohk.atala.prism.walletsdk.domain.models.Curve
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.CurveKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.CurvePointXKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.CurvePointYKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.DerivableKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.ExportableKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.JWK
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PEMKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PEMKeyType
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.SeedKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.SignableKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.StorableKey

class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey, StorableKey, ExportableKey {
class Secp256k1PrivateKey(nativeValue: ByteArray) :
PrivateKey(),
SignableKey,
StorableKey,
ExportableKey,
DerivableKey {
override val type: KeyTypes = KeyTypes.EC
override val keySpecification: MutableMap<String, String> = mutableMapOf()
override val size: Int
Expand All @@ -42,6 +52,7 @@ class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey, S
keyData = raw
).pemEncoded()
}

override fun getJwk(): JWK {
return JWK(
kty = "OKP",
Expand All @@ -50,7 +61,6 @@ class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey, S
y = getProperty(CurvePointYKey().property).base64UrlEncoded
)
}

override fun jwkWithKid(kid: String): JWK {
return JWK(
kty = "OKP",
Expand All @@ -65,4 +75,14 @@ class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey, S
get() = raw
override val restorationIdentifier: String
get() = "secp256k1+priv"

override fun derive(derivationPath: DerivationPath): PrivateKey {
val seed = getProperty(SeedKey().property)

val seedByteArray = BytesOps.hexToBytes(seed)

val hdKey = HDKey(seedByteArray, 0, 0)
val derivedHdKey = hdKey.derive(derivationPath.toString())
return Secp256k1PrivateKey(derivedHdKey.getKMMSecp256k1PrivateKey().raw)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.iohk.atala.prism.walletsdk.apollo

import io.iohk.atala.prism.apollo.base64.base64UrlEncoded
import io.iohk.atala.prism.apollo.derivation.DerivationPath
import io.iohk.atala.prism.apollo.derivation.Mnemonic
import io.iohk.atala.prism.apollo.derivation.MnemonicHelper
import io.iohk.atala.prism.apollo.utils.ECConfig
Expand All @@ -19,8 +20,12 @@ import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo
import io.iohk.atala.prism.walletsdk.domain.models.Curve
import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve
import io.iohk.atala.prism.walletsdk.domain.models.Seed
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.CurveKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.SeedKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.StorableKey
import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.TypeKey
import kotlinx.serialization.json.Json
import org.junit.Assert.assertNotEquals
import org.junit.Before
Expand Down Expand Up @@ -100,6 +105,26 @@ class ApolloTests {
assertTrue((keyPair.privateKey as Secp256k1PrivateKey).isExportable())
}

@Test
fun testDerivePrivateKey_whenSecp256k1_thenWorksAsExpected() {
val path = "m/0'/0'/0'"

val seed = Seed(Mnemonic.createRandomSeed())

val properties: MutableMap<String, Any> = mutableMapOf()
properties[TypeKey().property] = KeyTypes.EC
properties[SeedKey().property] = BytesOps.bytesToHex(seed.value)
properties[CurveKey().property] = Curve.SECP256K1.value

val privateKey = apollo.createPrivateKey(properties) as Secp256k1PrivateKey
privateKey.derive(DerivationPath.fromPath(path))
assertTrue(privateKey.isDerivable())

val ed25519KeyPair = Ed25519KeyPair.generateKeyPair()
val ed25519PrivateKey = ed25519KeyPair.privateKey as Ed25519PrivateKey
assertFalse(ed25519PrivateKey.isDerivable())
}

@Test
fun testCreateKeyPair_whenNoSeedAndKeyCurveEd25519_thenPrivateKeyLengthIsCorrect() {
val keyPair = Ed25519KeyPair.generateKeyPair()
Expand Down
Loading