Skip to content

Commit

Permalink
feat: Implement X25519 - Keypair generation
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianIOHK committed Apr 24, 2023
1 parent ce1c885 commit bbc2394
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,30 @@ import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve
import io.iohk.atala.prism.walletsdk.domain.models.KeyPair
import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey
import io.iohk.atala.prism.walletsdk.domain.models.PublicKey
import org.bouncycastle.jcajce.spec.XDHParameterSpec
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.KeyPairGenerator
import org.bouncycastle.crypto.generators.X25519KeyPairGenerator
import org.bouncycastle.crypto.params.X25519KeyGenerationParameters
import org.bouncycastle.crypto.params.X25519PrivateKeyParameters
import org.bouncycastle.crypto.params.X25519PublicKeyParameters
import java.security.SecureRandom

/**
* X25519
*/
actual object X25519 {
actual fun createKeyPair(): KeyPair {
val provider = BouncyCastleProvider()
val kpg = KeyPairGenerator.getInstance("X25519", provider)
kpg.initialize(XDHParameterSpec(XDHParameterSpec.X25519))
val javaKeyPair = kpg.generateKeyPair()
val generator = X25519KeyPairGenerator()
generator.init(X25519KeyGenerationParameters(SecureRandom()))
val keyPair = generator.generateKeyPair()

return KeyPair(
KeyCurve(Curve.X25519),
PrivateKey(
KeyCurve(Curve.X25519),
javaKeyPair.private.encoded
(keyPair.private as X25519PrivateKeyParameters).encoded
),
PublicKey(
KeyCurve(Curve.X25519),
javaKeyPair.public.encoded
(keyPair.public as X25519PublicKeyParameters).encoded
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ class ApolloImpl : Apollo {
)
}

override fun createKeyPair(seed: Seed, curve: KeyCurve): KeyPair {
override fun createKeyPair(seed: Seed?, curve: KeyCurve): KeyPair {
return when (curve.curve) {
Curve.SECP256K1 -> {
val derivationPath = DerivationPath.fromPath("m/${curve.index}'/0'/0'")
if (seed == null) {
throw ApolloError.InvalidMnemonicWord()
}
val extendedKey = KeyDerivation.deriveKey(seed.value, derivationPath)
val kmmKeyPair = extendedKey.keyPair()
val privateKey = kmmKeyPair.privateKey as KMMECSecp256k1PrivateKey
Expand All @@ -77,10 +80,13 @@ class ApolloImpl : Apollo {
}
}

override fun createKeyPair(seed: Seed, privateKey: PrivateKey): KeyPair {
override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair {
return when (privateKey.keyCurve.curve) {
Curve.SECP256K1 -> {
val derivationPath = DerivationPath.fromPath("m/${privateKey.keyCurve.index}'/0'/0'")
if (seed == null) {
throw ApolloError.InvalidMnemonicWord()
}
val extendedKey = KeyDerivation.deriveKey(seed.value, derivationPath)
val kmmKeyPair = extendedKey.keyPair()
val mPrivateKey = kmmKeyPair.privateKey as KMMECSecp256k1PrivateKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ interface Apollo {
fun createRandomSeed(passphrase: String? = ""): SeedWords

// @JsName("createKeyPairFromKeyCurve")
fun createKeyPair(seed: Seed, curve: KeyCurve): KeyPair
fun createKeyPair(seed: Seed? = null, curve: KeyCurve): KeyPair

// @JsName("createKeyPairFromPrivateKey")
fun createKeyPair(seed: Seed, privateKey: PrivateKey): KeyPair
fun createKeyPair(seed: Seed? = null, privateKey: PrivateKey): KeyPair

// @JsName("compressedPublicKeyFromPublicKey")
fun compressedPublicKey(publicKey: PublicKey): CompressedPublicKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,13 @@ class ApolloTests {

assertTrue(apollo.verifySignature(keyPair.publicKey, text.encodeToByteArray(), signature))
}

@Test
fun testCreateKeyPair_whenNoSeedAndKeyCurveX25519_thenPrivateKeyLengthIsCorrect() {
val keyPair = apollo.createKeyPair(curve = KeyCurve(Curve.X25519))
val privateKey = keyPair.privateKey
val publicKey = keyPair.publicKey
assertEquals(32, privateKey.value.size)
assertEquals(32, publicKey.value.size)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ class ApolloMock : Apollo {
return createRandomSeedReturn
}

override fun createKeyPair(seed: Seed, curve: KeyCurve): KeyPair {
override fun createKeyPair(seed: Seed?, curve: KeyCurve): KeyPair {
return createKeyPairReturn
}

override fun createKeyPair(seed: Seed, privateKey: PrivateKey): KeyPair {
override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair {
return createKeyPairReturn
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ class ApolloMock : Apollo {
return createRandomSeedReturn
}

override fun createKeyPair(seed: Seed, curve: KeyCurve): KeyPair {
override fun createKeyPair(seed: Seed?, curve: KeyCurve): KeyPair {
return createKeyPairReturn
}

override fun createKeyPair(seed: Seed, privateKey: PrivateKey): KeyPair {
override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair {
return createKeyPairReturn
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,30 @@ import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve
import io.iohk.atala.prism.walletsdk.domain.models.KeyPair
import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey
import io.iohk.atala.prism.walletsdk.domain.models.PublicKey
import org.bouncycastle.jcajce.spec.XDHParameterSpec
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.KeyPairGenerator
import org.bouncycastle.crypto.generators.X25519KeyPairGenerator
import org.bouncycastle.crypto.params.X25519KeyGenerationParameters
import org.bouncycastle.crypto.params.X25519PrivateKeyParameters
import org.bouncycastle.crypto.params.X25519PublicKeyParameters
import java.security.SecureRandom

/**
* X25519
*/
actual object X25519 {
actual fun createKeyPair(): KeyPair {
val provider = BouncyCastleProvider()
val kpg = KeyPairGenerator.getInstance("X25519", provider)
kpg.initialize(XDHParameterSpec(XDHParameterSpec.X25519))
val javaKeyPair = kpg.generateKeyPair()
val generator = X25519KeyPairGenerator()
generator.init(X25519KeyGenerationParameters(SecureRandom()))
val keyPair = generator.generateKeyPair()

return KeyPair(
KeyCurve(Curve.X25519),
PrivateKey(
KeyCurve(Curve.X25519),
javaKeyPair.private.encoded
(keyPair.private as X25519PrivateKeyParameters).encoded
),
PublicKey(
KeyCurve(Curve.X25519),
javaKeyPair.public.encoded
(keyPair.public as X25519PublicKeyParameters).encoded
)
)
}
Expand Down

0 comments on commit bbc2394

Please sign in to comment.