Skip to content

Commit

Permalink
feat: implement derivableKey an include it into Secp256k1PrivateKey (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianIOHK authored Nov 27, 2023
1 parent ccfb584 commit cecbbb1
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 6 deletions.
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

0 comments on commit cecbbb1

Please sign in to comment.