From 52a96384588bd9ec5ab7f3966cd7e4804b280760 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Tue, 12 Sep 2023 13:40:30 -0400 Subject: [PATCH 01/14] feature: apollo abstraction --- atala-prism-sdk/build.gradle.kts | 2 + .../atala/prism/walletsdk/apollo/Ed25519.kt | 75 ------ .../atala/prism/walletsdk/apollo/X25519.kt | 41 --- .../prism/walletsdk/apollo/ApolloImpl.kt | 235 +++++++----------- .../atala/prism/walletsdk/apollo/Ed25519.kt | 38 --- .../atala/prism/walletsdk/apollo/X25519.kt | 16 -- .../prism/walletsdk/apollo/config/ECConfig.kt | 18 ++ .../walletsdk/apollo/helpers/ByteArrayExt.kt | 11 + .../apollo/helpers/JVMBigIntegerExt.kt | 7 + .../walletsdk/apollo/utils/Ed25519KeyPair.kt | 28 +++ .../apollo/utils/Ed25519PrivateKey.kt | 38 +++ .../apollo/utils/Ed25519PublicKey.kt | 31 +++ .../apollo/utils/JVMBigIntegerExt.kt | 18 ++ .../apollo/utils/Secp256k1KeyPair.kt | 31 +++ .../apollo/utils/Secp256k1PrivateKey.kt | 38 +++ .../apollo/utils/Secp256k1PublicKey.kt | 136 ++++++++++ .../walletsdk/apollo/utils/X25519KeyPair.kt | 25 ++ .../apollo/utils/X25519PrivateKey.kt | 27 ++ .../walletsdk/apollo/utils/X25519PublicKey.kt | 19 ++ .../apollo/utils/ec/_ECCoordinate.kt | 13 + .../walletsdk/apollo/utils/ec/_ECPoint.kt | 15 ++ .../prism/walletsdk/castor/CastorImpl.kt | 4 +- .../castor/did/prismdid/PrismDIDPublicKey.kt | 26 +- .../walletsdk/castor/shared/CastorShared.kt | 57 ++++- .../walletsdk/domain/buildingblocks/Apollo.kt | 10 +- .../walletsdk/domain/buildingblocks/Castor.kt | 5 +- .../walletsdk/domain/buildingblocks/Pluto.kt | 2 +- .../walletsdk/domain/buildingblocks/Pollux.kt | 2 +- .../prism/walletsdk/domain/models/KeyCurve.kt | 19 ++ .../prism/walletsdk/domain/models/KeyPair.kt | 46 ---- .../prism/walletsdk/domain/models/PeerDID.kt | 2 + .../walletsdk/domain/models/PrivateKey.kt | 48 ++-- .../models/keyManagement/DerivableKey.kt | 7 + .../domain/models/keyManagement/Key.kt | 66 +++++ .../domain/models/keyManagement/KeyPair.kt | 16 ++ .../models/keyManagement/KeyProperties.kt | 60 +++++ .../domain/models/keyManagement/KeyTypes.kt | 6 + .../domain/models/keyManagement/PrivateKey.kt | 18 ++ .../domain/models/keyManagement/PublicKey.kt | 12 + .../models/keyManagement/SignableKey.kt | 5 + .../models/keyManagement/StorableKey.kt | 13 + .../models/keyManagement/VerifiableKey.kt | 5 + .../resolvers/DIDCommSecretsResolver.kt | 29 ++- .../resolvers/DefaultSecretsResolverImpl.kt | 4 +- .../atala/prism/walletsdk/pluto/PlutoImpl.kt | 99 ++++++-- .../prism/walletsdk/pollux/PolluxImpl.kt | 4 +- .../prism/walletsdk/prismagent/PrismAgent.kt | 4 +- .../atala/prism/walletsdk/apollo/Ed25519.kt | 76 ------ .../atala/prism/walletsdk/apollo/X25519.kt | 41 --- 49 files changed, 973 insertions(+), 575 deletions(-) delete mode 100644 atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt delete mode 100644 atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt delete mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt delete mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/config/ECConfig.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/ByteArrayExt.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/JVMBigIntegerExt.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECCoordinate.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt delete mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/DerivableKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyPair.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyProperties.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyTypes.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/SignableKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/StorableKey.kt create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/VerifiableKey.kt delete mode 100644 atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt delete mode 100644 atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt diff --git a/atala-prism-sdk/build.gradle.kts b/atala-prism-sdk/build.gradle.kts index 8376e568c..b2a5751c8 100644 --- a/atala-prism-sdk/build.gradle.kts +++ b/atala-prism-sdk/build.gradle.kts @@ -131,6 +131,8 @@ kotlin { implementation("com.squareup.sqldelight:coroutines-extensions:1.5.4") api("org.lighthousegames:logging:1.1.2") + + implementation("com.ionspin.kotlin:bignum:0.3.7") } } val commonTest by getting { diff --git a/atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt b/atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt deleted file mode 100644 index c90ddc7b8..000000000 --- a/atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt +++ /dev/null @@ -1,75 +0,0 @@ -package io.iohk.atala.prism.walletsdk.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.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey -import io.iohk.atala.prism.walletsdk.domain.models.Signature -import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator -import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters -import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters -import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters -import org.bouncycastle.crypto.signers.Ed25519Signer -import java.security.SecureRandom - -/** - * Ed25519 is a variation of EdDSA - */ -actual object Ed25519 { - - /** - * Create keypair for [Ed25519]. - * - * @return [KeyPair] for [Ed25519]. - */ - actual fun createKeyPair(): KeyPair { - val generator = Ed25519KeyPairGenerator() - generator.init(Ed25519KeyGenerationParameters(SecureRandom())) - val keyPair = generator.generateKeyPair() - - return KeyPair( - KeyCurve(Curve.ED25519), - PrivateKey( - KeyCurve(Curve.ED25519), - (keyPair.private as Ed25519PrivateKeyParameters).encoded - ), - PublicKey( - KeyCurve(Curve.ED25519), - (keyPair.public as Ed25519PublicKeyParameters).encoded - ) - ) - } - - /** - * Sign the message with [Ed25519]. - * - * @param privateKey key to be used in signing. - * @param message message to sign in [ByteArray] form. - * @return [ByteArray] representing the signature. - */ - actual fun sign(privateKey: PrivateKey, message: ByteArray): ByteArray { - val edPrivateKey = Ed25519PrivateKeyParameters(privateKey.value, 0) - - val signer = Ed25519Signer() - signer.init(true, edPrivateKey) - signer.update(message, 0, message.size) - return signer.generateSignature() - } - - /** - * Verify the signature against [Ed25519]. - * - * @param publicKey key used in verifying. - * @param signature the signature that we need to verify. - * @param message the message that resulted in the provided signature. - * @return [Boolean] whether this verifying was valid or not. - */ - actual fun verify(publicKey: PublicKey, signature: Signature, message: ByteArray): Boolean { - val edPublicKey = Ed25519PublicKeyParameters(publicKey.value, 0) - val verifier = Ed25519Signer() - verifier.init(false, edPublicKey) - verifier.update(message, 0, message.size) - return verifier.verifySignature(signature.value) - } -} diff --git a/atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt b/atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt deleted file mode 100644 index 9be2f892c..000000000 --- a/atala-prism-sdk/src/androidMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.iohk.atala.prism.walletsdk.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.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey -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 { - - /** - * Create keypair for [X25519]. - * - * @return [KeyPair] for [X25519]. - */ - actual fun createKeyPair(): KeyPair { - val generator = X25519KeyPairGenerator() - generator.init(X25519KeyGenerationParameters(SecureRandom())) - val keyPair = generator.generateKeyPair() - - return KeyPair( - KeyCurve(Curve.X25519), - PrivateKey( - KeyCurve(Curve.X25519), - (keyPair.private as X25519PrivateKeyParameters).encoded - ), - PublicKey( - KeyCurve(Curve.X25519), - (keyPair.public as X25519PublicKeyParameters).encoded - ) - ) - } -} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt index 95aca08de..0e0868144 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt @@ -1,27 +1,32 @@ package io.iohk.atala.prism.walletsdk.apollo -import io.iohk.atala.prism.apollo.derivation.DerivationPath import io.iohk.atala.prism.apollo.derivation.KeyDerivation import io.iohk.atala.prism.apollo.derivation.MnemonicCode import io.iohk.atala.prism.apollo.derivation.MnemonicLengthException -import io.iohk.atala.prism.apollo.ecdsa.ECDSAType -import io.iohk.atala.prism.apollo.ecdsa.KMMECDSA import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PublicKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.models.ApolloError import io.iohk.atala.prism.walletsdk.domain.models.CompressedPublicKey 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.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.Seed import io.iohk.atala.prism.walletsdk.domain.models.SeedWords import io.iohk.atala.prism.walletsdk.domain.models.Signature +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters import org.bouncycastle.crypto.params.X25519PrivateKeyParameters -import kotlin.jvm.Throws /** * Apollo defines the set of cryptographic operations that are used in the Atala PRISM. @@ -86,33 +91,15 @@ class ApolloImpl : Apollo { 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 - val publicKey = kmmKeyPair.publicKey as KMMECSecp256k1PublicKey - KeyPair( - keyCurve = curve, - privateKey = PrivateKey( - keyCurve = curve, - value = privateKey.getEncoded(), - ), - publicKey = PublicKey( - curve = curve, - value = publicKey.getEncoded(), - ), - ) + Secp256k1KeyPair.generateKeyPair(seed, curve) } Curve.ED25519 -> { - Ed25519.createKeyPair() + Ed25519KeyPair.generateKeyPair() } Curve.X25519 -> { - X25519.createKeyPair() + X25519KeyPair.generateKeyPair() } } } @@ -125,56 +112,41 @@ class ApolloImpl : Apollo { * @return A [KeyPair] object containing a private and public key. */ override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair { - return when (privateKey.keyCurve.curve) { - Curve.SECP256K1 -> { - val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(privateKey.value) - - KeyPair( - keyCurve = privateKey.keyCurve, - privateKey = PrivateKey( - keyCurve = privateKey.keyCurve, - value = kmmPrivateKey.getEncoded(), - ), - publicKey = PublicKey( - curve = privateKey.keyCurve, - value = kmmPrivateKey.getPublicKey().getEncoded(), - ), + return when (privateKey::class) { + Secp256k1PrivateKey::class -> { + val key = privateKey as Secp256k1PrivateKey + val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(key.getEncoded()) + Secp256k1KeyPair( + privateKey = Secp256k1PrivateKey(kmmPrivateKey.getEncoded()), + publicKey = Secp256k1PublicKey(kmmPrivateKey.getPublicKey().getEncoded()) ) } - Curve.ED25519 -> { - val edPrivateKey = Ed25519PrivateKeyParameters(privateKey.value, 0) + Ed25519PrivateKey::class -> { + val key = privateKey as Ed25519PrivateKey + val edPrivateKey = Ed25519PrivateKeyParameters(key.getEncoded(), 0) val edPublicKey = edPrivateKey.generatePublicKey() - KeyPair( - keyCurve = privateKey.keyCurve, - privateKey = PrivateKey( - keyCurve = privateKey.keyCurve, - value = edPrivateKey.encoded, - ), - publicKey = PublicKey( - curve = privateKey.keyCurve, - value = edPublicKey.encoded, - ), + Ed25519KeyPair( + privateKey = Ed25519PrivateKey(edPrivateKey.encoded), + publicKey = Ed25519PublicKey(edPublicKey.encoded) ) } - Curve.X25519 -> { - val xPrivateKey = X25519PrivateKeyParameters(privateKey.value, 0) + X25519PrivateKey::class -> { + val key = privateKey as X25519PrivateKey + val xPrivateKey = X25519PrivateKeyParameters(key.getEncoded(), 0) val xPublicKey = xPrivateKey.generatePublicKey() - KeyPair( - keyCurve = privateKey.keyCurve, - privateKey = PrivateKey( - keyCurve = privateKey.keyCurve, - value = xPrivateKey.encoded, - ), - publicKey = PublicKey( - curve = privateKey.keyCurve, - value = xPublicKey.encoded, - ), + X25519KeyPair( + privateKey = X25519PrivateKey(xPrivateKey.encoded), + publicKey = X25519PublicKey(xPublicKey.encoded) ) } + + else -> { + throw ApolloError.InvalidKeyCurve() + } } } @@ -184,13 +156,9 @@ class ApolloImpl : Apollo { * @param publicKey The public key to compress. * @return [CompressedPublicKey] */ - override fun compressedPublicKey(publicKey: PublicKey): CompressedPublicKey { - val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromBytes(publicKey.value) - val kmmCompressed = kmmPublicKey.getEncodedCompressed() - return CompressedPublicKey( - uncompressed = publicKey, - value = kmmCompressed, - ) + override fun compressedPublicKey(publicKey: PublicKey): PublicKey { + val compressedRaw = (publicKey as Secp256k1PublicKey).getEncodedCompressed() + return Secp256k1PublicKey(compressedRaw) } /** @@ -199,17 +167,8 @@ class ApolloImpl : Apollo { * @param compressedData The compressed public key data. * @return [CompressedPublicKey] */ - override fun compressedPublicKey(compressedData: ByteArray): CompressedPublicKey { - val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromCompressed(compressedData) - val kmmCompressed = kmmPublicKey.getEncodedCompressed() - val publicKey = PublicKey( - curve = KeyCurve(Curve.SECP256K1), - value = kmmPublicKey.getEncoded(), - ) - return CompressedPublicKey( - uncompressed = publicKey, - value = kmmCompressed, - ) + override fun compressedPublicKey(compressedData: ByteArray): PublicKey { + return Secp256k1PublicKey.secp256k1FromCompressed(compressedData) } /** @@ -224,10 +183,7 @@ class ApolloImpl : Apollo { return when (curve.curve) { Curve.SECP256K1 -> { val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromByteCoordinates(x, y) - PublicKey( - curve = curve, - value = kmmPublicKey.getEncoded(), - ) + Secp256k1PublicKey(kmmPublicKey.getEncoded()) } else -> { @@ -248,10 +204,7 @@ class ApolloImpl : Apollo { return when (curve.curve) { Curve.SECP256K1 -> { val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromBytes(x) - PublicKey( - curve = curve, - value = kmmPublicKey.getEncoded(), - ) + Secp256k1PublicKey(kmmPublicKey.getEncoded()) } else -> { @@ -269,32 +222,32 @@ class ApolloImpl : Apollo { * @return The signature of the message. */ override fun signMessage(privateKey: PrivateKey, message: ByteArray): Signature { - return when (privateKey.keyCurve.curve) { - Curve.SECP256K1 -> { - val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(privateKey.value) - val kmmSignature = KMMECDSA.sign( - type = ECDSAType.ECDSA_SHA256, - data = message, - privateKey = kmmPrivateKey, - ) - Signature( - value = kmmSignature, - ) - } + if (privateKey.isSignable()) { + return when (privateKey::class) { + Secp256k1PrivateKey::class -> { + val key = privateKey as Secp256k1PrivateKey + val signature = key.sign(message) - Curve.ED25519 -> { - val signature = Ed25519.sign( - privateKey = privateKey, - message = message - ) - Signature( - value = signature - ) - } + Signature( + value = signature, + ) + } - else -> { - TODO() + Ed25519PrivateKey::class -> { + val key = privateKey as Ed25519PrivateKey + val signature = key.sign(message) + + Signature( + value = signature + ) + } + + else -> { + TODO() + } } + } else { + throw ApolloError.InvalidKeyCurve() } } @@ -306,25 +259,7 @@ class ApolloImpl : Apollo { * @return The signature of the message. */ override fun signMessage(privateKey: PrivateKey, message: String): Signature { - return when (privateKey.keyCurve.curve) { - Curve.SECP256K1 -> { - signMessage(privateKey, message.encodeToByteArray()) - } - - Curve.ED25519 -> { - val signature = Ed25519.sign( - privateKey = privateKey, - message = message.toByteArray() - ) - Signature( - value = signature - ) - } - - else -> { - TODO() - } - } + return signMessage(privateKey, message.encodeToByteArray()) } /** @@ -337,22 +272,24 @@ class ApolloImpl : Apollo { * @return A boolean value indicating whether the signature is valid or not. */ override fun verifySignature(publicKey: PublicKey, challenge: ByteArray, signature: Signature): Boolean { - return when (publicKey.curve.curve) { - Curve.SECP256K1 -> { - val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromBytes(publicKey.value) - KMMECDSA.verify( - type = ECDSAType.ECDSA_SHA256, - data = challenge, - publicKey = kmmPublicKey, - signature = signature.value, - ) - } - Curve.ED25519 -> { - Ed25519.verify(publicKey, signature, challenge) - } - else -> { - TODO() + if (publicKey.canVerify()) { + return when (publicKey::class) { + Secp256k1PublicKey::class -> { + val key = publicKey as Secp256k1PublicKey + key.verify(challenge, signature.value) + } + + Ed25519PublicKey::class -> { + val key = publicKey as Ed25519PublicKey + key.verify(challenge, signature.value) + } + + else -> { + TODO() + } } + } else { + throw ApolloError.InvalidKeyCurve() } } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt deleted file mode 100644 index 3b6d3d6ce..000000000 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.iohk.atala.prism.walletsdk.apollo - -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 io.iohk.atala.prism.walletsdk.domain.models.Signature - -/** - * Ed25519 is a variation of EdDSA - */ -expect object Ed25519 { - - /** - * Create keypair for [Ed25519]. - * - * @return [KeyPair] for [Ed25519]. - */ - fun createKeyPair(): KeyPair - - /** - * Sign the message with [Ed25519]. - * - * @param privateKey key to be used in signing. - * @param message message to sign in [ByteArray] form. - * @return [ByteArray] representing the signature. - */ - fun sign(privateKey: PrivateKey, message: ByteArray): ByteArray - - /** - * Verify the signature against [Ed25519]. - * - * @param publicKey key used in verifying. - * @param signature the signature that we need to verify. - * @param message the message that resulted in the provided signature. - * @return [Boolean] whether this verifying was valid or not. - */ - fun verify(publicKey: PublicKey, signature: Signature, message: ByteArray): Boolean -} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt deleted file mode 100644 index 958ebd5ce..000000000 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.iohk.atala.prism.walletsdk.apollo - -import io.iohk.atala.prism.walletsdk.domain.models.KeyPair - -/** - * X25519 - */ -expect object X25519 { - - /** - * Create keypair for [X25519]. - * - * @return [KeyPair] for [X25519]. - */ - fun createKeyPair(): KeyPair -} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/config/ECConfig.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/config/ECConfig.kt new file mode 100644 index 000000000..114852b9e --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/config/ECConfig.kt @@ -0,0 +1,18 @@ +package io.iohk.atala.prism.walletsdk.apollo.config + +import com.ionspin.kotlin.bignum.integer.BigInteger + +object ECConfig { + val PRIVATE_KEY_BYTE_SIZE: Int = 32 + internal val PUBLIC_KEY_COORDINATE_BYTE_SIZE: Int = 32 + internal val PUBLIC_KEY_COMPRESSED_BYTE_SIZE: Int = PUBLIC_KEY_COORDINATE_BYTE_SIZE + 1 + val SIGNATURE_MAX_BYTE_SIZE: Int = 72 + val PUBLIC_KEY_BYTE_SIZE: Int = PUBLIC_KEY_COORDINATE_BYTE_SIZE * 2 + 1 + + // Field characteristic p (prime) is equal to 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 + internal val p = BigInteger.parseString("115792089237316195423570985008687907853269984665640564039457584007908834671663", 10) + internal val b = BigInteger(7) + + // n curve order (The order of secp256k1 is n) + internal val n = BigInteger.parseString("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10) +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/ByteArrayExt.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/ByteArrayExt.kt new file mode 100644 index 000000000..11ce5d58f --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/ByteArrayExt.kt @@ -0,0 +1,11 @@ +package io.iohk.atala.prism.walletsdk.apollo.helpers + +fun ByteArray.padStart(length: Int, padValue: Byte): ByteArray { + return if (size >= length) { + this + } else { + val result = ByteArray(length) { padValue } + copyInto(result, length - size) + result + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/JVMBigIntegerExt.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/JVMBigIntegerExt.kt new file mode 100644 index 000000000..fa197eca6 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/helpers/JVMBigIntegerExt.kt @@ -0,0 +1,7 @@ +package io.iohk.atala.prism.walletsdk.apollo.helpers + +import java.math.BigInteger + +fun com.ionspin.kotlin.bignum.integer.BigInteger.toJavaBigInteger(): BigInteger { + return BigInteger(this.signum(), this.toByteArray()) +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt new file mode 100644 index 000000000..23b9cff12 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt @@ -0,0 +1,28 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey +import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator +import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters +import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters +import java.security.SecureRandom + +class Ed25519KeyPair( + override var privateKey: PrivateKey, + override var publicKey: PublicKey +) : KeyPair() { + + companion object { + fun generateKeyPair(): Ed25519KeyPair { + val generator = Ed25519KeyPairGenerator() + generator.init(Ed25519KeyGenerationParameters(SecureRandom())) + val pair = generator.generateKeyPair() + return Ed25519KeyPair( + privateKey = Ed25519PrivateKey(nativeValue = (pair.private as Ed25519PrivateKeyParameters).encoded), + publicKey = Ed25519PublicKey(nativeValue = (pair.public as Ed25519PublicKeyParameters).encoded) + ) + } + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt new file mode 100644 index 000000000..04fc0f0ec --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt @@ -0,0 +1,38 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +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.KeyProperties +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes +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.SignableKey +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters +import org.bouncycastle.crypto.signers.Ed25519Signer + +class Ed25519PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { + + override val type: KeyTypes = KeyTypes.EC + override val keySpecification: MutableMap = mutableMapOf() + override val size: Int + override val raw: ByteArray = nativeValue + + init { + size = raw.size + keySpecification[CurveKey()] = Curve.ED25519.value + } + + override fun publicKey(): PublicKey { + val private = Ed25519PrivateKeyParameters(raw, 0) + val public = private.generatePublicKey() + return Ed25519PublicKey(public.encoded) + } + + override fun sign(message: ByteArray): ByteArray { + val privateParams = Ed25519PrivateKeyParameters(raw, 0) + val signer = Ed25519Signer() + signer.init(true, privateParams) + signer.update(message, 0, message.size) + return signer.generateSignature() + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt new file mode 100644 index 000000000..6b007f335 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt @@ -0,0 +1,31 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +import io.iohk.atala.prism.apollo.base64.base64UrlDecoded +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.KeyProperties +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.VerifiableKey +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters +import org.bouncycastle.crypto.signers.Ed25519Signer + +class Ed25519PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { + override val type: KeyTypes = KeyTypes.EC + override val keySpecification: MutableMap = mutableMapOf() + override val size: Int + override val raw: ByteArray = nativeValue + + init { + size = raw.size + keySpecification[CurveKey()] = Curve.ED25519.value + } + + override fun verify(message: ByteArray, signature: ByteArray): Boolean { + val key = Ed25519PrivateKeyParameters(raw.base64UrlDecoded.toByteArray().inputStream()).generatePublicKey() + val verifier = Ed25519Signer() + verifier.init(false, key) + verifier.update(message, 0, message.size) + return verifier.verifySignature(signature) + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt new file mode 100644 index 000000000..09181265a --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt @@ -0,0 +1,18 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +import com.ionspin.kotlin.bignum.integer.Sign +import java.math.BigInteger + +fun BigInteger.toUnsignedByteArray(): ByteArray { + return toByteArray().dropWhile { it == 0.toByte() }.toByteArray() +} + +fun BigInteger.toKotlinBigInteger(): com.ionspin.kotlin.bignum.integer.BigInteger { + val sign = when (this.signum()) { + -1 -> Sign.NEGATIVE + 0 -> Sign.ZERO + 1 -> Sign.POSITIVE + else -> throw IllegalStateException("Illegal BigInteger sign") + } + return com.ionspin.kotlin.bignum.integer.BigInteger.fromByteArray(this.toUnsignedByteArray(), sign) +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt new file mode 100644 index 000000000..bc73c6a31 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt @@ -0,0 +1,31 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +import io.iohk.atala.prism.apollo.derivation.DerivationPath +import io.iohk.atala.prism.apollo.derivation.KeyDerivation +import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey +import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey +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.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey + +class Secp256k1KeyPair(override var privateKey: PrivateKey, override var publicKey: PublicKey) : KeyPair() { + companion object { + fun generateKeyPair(seed: Seed?, curve: KeyCurve): Secp256k1KeyPair { + val derivationPath = DerivationPath.fromPath("m/${curve.index}'/0'/0'") + if (seed == null) { + // TODO: Custom error for null seed + throw Error("Seed cannot be null") + } + val extendedKey = KeyDerivation.deriveKey(seed.value, derivationPath) + val kmmKeyPair = extendedKey.keyPair() + val privateKey = kmmKeyPair.privateKey as KMMECSecp256k1PrivateKey + val publicKey = kmmKeyPair.publicKey as KMMECSecp256k1PublicKey + return Secp256k1KeyPair( + privateKey = Secp256k1PrivateKey(privateKey.getEncoded()), + publicKey = Secp256k1PublicKey(publicKey.getEncoded()) + ) + } + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt new file mode 100644 index 000000000..e7826d460 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt @@ -0,0 +1,38 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +import io.iohk.atala.prism.apollo.ecdsa.ECDSAType +import io.iohk.atala.prism.apollo.ecdsa.KMMECDSA +import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey +import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey +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.KeyProperties +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes +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.SignableKey + +class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { + override val type: KeyTypes = KeyTypes.EC + override val keySpecification: MutableMap = mutableMapOf() + override val size: Int + override val raw: ByteArray = nativeValue + + init { + size = raw.size + keySpecification[CurveKey()] = Curve.SECP256K1.value + } + + override fun publicKey(): PublicKey { + return Secp256k1PublicKey(KMMECSecp256k1PublicKey.secp256k1FromBytes(raw).getEncoded()) + } + + override fun sign(message: ByteArray): ByteArray { + val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(raw) + return KMMECDSA.sign( + type = ECDSAType.ECDSA_SHA256, + data = message, + privateKey = kmmPrivateKey, + ) + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt new file mode 100644 index 000000000..6b3b950f3 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt @@ -0,0 +1,136 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +import com.ionspin.kotlin.bignum.integer.BigInteger +import com.ionspin.kotlin.bignum.integer.base63.toJavaBigInteger +import io.iohk.atala.prism.apollo.ecdsa.ECDSAType +import io.iohk.atala.prism.apollo.ecdsa.KMMECDSA +import io.iohk.atala.prism.apollo.utils.ECPublicKeyInitializationException +import io.iohk.atala.prism.apollo.utils.KMMECPoint +import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey +import io.iohk.atala.prism.apollo.utils.KMMEllipticCurve +import io.iohk.atala.prism.walletsdk.apollo.config.ECConfig +import io.iohk.atala.prism.walletsdk.apollo.utils.ec._ECPoint +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.CustomKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyProperties +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.VerifiableKey +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey +import org.bouncycastle.jce.ECNamedCurveTable +import org.bouncycastle.jce.provider.BouncyCastleProvider +import org.bouncycastle.jce.spec.ECNamedCurveSpec +import java.security.KeyFactory +import java.security.spec.ECParameterSpec +import java.security.spec.ECPoint +import java.security.spec.ECPublicKeySpec +import kotlin.experimental.and + +class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { + override val type: KeyTypes = KeyTypes.EC + override val keySpecification: MutableMap = mutableMapOf() + override val size: Int + override val raw: ByteArray = nativeValue + + init { + size = raw.size + if (size == ECConfig.PUBLIC_KEY_COMPRESSED_BYTE_SIZE) { + keySpecification[CustomKey("compressed")] = "true" + } else { + keySpecification[CustomKey("compressed")] = "false" + } + keySpecification[CurveKey()] = Curve.SECP256K1.value + } + + override fun verify(message: ByteArray, signature: ByteArray): Boolean { + val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromBytes(raw) + return KMMECDSA.verify( + type = ECDSAType.ECDSA_SHA256, + data = message, + publicKey = kmmPublicKey, + signature = signature, + ) + } + + fun isCompressed(): Boolean { + return ( + keySpecification.containsKey(CustomKey("compressed")) && + keySpecification[CustomKey("compressed")] == "true" + ) + } + + fun getEncodedCompressed(): ByteArray { + if (isCompressed()) { + return raw + } + val size = io.iohk.atala.prism.apollo.utils.ECConfig.PRIVATE_KEY_BYTE_SIZE + val curvePoint = computeCurvePoint(bcecpublicKeyFromSecp256K1()) + val yArr = curvePoint.y.bytes() + val xArr = curvePoint.x.bytes() + val prefix = 2 + (yArr[yArr.size - 1] and 1) + val arr = ByteArray(1 + size) + arr[0] = prefix.toByte() + xArr.copyInto(arr, 1) + return arr + } + + private fun bcecpublicKeyFromSecp256K1(): BCECPublicKey { + val ecParameterSpec = ECNamedCurveTable.getParameterSpec(KMMEllipticCurve.SECP256k1.value) + val ecNamedCurveSpec: ECParameterSpec = ECNamedCurveSpec( + ecParameterSpec.name, + ecParameterSpec.curve, + ecParameterSpec.g, + ecParameterSpec.n + ) + + val bouncyCastlePoint = ecParameterSpec.curve.decodePoint(raw) + val point = + ECPoint(bouncyCastlePoint.xCoord.toBigInteger(), bouncyCastlePoint.yCoord.toBigInteger()) + val spec = ECPublicKeySpec(point, ecNamedCurveSpec) + val provider = BouncyCastleProvider() + val keyFactory = KeyFactory.getInstance("EC", provider) + return keyFactory.generatePublic(spec) as BCECPublicKey + } + + companion object { + fun computeCurvePoint(key: BCECPublicKey): _ECPoint { + val javaPoint = key.w + return _ECPoint(javaPoint.affineX.toKotlinBigInteger(), javaPoint.affineY.toKotlinBigInteger()) + } + + fun secp256k1FromCompressed(compressed: ByteArray): Secp256k1PublicKey { + require(compressed.size == ECConfig.PUBLIC_KEY_COMPRESSED_BYTE_SIZE) { + "Compressed byte array's expected length is ${ECConfig.PUBLIC_KEY_COMPRESSED_BYTE_SIZE}, but got ${compressed.size}" + } + val ecParameterSpec = ECNamedCurveTable.getParameterSpec(KMMEllipticCurve.SECP256k1.value) + val bouncyCastlePoint = ecParameterSpec.curve.decodePoint(compressed) + val point = + ECPoint(bouncyCastlePoint.xCoord.toBigInteger(), bouncyCastlePoint.yCoord.toBigInteger()) + return secp256k1FromBigIntegerCoordinates( + point.affineX.toKotlinBigInteger(), + point.affineY.toKotlinBigInteger() + ) + } + + fun secp256k1FromBigIntegerCoordinates(x: BigInteger, y: BigInteger): Secp256k1PublicKey { + val ecPoint = ECPoint(x.toJavaBigInteger(), y.toJavaBigInteger()) + if (!KMMECSecp256k1PublicKey.isPointOnSecp256k1Curve(KMMECPoint(x, y))) { + throw ECPublicKeyInitializationException("ECPoint corresponding to a public key doesn't belong to Secp256k1 curve") + } + val ecParameterSpec = ECNamedCurveTable.getParameterSpec(KMMEllipticCurve.SECP256k1.value) + val ecNamedCurveSpec: ECParameterSpec = ECNamedCurveSpec( + ecParameterSpec.name, + ecParameterSpec.curve, + ecParameterSpec.g, + ecParameterSpec.n + ) + val spec = ECPublicKeySpec(ecPoint, ecNamedCurveSpec) + val provider = BouncyCastleProvider() + val keyFactory = KeyFactory.getInstance("EC", provider) + val publicKey = keyFactory.generatePublic(spec) as BCECPublicKey + + return Secp256k1PublicKey(publicKey.encoded) + } + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt new file mode 100644 index 000000000..ba9940663 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt @@ -0,0 +1,25 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey +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 + +class X25519KeyPair(override var privateKey: PrivateKey, override var publicKey: PublicKey) : KeyPair() { + + companion object { + fun generateKeyPair(): X25519KeyPair { + val generator = X25519KeyPairGenerator() + generator.init(X25519KeyGenerationParameters(SecureRandom())) + val keyPair = generator.generateKeyPair() + return X25519KeyPair( + privateKey = X25519PrivateKey((keyPair.private as X25519PrivateKeyParameters).encoded), + publicKey = X25519PublicKey((keyPair.public as X25519PublicKeyParameters).encoded), + ) + } + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt new file mode 100644 index 000000000..839d440d4 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt @@ -0,0 +1,27 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +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.KeyProperties +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey +import org.bouncycastle.crypto.params.X25519PrivateKeyParameters + +class X25519PrivateKey(nativeValue: ByteArray) : PrivateKey() { + override val type: KeyTypes = KeyTypes.EC + override val keySpecification: MutableMap = mutableMapOf() + override val size: Int + override val raw: ByteArray = nativeValue + + init { + size = raw.size + keySpecification[CurveKey()] = Curve.X25519.value + } + + override fun publicKey(): PublicKey { + val xPrivateKey = X25519PrivateKeyParameters(raw, 0) + val xPublicKey = xPrivateKey.generatePublicKey() + return X25519PublicKey(xPublicKey.encoded) + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt new file mode 100644 index 000000000..0ef06c30c --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt @@ -0,0 +1,19 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils + +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.KeyProperties +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey + +class X25519PublicKey(nativeValue: ByteArray) : PublicKey() { + override val type: KeyTypes = KeyTypes.EC + override val keySpecification: MutableMap = mutableMapOf() + override val size: Int + override val raw: ByteArray = nativeValue + + init { + size = raw.size + keySpecification[CurveKey()] = Curve.X25519.value + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECCoordinate.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECCoordinate.kt new file mode 100644 index 000000000..130834734 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECCoordinate.kt @@ -0,0 +1,13 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils.ec + +import com.ionspin.kotlin.bignum.integer.BigInteger +import io.iohk.atala.prism.walletsdk.apollo.helpers.padStart + +class _ECCoordinate(val coordinate: BigInteger) { + + fun bytes(): ByteArray = coordinate.toByteArray().padStart(PRIVATE_KEY_BYTE_SIZE, 0) + + companion object { + internal val PRIVATE_KEY_BYTE_SIZE: Int = 32 + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt new file mode 100644 index 000000000..1ade3f708 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt @@ -0,0 +1,15 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils.ec + +import com.ionspin.kotlin.bignum.integer.BigInteger + +class _ECPoint(val x: _ECCoordinate, val y: _ECCoordinate) { + constructor(x: String, y: String) : this( + _ECCoordinate(BigInteger.parseString(x)), + _ECCoordinate(BigInteger.parseString(y)) + ) + + constructor(x: BigInteger, y: BigInteger) : this( + _ECCoordinate(x), + _ECCoordinate(y) + ) +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt index 426aab8c7..04d4a6ab0 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt @@ -9,9 +9,9 @@ import io.iohk.atala.prism.walletsdk.domain.models.CastorError import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument import io.iohk.atala.prism.walletsdk.domain.models.DIDResolver -import io.iohk.atala.prism.walletsdk.domain.models.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.Signature +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import io.iohk.atala.prism.walletsdk.logger.LogComponent import io.iohk.atala.prism.walletsdk.logger.LogLevel import io.iohk.atala.prism.walletsdk.logger.Metadata diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt index 6ae5494c0..e87b992f6 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt @@ -1,12 +1,10 @@ package io.iohk.atala.prism.walletsdk.castor.did.prismdid -import io.iohk.atala.prism.protos.CompressedECKeyData import io.iohk.atala.prism.protos.KeyUsage +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.models.CastorError -import io.iohk.atala.prism.walletsdk.domain.models.CompressedPublicKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey -import pbandk.ByteArr +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import kotlin.jvm.Throws class PrismDIDPublicKey { @@ -29,7 +27,9 @@ class PrismDIDPublicKey { this.usage = proto.usage.fromProto() this.keyData = when (proto.keyData) { is io.iohk.atala.prism.protos.PublicKey.KeyData.CompressedEcKeyData -> { - apollo.compressedPublicKey(compressedData = proto.keyData.value.data.array).uncompressed + // TODO: Is it always secp256k1 + Secp256k1PublicKey(proto.keyData.value.data.array) +// apollo.compressedPublicKey(compressedData = proto.keyData.value.data.array) } else -> { @@ -39,12 +39,12 @@ class PrismDIDPublicKey { } fun toProto(): io.iohk.atala.prism.protos.PublicKey { - val compressed = apollo.compressedPublicKey(keyData) + val compressedPublicKey = apollo.compressedPublicKey(keyData) return io.iohk.atala.prism.protos.PublicKey( id = id, usage = usage.toProto(), keyData = io.iohk.atala.prism.protos.PublicKey.KeyData.CompressedEcKeyData( - compressed.toProto(), + compressedPublicKey.toProto(), ), ) } @@ -75,12 +75,12 @@ fun KeyUsage.fromProto(): PrismDIDPublicKey.Usage { } } -fun CompressedPublicKey.toProto(): CompressedECKeyData { - return CompressedECKeyData( - curve = uncompressed.curve.curve.value, - data = ByteArr(value), - ) -} +// fun PublicKey.toProto(): CompressedECKeyData { +// return CompressedECKeyData( +// curve = uncompressed.curve.curve.value, +// data = ByteArr(value), +// ) +// } fun PrismDIDPublicKey.Usage.id(index: Int): String { return when (this) { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt index b60ba163a..7a668ed06 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt @@ -19,6 +19,12 @@ import io.iohk.atala.prism.didcomm.didpeer.createPeerDIDNumalgo2 import io.iohk.atala.prism.protos.AtalaOperation import io.iohk.atala.prism.protos.CreateDIDOperation import io.iohk.atala.prism.protos.Service +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PublicKey import io.iohk.atala.prism.walletsdk.castor.DID import io.iohk.atala.prism.walletsdk.castor.PRISM import io.iohk.atala.prism.walletsdk.castor.did.DIDParser @@ -35,10 +41,9 @@ import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument import io.iohk.atala.prism.walletsdk.domain.models.DIDDocumentCoreProperty import io.iohk.atala.prism.walletsdk.domain.models.DIDResolver import io.iohk.atala.prism.walletsdk.domain.models.DIDUrl -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.OctetPublicKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import io.iohk.atala.prism.walletsdk.logger.LogComponent import io.iohk.atala.prism.walletsdk.logger.LogLevel import io.iohk.atala.prism.walletsdk.logger.Metadata @@ -398,8 +403,8 @@ internal class CastorShared { val method = DIDDocument.VerificationMethod( id = didUrl, controller = did, - type = publicKey.keyData.curve.curve.value, - publicKeyMultibase = publicKey.keyData.value.base64Encoded, + type = publicKey.keyData.getCurve(), + publicKeyMultibase = publicKey.keyData.getValue().base64Encoded, ) partialResult + (didUrl.string() to method) } @@ -437,10 +442,19 @@ internal class CastorShared { .flatMap { it.verificationMethods.toList() } .mapNotNull { it.publicKeyMultibase?.let { publicKey -> - PublicKey( - curve = KeyCurve(DIDDocument.VerificationMethod.getCurveByType(it.type)), - value = publicKey.encodeToByteArray(), - ) + when (DIDDocument.VerificationMethod.getCurveByType(it.type)) { + Curve.SECP256K1 -> { + Secp256k1PublicKey(publicKey.encodeToByteArray()) + } + + Curve.ED25519 -> { + Ed25519PublicKey(publicKey.encodeToByteArray()) + } + + Curve.X25519 -> { + X25519PublicKey(publicKey.encodeToByteArray()) + } + } } } } @@ -452,7 +466,24 @@ internal class CastorShared { * @return [OctetPublicKey]. */ private fun octetPublicKey(keyPair: KeyPair): OctetPublicKey { - return OctetPublicKey(crv = keyPair.keyCurve.curve.value, x = keyPair.publicKey.value.base64UrlEncoded) + val curve = when (keyPair::class) { + Secp256k1KeyPair::class -> { + Curve.SECP256K1 + } + + Ed25519KeyPair::class -> { + Curve.ED25519 + } + + X25519KeyPair::class -> { + Curve.X25519 + } + + else -> { + throw CastorError.KeyCurveNotSupported(KeyPair::class.simpleName ?: "") + } + } + return OctetPublicKey(crv = curve.value, x = keyPair.publicKey.getValue().base64UrlEncoded) } /** @@ -474,8 +505,8 @@ internal class CastorShared { val signingKeys: MutableList = mutableListOf() keyPairs.forEach { - when (it.keyCurve.curve) { - Curve.X25519 -> { + when (it::class) { + X25519KeyPair::class -> { val octetString = Json.encodeToString(octetPublicKey(it)) encryptionKeys.add( VerificationMaterialAgreement( @@ -486,7 +517,7 @@ internal class CastorShared { ) } - Curve.ED25519 -> { + Ed25519KeyPair::class -> { val octetString = Json.encodeToString(octetPublicKey(it)) signingKeys.add( VerificationMaterialAuthentication( diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt index 75efbb483..073e3de27 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt @@ -3,12 +3,12 @@ package io.iohk.atala.prism.walletsdk.domain.buildingblocks import io.iohk.atala.prism.apollo.derivation.MnemonicLengthException import io.iohk.atala.prism.walletsdk.domain.models.CompressedPublicKey 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 io.iohk.atala.prism.walletsdk.domain.models.Seed import io.iohk.atala.prism.walletsdk.domain.models.SeedWords import io.iohk.atala.prism.walletsdk.domain.models.Signature +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import kotlin.jvm.Throws /** @@ -70,7 +70,7 @@ interface Apollo { * @return [CompressedPublicKey]. */ // @JsName("compressedPublicKeyFromPublicKey") - fun compressedPublicKey(publicKey: PublicKey): CompressedPublicKey + fun compressedPublicKey(publicKey: PublicKey): PublicKey /** * Decompresses a given compressed public key into its original form. @@ -79,7 +79,7 @@ interface Apollo { * @return [CompressedPublicKey]. */ // @JsName("compressedPublicKeyFromCompressedData") - fun compressedPublicKey(compressedData: ByteArray): CompressedPublicKey + fun compressedPublicKey(compressedData: ByteArray): PublicKey /** * Create a public key from byte coordinates. diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Castor.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Castor.kt index 5aa980daf..fd19f38c8 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Castor.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Castor.kt @@ -3,9 +3,8 @@ package io.iohk.atala.prism.walletsdk.domain.buildingblocks import io.iohk.atala.prism.walletsdk.domain.models.CastorError import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument -import io.iohk.atala.prism.walletsdk.domain.models.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey -import kotlin.jvm.Throws +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey /** * Castor is a powerful and flexible library for working with DIDs. Whether you are building a decentralised application diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pluto.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pluto.kt index 34da8e768..ad12c9704 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pluto.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pluto.kt @@ -6,8 +6,8 @@ import io.iohk.atala.prism.walletsdk.domain.models.Mediator import io.iohk.atala.prism.walletsdk.domain.models.Message import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.pluto.CredentialRecovery import ioiohkatalaprismwalletsdkpluto.data.AvailableClaims import kotlinx.coroutines.flow.Flow diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pollux.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pollux.kt index adedc1a6d..ae3768692 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pollux.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Pollux.kt @@ -2,8 +2,8 @@ package io.iohk.atala.prism.walletsdk.domain.buildingblocks import io.iohk.atala.prism.walletsdk.domain.models.Credential import io.iohk.atala.prism.walletsdk.domain.models.DID -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import kotlinx.serialization.json.JsonObject interface Pollux { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt new file mode 100644 index 000000000..0339b675c --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt @@ -0,0 +1,19 @@ +package io.iohk.atala.prism.walletsdk.domain.models + +import kotlinx.serialization.Serializable + +/** + * Data class representing supported key curves for key generation. + */ +@Serializable +data class KeyCurve @JvmOverloads constructor( + val curve: Curve, + val index: Int? = 0 +) + +@Serializable +enum class Curve(val value: String) { + X25519("X25519"), + ED25519("Ed25519"), + SECP256K1("secp256k1"), +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt deleted file mode 100644 index a4e0ac7d0..000000000 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt +++ /dev/null @@ -1,46 +0,0 @@ -package io.iohk.atala.prism.walletsdk.domain.models - -import kotlinx.serialization.Serializable -import kotlin.jvm.JvmOverloads - -/** - * Data class representing a pair of private and public keys for a specific key curve. - */ -@Serializable -data class KeyPair( - val keyCurve: KeyCurve = KeyCurve(Curve.SECP256K1), - val privateKey: PrivateKey, - val publicKey: PublicKey -) - -/** - * Data class representing supported key curves for key generation. - */ -@Serializable -data class KeyCurve @JvmOverloads constructor( - val curve: Curve, - val index: Int? = 0 -) - -@Serializable -enum class Curve(val value: String) { - X25519("X25519"), - ED25519("Ed25519"), - SECP256K1("secp256k1"), -} - -fun getKeyCurveByNameAndIndex(name: String, index: Int?): KeyCurve { - return when (name) { - Curve.X25519.value -> - KeyCurve(Curve.X25519) - - Curve.ED25519.value -> - KeyCurve(Curve.ED25519) - - Curve.SECP256K1.value -> - KeyCurve(Curve.SECP256K1, index) - - else -> - KeyCurve(Curve.SECP256K1, index) - } -} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PeerDID.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PeerDID.kt index 4273b8f8a..657500d7e 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PeerDID.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PeerDID.kt @@ -1,5 +1,7 @@ package io.iohk.atala.prism.walletsdk.domain.models +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey + data class PeerDID( val did: DID, val privateKeys: Array diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PrivateKey.kt index 43c1bbc4e..3a3a825d7 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/PrivateKey.kt @@ -1,30 +1,30 @@ package io.iohk.atala.prism.walletsdk.domain.models -import kotlinx.serialization.Serializable +// import kotlinx.serialization.Serializable /** * Represents a private key with a specific key curve and value. */ -@Serializable -data class PrivateKey( - val keyCurve: KeyCurve, - val value: ByteArray -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || this::class != other::class) return false - - other as PrivateKey - - if (keyCurve != other.keyCurve) return false - if (!value.contentEquals(other.value)) return false - - return true - } - - override fun hashCode(): Int { - var result = keyCurve.hashCode() - result = 31 * result + value.contentHashCode() - return result - } -} +// @Serializable +// data class PrivateKey( +// val keyCurve: KeyCurve, +// val value: ByteArray +// ) { +// override fun equals(other: Any?): Boolean { +// if (this === other) return true +// if (other == null || this::class != other::class) return false +// +// other as PrivateKey +// +// if (keyCurve != other.keyCurve) return false +// if (!value.contentEquals(other.value)) return false +// +// return true +// } +// +// override fun hashCode(): Int { +// var result = keyCurve.hashCode() +// result = 31 * result + value.contentHashCode() +// return result +// } +// } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/DerivableKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/DerivableKey.kt new file mode 100644 index 000000000..e66fbf60b --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/DerivableKey.kt @@ -0,0 +1,7 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +import io.iohk.atala.prism.apollo.derivation.DerivationPath + +interface DerivableKey { + fun derive(derivationPath: DerivationPath): PrivateKey +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt new file mode 100644 index 000000000..379c7bd5f --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt @@ -0,0 +1,66 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +import io.iohk.atala.prism.apollo.base64.base64UrlEncoded +import io.iohk.atala.prism.walletsdk.domain.models.ApolloError +import io.iohk.atala.prism.walletsdk.domain.models.Curve +import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve + +abstract class Key { + abstract val type: KeyTypes + abstract val keySpecification: MutableMap + abstract val size: Int + abstract val raw: ByteArray + + fun getEncoded(): ByteArray { + return raw.base64UrlEncoded.encodeToByteArray() + } + + fun isExportable(): Boolean { + return this is StorableKey + } + + fun isSignable(): Boolean { + return this is SignableKey + } + + fun isDerivable(): Boolean { + return this is DerivableKey + } + + fun canVerify(): Boolean { + return this is VerifiableKey + } + + fun getProperty(name: String): String { + val property = getKeyPropertyByName(name) + if (!keySpecification.containsKey(property)) { + throw Exception("KeySpecification do not contain $name") + } + return this.keySpecification[property].toString() + } + + fun isCurve(curve: String): Boolean { + val keyCurve = keySpecification[CurveKey()] + return keyCurve == curve + } +} + +fun getKeyCurveByNameAndIndex(name: String, index: Int?): KeyCurve { + return when (name) { + Curve.X25519.value -> { + KeyCurve(Curve.X25519) + } + + Curve.ED25519.value -> { + KeyCurve(Curve.ED25519) + } + + Curve.SECP256K1.value -> { + KeyCurve(Curve.SECP256K1, index) + } + + else -> { + throw ApolloError.InvalidKeyCurve() + } + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyPair.kt new file mode 100644 index 000000000..fe379a950 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyPair.kt @@ -0,0 +1,16 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +import kotlinx.serialization.Serializable + +/** + * Data class representing a pair of private and public keys for a specific key curve. + */ +@Serializable +abstract class KeyPair { + abstract var privateKey: PrivateKey + abstract var publicKey: PublicKey + + fun getCurve(): String { + return this.privateKey.getProperty(CurveKey().property) + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyProperties.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyProperties.kt new file mode 100644 index 000000000..6c640a91c --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyProperties.kt @@ -0,0 +1,60 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +abstract class KeyProperties { + abstract val property: String +} + +class AlgorithmKey(override val property: String = "algorithm") : KeyProperties() +class CurveKey(override val property: String = "curve") : KeyProperties() +class SeedKey(override val property: String = "seed") : KeyProperties() +class RawKey(override val property: String = "raw") : KeyProperties() +class DerivationPathKey(override val property: String = "derivationPath") : KeyProperties() +class IndexKey(override val property: String = "index") : KeyProperties() +class TypeKey(override val property: String = "type") : KeyProperties() +class CurvePointXKey(override val property: String = "curvePoint.x") : KeyProperties() +class CurvePointYKey(override val property: String = "curvePoint.y") : KeyProperties() +class CustomKey(override val property: String) : KeyProperties() + +fun getKeyPropertyByName(name: String): KeyProperties { + when (name) { + AlgorithmKey().property -> { + return AlgorithmKey() + } + + CurveKey().property -> { + return CurveKey() + } + + SeedKey().property -> { + return SeedKey() + } + + RawKey().property -> { + return RawKey() + } + + DerivationPathKey().property -> { + return DerivationPathKey() + } + + IndexKey().property -> { + return IndexKey() + } + + TypeKey().property -> { + return TypeKey() + } + + CurvePointXKey().property -> { + return CurvePointXKey() + } + + CurvePointYKey().property -> { + return CurvePointYKey() + } + + else -> { + return CustomKey(name) + } + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyTypes.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyTypes.kt new file mode 100644 index 000000000..24fe30392 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/KeyTypes.kt @@ -0,0 +1,6 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +enum class KeyTypes(val type: String) { + EC("EC"), + Curve25519("Curve25519") +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt new file mode 100644 index 000000000..d7f917afa --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt @@ -0,0 +1,18 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +abstract class PrivateKey : Key() { + + fun getCurve(): String { + return this.getProperty(CurveKey().property) + } + + fun getIndex(): String { + return this.getProperty(IndexKey().property) + } + + fun getValue(): ByteArray { + return this.raw + } + + abstract fun publicKey(): PublicKey +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt new file mode 100644 index 000000000..a26156440 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt @@ -0,0 +1,12 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +abstract class PublicKey : Key() { + + fun getCurve(): String { + return this.getProperty(CurveKey().property) + } + + fun getValue(): ByteArray { + return this.raw + } +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/SignableKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/SignableKey.kt new file mode 100644 index 000000000..f6b4dcb40 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/SignableKey.kt @@ -0,0 +1,5 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +interface SignableKey { + fun sign(message: ByteArray): ByteArray +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/StorableKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/StorableKey.kt new file mode 100644 index 000000000..4a4417937 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/StorableKey.kt @@ -0,0 +1,13 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +enum class SecurityLevel { + HIGH, + LOW +} + +interface StorableKey { + fun store() + val securityLevel: SecurityLevel + val storableData: ByteArray + val restorationIdentifier: String +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/VerifiableKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/VerifiableKey.kt new file mode 100644 index 000000000..380b51dd2 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/VerifiableKey.kt @@ -0,0 +1,5 @@ +package io.iohk.atala.prism.walletsdk.domain.models.keyManagement + +interface VerifiableKey { + fun verify(message: ByteArray, signature: ByteArray): Boolean +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt index 1a7fe6fe7..89c2c5418 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt @@ -1,9 +1,15 @@ package io.iohk.atala.prism.walletsdk.mercury.resolvers import io.iohk.atala.prism.apollo.base64.base64UrlEncoded +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pluto +import io.iohk.atala.prism.walletsdk.domain.models.CastorError +import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.OctetPrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.mercury.OKP import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.runBlocking @@ -28,12 +34,29 @@ class DIDCommSecretsResolver(val pluto: Pluto, val apollo: Apollo) : SecretResol pluto.getDIDPrivateKeyByID(kid) .firstOrNull() ?.let { privateKey -> + val curve = when (privateKey::class) { + Secp256k1PrivateKey::class -> { + Curve.SECP256K1 + } + + Ed25519PrivateKey::class -> { + Curve.ED25519 + } + + X25519PrivateKey::class -> { + Curve.X25519 + } + + else -> { + throw CastorError.KeyCurveNotSupported(KeyPair::class.simpleName ?: "") + } + } val keyPair = apollo.createKeyPair(privateKey = privateKey) val octetJwk = OctetPrivateKey( - crv = privateKey.keyCurve.curve.value, + crv = curve.value, kty = OKP, - d = privateKey.value.base64UrlEncoded, - x = keyPair.publicKey.value.base64UrlEncoded + d = privateKey.getValue().base64UrlEncoded, + x = keyPair.publicKey.getValue().base64UrlEncoded ) Optional.of( Secret( diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt index 5378a276f..06a4153a1 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt @@ -34,8 +34,8 @@ class DefaultSecretsResolverImpl(val pluto: Pluto) : SecretsResolver { SecretMaterialJWK( PrivateJWK( secretId, - privateKey.keyCurve.curve.toString(), - privateKey.value.base64UrlEncoded, + privateKey.getCurve(), + privateKey.getValue().base64UrlEncoded, ).toString(), ), ) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt index 56810bab7..5ce4e47d3 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt @@ -3,11 +3,15 @@ package io.iohk.atala.prism.walletsdk.pluto import com.squareup.sqldelight.runtime.coroutines.asFlow import com.squareup.sqldelight.runtime.coroutines.mapToList import io.iohk.atala.prism.apollo.base64.base64DecodedBytes -import io.iohk.atala.prism.apollo.base64.base64UrlDecodedBytes import io.iohk.atala.prism.apollo.base64.base64UrlEncoded import io.iohk.atala.prism.apollo.uuid.UUID import io.iohk.atala.prism.walletsdk.PrismPlutoDb +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pluto +import io.iohk.atala.prism.walletsdk.domain.models.CastorError +import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDPair import io.iohk.atala.prism.walletsdk.domain.models.Mediator @@ -15,9 +19,10 @@ import io.iohk.atala.prism.walletsdk.domain.models.Message import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PlutoError import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential -import io.iohk.atala.prism.walletsdk.domain.models.getKeyCurveByNameAndIndex +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.getKeyCurveByNameAndIndex import io.iohk.atala.prism.walletsdk.pluto.data.DbConnection import io.iohk.atala.prism.walletsdk.pluto.data.isConnected import ioiohkatalaprismwalletsdkpluto.data.AvailableClaims @@ -127,14 +132,31 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { keyPathIndex: Int, metaId: String? ) { + val curve = when (privateKey::class) { + Secp256k1PrivateKey::class -> { + Curve.SECP256K1 + } + + Ed25519PrivateKey::class -> { + Curve.ED25519 + } + + X25519PrivateKey::class -> { + Curve.X25519 + } + + else -> { + throw CastorError.KeyCurveNotSupported(KeyPair::class.simpleName ?: "") + } + } metaId?.let { id -> val list = getInstance().privateKeyQueries.fetchPrivateKeyByID(id).executeAsList() if (list.isEmpty()) { getInstance().privateKeyQueries.insert( PrivateKeyDB( metaId, - privateKey.keyCurve.curve.value, - privateKey.value.base64UrlEncoded, + curve.value, + privateKey.getValue().base64UrlEncoded, keyPathIndex, did.toString() ) @@ -146,8 +168,8 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { getInstance().privateKeyQueries.insert( PrivateKeyDB( UUID.randomUUID4().toString(), - privateKey.keyCurve.curve.value, - privateKey.value.base64UrlEncoded, + curve.value, + privateKey.getValue().base64UrlEncoded, keyPathIndex, did.toString() ) @@ -260,13 +282,23 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { it.executeAsList() .map { didInfo -> try { - PrivateKey( - getKeyCurveByNameAndIndex( - didInfo.curve, - didInfo.keyPathIndex - ), - didInfo.privateKey.base64DecodedBytes + val keyCurve = getKeyCurveByNameAndIndex( + didInfo.curve, + didInfo.keyPathIndex ) + when (keyCurve.curve) { + Curve.SECP256K1 -> { + Secp256k1PrivateKey(didInfo.privateKey.base64DecodedBytes) + } + + Curve.ED25519 -> { + Ed25519PrivateKey(didInfo.privateKey.base64DecodedBytes) + } + + Curve.X25519 -> { + X25519PrivateKey(didInfo.privateKey.base64DecodedBytes) + } + } } catch (e: IllegalStateException) { null } @@ -280,13 +312,23 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { .asFlow() .map { it -> it.executeAsList().firstOrNull()?.let { - PrivateKey( - getKeyCurveByNameAndIndex( - it.curve, - it.keyPathIndex - ), - it.privateKey.base64UrlDecodedBytes + val keyCurve = getKeyCurveByNameAndIndex( + it.curve, + it.keyPathIndex ) + when (keyCurve.curve) { + Curve.SECP256K1 -> { + Secp256k1PrivateKey(it.privateKey.base64DecodedBytes) + } + + Curve.ED25519 -> { + Ed25519PrivateKey(it.privateKey.base64DecodedBytes) + } + + Curve.X25519 -> { + X25519PrivateKey(it.privateKey.base64DecodedBytes) + } + } } } } @@ -319,10 +361,23 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { .groupBy { allPeerDid -> allPeerDid.did } .map { val privateKeyList = it.value.mapNotNull { data -> - PrivateKey( - getKeyCurveByNameAndIndex(data.curve, data.keyPathIndex), - data.privateKey.base64UrlDecodedBytes + val keyCurve = getKeyCurveByNameAndIndex( + data.curve, + data.keyPathIndex ) + when (keyCurve.curve) { + Curve.SECP256K1 -> { + Secp256k1PrivateKey(data.privateKey.base64DecodedBytes) + } + + Curve.ED25519 -> { + Ed25519PrivateKey(data.privateKey.base64DecodedBytes) + } + + Curve.X25519 -> { + X25519PrivateKey(data.privateKey.base64DecodedBytes) + } + } }.toTypedArray() PeerDID(DID(it.key), privateKeyList) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/PolluxImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/PolluxImpl.kt index 3fc0e3e73..dc7c4ff82 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/PolluxImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/PolluxImpl.kt @@ -12,9 +12,9 @@ import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pollux import io.iohk.atala.prism.walletsdk.domain.models.Credential import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.PolluxError -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential import io.iohk.atala.prism.walletsdk.domain.models.W3CCredential +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject @@ -98,7 +98,7 @@ class PolluxImpl(val castor: Castor) : Pollux { val curveName = KMMEllipticCurve.SECP256k1.value val sp = ECNamedCurveTable.getParameterSpec(curveName) val params: ECParameterSpec = ECNamedCurveSpec(sp.name, sp.curve, sp.g, sp.n, sp.h) - val privateKeySpec = ECPrivateKeySpec(BigInteger(1, privateKey.value), params) + val privateKeySpec = ECPrivateKeySpec(BigInteger(1, privateKey.getValue()), params) val keyFactory = KeyFactory.getInstance(EC, BouncyCastleProvider()) return keyFactory.generatePrivate(privateKeySpec) as ECPrivateKey } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt index d74bbdf54..24da30672 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt @@ -19,15 +19,15 @@ import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument import io.iohk.atala.prism.walletsdk.domain.models.DIDPair 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.Message import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PolluxError import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.Seed import io.iohk.atala.prism.walletsdk.domain.models.Signature import io.iohk.atala.prism.walletsdk.domain.models.httpClient +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.logger.LogComponent import io.iohk.atala.prism.walletsdk.logger.Metadata import io.iohk.atala.prism.walletsdk.logger.PrismLogger diff --git a/atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt b/atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt deleted file mode 100644 index 6f9ca8f08..000000000 --- a/atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/Ed25519.kt +++ /dev/null @@ -1,76 +0,0 @@ -package io.iohk.atala.prism.walletsdk.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.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey -import io.iohk.atala.prism.walletsdk.domain.models.Signature -import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator -import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters -import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters -import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters -import org.bouncycastle.crypto.signers.Ed25519Signer -import java.security.SecureRandom -import io.iohk.atala.prism.walletsdk.domain.models.KeyPair as KeyPairModel - -/** - * Ed25519 is a variation of EdDSA - */ -actual object Ed25519 { - - /** - * Create keypair for [Ed25519]. - * - * @return [KeyPair] for [Ed25519]. - */ - actual fun createKeyPair(): KeyPairModel { - val generator = Ed25519KeyPairGenerator() - generator.init(Ed25519KeyGenerationParameters(SecureRandom())) - val keyPair = generator.generateKeyPair() - - return KeyPairModel( - KeyCurve(Curve.ED25519), - PrivateKey( - KeyCurve(Curve.ED25519), - (keyPair.private as Ed25519PrivateKeyParameters).encoded - ), - PublicKey( - KeyCurve(Curve.ED25519), - (keyPair.public as Ed25519PublicKeyParameters).encoded - ) - ) - } - - /** - * Sign the message with [Ed25519]. - * - * @param privateKey key to be used in signing. - * @param message message to sign in [ByteArray] form. - * @return [ByteArray] representing the signature. - */ - actual fun sign(privateKey: PrivateKey, message: ByteArray): ByteArray { - val edPrivateKey = Ed25519PrivateKeyParameters(privateKey.value, 0) - - val signer = Ed25519Signer() - signer.init(true, edPrivateKey) - signer.update(message, 0, message.size) - return signer.generateSignature() - } - - /** - * Verify the signature against [Ed25519]. - * - * @param publicKey key used in verifying. - * @param signature the signature that we need to verify. - * @param message the message that resulted in the provided signature. - * @return [Boolean] whether this verifying was valid or not. - */ - actual fun verify(publicKey: PublicKey, signature: Signature, message: ByteArray): Boolean { - val edPublicKey = Ed25519PublicKeyParameters(publicKey.value, 0) - val verifier = Ed25519Signer() - verifier.init(false, edPublicKey) - verifier.update(message, 0, message.size) - return verifier.verifySignature(signature.value) - } -} diff --git a/atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt b/atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt deleted file mode 100644 index 9be2f892c..000000000 --- a/atala-prism-sdk/src/jvmMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/X25519.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.iohk.atala.prism.walletsdk.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.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey -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 { - - /** - * Create keypair for [X25519]. - * - * @return [KeyPair] for [X25519]. - */ - actual fun createKeyPair(): KeyPair { - val generator = X25519KeyPairGenerator() - generator.init(X25519KeyGenerationParameters(SecureRandom())) - val keyPair = generator.generateKeyPair() - - return KeyPair( - KeyCurve(Curve.X25519), - PrivateKey( - KeyCurve(Curve.X25519), - (keyPair.private as X25519PrivateKeyParameters).encoded - ), - PublicKey( - KeyCurve(Curve.X25519), - (keyPair.public as X25519PublicKeyParameters).encoded - ) - ) - } -} From 5271535a1d46824c9911b82768804c4d7fd58250 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Wed, 13 Sep 2023 11:42:59 -0400 Subject: [PATCH 02/14] fixing tests --- .../castor/did/prismdid/PrismDIDPublicKey.kt | 19 +++++----- .../prism/walletsdk/apollo/ApolloTests.kt | 16 ++++---- .../prism/walletsdk/castor/ApolloMock.kt | 35 ++++++++--------- .../prism/walletsdk/castor/DIDCreateTest.kt | 38 +++++++++---------- .../castor/PrismDIDPublicKeyTests.kt | 2 +- .../prism/walletsdk/mercury/CastorMock.kt | 4 +- .../prism/walletsdk/mercury/PlutoMock.kt | 6 ++- .../walletsdk/mercury/SecretsResolverTests.kt | 20 +++++----- .../prism/walletsdk/prismagent/ApolloMock.kt | 33 +++++++--------- .../prism/walletsdk/prismagent/CastorMock.kt | 4 +- .../prism/walletsdk/prismagent/PlutoMock.kt | 2 +- .../prism/walletsdk/prismagent/PolluxMock.kt | 2 +- .../walletsdk/prismagent/PrismAgentTests.kt | 6 +-- 13 files changed, 89 insertions(+), 98 deletions(-) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt index e87b992f6..5c1bc3e80 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt @@ -1,10 +1,13 @@ package io.iohk.atala.prism.walletsdk.castor.did.prismdid +import io.iohk.atala.prism.protos.CompressedECKeyData import io.iohk.atala.prism.protos.KeyUsage import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.models.CastorError +import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey +import pbandk.ByteArr import kotlin.jvm.Throws class PrismDIDPublicKey { @@ -27,9 +30,7 @@ class PrismDIDPublicKey { this.usage = proto.usage.fromProto() this.keyData = when (proto.keyData) { is io.iohk.atala.prism.protos.PublicKey.KeyData.CompressedEcKeyData -> { - // TODO: Is it always secp256k1 Secp256k1PublicKey(proto.keyData.value.data.array) -// apollo.compressedPublicKey(compressedData = proto.keyData.value.data.array) } else -> { @@ -39,7 +40,7 @@ class PrismDIDPublicKey { } fun toProto(): io.iohk.atala.prism.protos.PublicKey { - val compressedPublicKey = apollo.compressedPublicKey(keyData) + val compressedPublicKey: Secp256k1PublicKey = apollo.compressedPublicKey(keyData) as Secp256k1PublicKey return io.iohk.atala.prism.protos.PublicKey( id = id, usage = usage.toProto(), @@ -75,12 +76,12 @@ fun KeyUsage.fromProto(): PrismDIDPublicKey.Usage { } } -// fun PublicKey.toProto(): CompressedECKeyData { -// return CompressedECKeyData( -// curve = uncompressed.curve.curve.value, -// data = ByteArr(value), -// ) -// } +fun Secp256k1PublicKey.toProto(): CompressedECKeyData { + return CompressedECKeyData( + curve = Curve.SECP256K1.value, + data = ByteArr(raw), + ) +} fun PrismDIDPublicKey.Usage.id(index: Int): String { return when (this) { diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt index cef20832b..9ab0a23ef 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt @@ -9,7 +9,7 @@ import io.iohk.atala.prism.walletsdk.apollo.helpers.BytesOps 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.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlin.test.BeforeTest @@ -87,8 +87,8 @@ class ApolloTests { @Test fun testKeyPairGeneration() { - assertEquals(keyPair.publicKey.value.size, ECConfig.PUBLIC_KEY_BYTE_SIZE) - assertEquals(keyPair.privateKey.value.size, ECConfig.PRIVATE_KEY_BYTE_SIZE) + assertEquals(keyPair.publicKey.raw.size, ECConfig.PUBLIC_KEY_BYTE_SIZE) + assertEquals(keyPair.privateKey.raw.size, ECConfig.PRIVATE_KEY_BYTE_SIZE) } @Test @@ -106,8 +106,8 @@ class ApolloTests { val keyPair = apollo.createKeyPair(curve = KeyCurve(Curve.ED25519)) val privateKey = keyPair.privateKey val publicKey = keyPair.publicKey - assertEquals(32, privateKey.value.size) - assertEquals(32, publicKey.value.size) + assertEquals(32, privateKey.raw.size) + assertEquals(32, publicKey.raw.size) } @Test @@ -115,8 +115,8 @@ class ApolloTests { 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) + assertEquals(32, privateKey.raw.size) + assertEquals(32, publicKey.raw.size) } @Test @@ -178,7 +178,7 @@ class ApolloTests { val expectedPrivateKeyBase64Url = "xURclKhT6as1Tb9vg4AJRRLPAMWb9dYTTthDvXEKjMc" val keyPair = apollo.createKeyPair(seed, KeyCurve(Curve.SECP256K1)) - assertEquals(expectedPrivateKeyBase64Url, keyPair.privateKey.value.base64UrlEncoded) + assertEquals(expectedPrivateKeyBase64Url, keyPair.privateKey.raw.base64UrlEncoded) } @Test diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt index f66973498..44e494411 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt @@ -1,35 +1,31 @@ package io.iohk.atala.prism.walletsdk.castor +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo -import io.iohk.atala.prism.walletsdk.domain.models.CompressedPublicKey -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.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.Seed import io.iohk.atala.prism.walletsdk.domain.models.SeedWords import io.iohk.atala.prism.walletsdk.domain.models.Signature +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey class ApolloMock : Apollo { var createRandomMnemonicsReturn: Array = emptyArray() var createSeedReturn: Seed = Seed(ByteArray(0)) var createRandomSeedReturn: SeedWords = SeedWords(emptyArray(), Seed(ByteArray(0))) - var createKeyPairReturn: KeyPair = KeyPair( - privateKey = PrivateKey(KeyCurve(Curve.ED25519), ByteArray(0)), - publicKey = PublicKey(KeyCurve(Curve.ED25519), ByteArray(0)), + var createKeyPairReturn: KeyPair = Ed25519KeyPair( + privateKey = Ed25519PrivateKey(ByteArray(0)), + publicKey = Ed25519PublicKey(ByteArray(0)), ) - var compressedPublicKeyReturn: CompressedPublicKey = CompressedPublicKey( - PublicKey(KeyCurve(Curve.SECP256K1), ByteArray(0)), - ByteArray(0), - ) - var publicKeyReturn: PublicKey = PublicKey(KeyCurve(Curve.ED25519), ByteArray(0)) + var compressedPublicKeyReturn: PublicKey = Secp256k1PublicKey(ByteArray(0)) + var publicKeyReturn: PublicKey = Ed25519PublicKey(ByteArray(0)) var signMessageReturn: Signature = Signature(ByteArray(0)) var verifySignatureReturn: Boolean = true - var compressedPublicKeyDataReturn: CompressedPublicKey = CompressedPublicKey( - PublicKey(KeyCurve(Curve.SECP256K1), ByteArray(0)), - ByteArray(0), - ) + var compressedPublicKeyDataReturn: PublicKey = Secp256k1PublicKey(ByteArray(0)) var signMessageByteArrayReturn: Signature = Signature(ByteArray(0)) var signMessageStringReturn: Signature = Signature(ByteArray(0)) @@ -51,10 +47,11 @@ class ApolloMock : Apollo { return createKeyPairReturn } - override fun compressedPublicKey(publicKey: PublicKey): CompressedPublicKey { + override fun compressedPublicKey(publicKey: PublicKey): PublicKey { return compressedPublicKeyReturn } - override fun compressedPublicKey(compressedData: ByteArray): CompressedPublicKey = + + override fun compressedPublicKey(compressedData: ByteArray): PublicKey = compressedPublicKeyDataReturn override fun publicKey(curve: KeyCurve, x: ByteArray, y: ByteArray): PublicKey = diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/DIDCreateTest.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/DIDCreateTest.kt index a72f3eb56..f90216e76 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/DIDCreateTest.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/DIDCreateTest.kt @@ -1,12 +1,14 @@ package io.iohk.atala.prism.walletsdk.castor +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PublicKey import io.iohk.atala.prism.walletsdk.domain.models.CastorError -import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument -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 io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.prismagent.DIDCOMM_MESSAGING import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -19,16 +21,14 @@ class DIDCreateTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun it_should_create_peerDID_correctly() = runTest { - val keyAgreementKeyPair = KeyPair( - KeyCurve(Curve.X25519), - PrivateKey(KeyCurve(Curve.X25519), byteArrayOf(-24, 18, -94, -98, 106, 49, -55, -55, -6, -66, 75, 73, -120, -96, 33, 28, -55, -109, 105, -67, 9, 28, 88, -98, 43, -4, -6, 75, 65, -68, 112, 92)), - PublicKey(KeyCurve(Curve.X25519), byteArrayOf(-16, 16, 107, -82, -125, 83, 101, -94, -103, -112, 47, 117, -90, -100, 64, 77, 62, -4, 11, 101, -53, -64, -2, -77, -106, -16, -63, -54, -42, -59, 80, 23)) + val keyAgreementKeyPair = X25519KeyPair( + X25519PrivateKey(byteArrayOf(-24, 18, -94, -98, 106, 49, -55, -55, -6, -66, 75, 73, -120, -96, 33, 28, -55, -109, 105, -67, 9, 28, 88, -98, 43, -4, -6, 75, 65, -68, 112, 92)), + X25519PublicKey(byteArrayOf(-16, 16, 107, -82, -125, 83, 101, -94, -103, -112, 47, 117, -90, -100, 64, 77, 62, -4, 11, 101, -53, -64, -2, -77, -106, -16, -63, -54, -42, -59, 80, 23)) ) - val authenticationKeyPair = KeyPair( - KeyCurve(Curve.ED25519), - PrivateKey(KeyCurve(Curve.ED25519), byteArrayOf(-68, 7, 65, -41, -60, -42, -9, 55, -113, -80, -86, -106, -40, 97, 81, -13, -22, -124, -58, -39, -64, -126, 75, 88, 126, 39, 51, -52, 121, -64, -5, 35)), - PublicKey(KeyCurve(Curve.ED25519), byteArrayOf(-8, 10, 34, 65, -42, -19, -92, 1, -48, -59, -10, -99, -8, -88, -32, 119, 50, -15, -93, 56, -121, -51, 78, -93, 42, -86, -37, 20, 34, -94, 108, -68)) + val authenticationKeyPair = Ed25519KeyPair( + Ed25519PrivateKey(byteArrayOf(-68, 7, 65, -41, -60, -42, -9, 55, -113, -80, -86, -106, -40, 97, 81, -13, -22, -124, -58, -39, -64, -126, 75, 88, 126, 39, 51, -52, 121, -64, -5, 35)), + Ed25519PublicKey(byteArrayOf(-8, 10, 34, 65, -42, -19, -92, 1, -48, -59, -10, -99, -8, -88, -32, 119, 50, -15, -93, 56, -121, -51, 78, -93, 42, -86, -37, 20, 34, -94, 108, -68)) ) val keyPairs: Array = arrayOf(keyAgreementKeyPair, authenticationKeyPair) @@ -45,14 +45,14 @@ class DIDCreateTest { val verKeyStr = "z6LSci5EK4Ezue5QA72ZX71QUbXY2xr5ygRw7wM1WJigTNnd" val authKeyStr = "z6MkqgCXHEGr2wJZANPZGC8WFmeVuS3abAD9uvh7mTXygCFv" - val fakeVerPrivateKey = PrivateKey(KeyCurve(Curve.ED25519), "".encodeToByteArray()) - val fakeAuthPrivateKey = PrivateKey(KeyCurve(Curve.X25519), "".encodeToByteArray()) + val fakeVerPrivateKey = Ed25519PrivateKey("".encodeToByteArray()) + val fakeAuthPrivateKey = X25519PrivateKey("".encodeToByteArray()) - val verificationPubKey = PublicKey(KeyCurve(Curve.ED25519), verKeyStr.encodeToByteArray()) - val authenticationPubKey = PublicKey(KeyCurve(Curve.X25519), authKeyStr.encodeToByteArray()) + val verificationPubKey = Ed25519PublicKey(verKeyStr.encodeToByteArray()) + val authenticationPubKey = X25519PublicKey(authKeyStr.encodeToByteArray()) - val verificationKeyPair = KeyPair(KeyCurve(Curve.ED25519), fakeVerPrivateKey, verificationPubKey) - val authenticationKeyPair = KeyPair(KeyCurve(Curve.ED25519), fakeAuthPrivateKey, authenticationPubKey) + val verificationKeyPair = Ed25519KeyPair(fakeVerPrivateKey, verificationPubKey) + val authenticationKeyPair = Ed25519KeyPair(fakeAuthPrivateKey, authenticationPubKey) val keyPairs: Array = arrayOf(verificationKeyPair, authenticationKeyPair) diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt index 8186a046f..8dce48a0e 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt @@ -39,7 +39,7 @@ class PrismDIDPublicKeyTests { proto = proto, ) assertEquals(parsedPublicKey.id, "master0") - assertContentEquals(parsedPublicKey.keyData.value, publicKey.keyData.value) + assertContentEquals(parsedPublicKey.keyData.raw, publicKey.keyData.raw) assertEquals(parsedPublicKey.usage, publicKey.usage) } } diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/CastorMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/CastorMock.kt index 49b065a0a..ed774d02d 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/CastorMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/CastorMock.kt @@ -3,8 +3,8 @@ package io.iohk.atala.prism.walletsdk.mercury import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Castor import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument -import io.iohk.atala.prism.walletsdk.domain.models.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import kotlin.jvm.Throws class CastorMock : Castor { diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/PlutoMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/PlutoMock.kt index ea12c2f9b..6befa5e02 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/PlutoMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/PlutoMock.kt @@ -7,8 +7,8 @@ import io.iohk.atala.prism.walletsdk.domain.models.Mediator import io.iohk.atala.prism.walletsdk.domain.models.Message import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.pluto.CredentialRecovery import ioiohkatalaprismwalletsdkpluto.data.AvailableClaims import kotlinx.coroutines.flow.Flow @@ -18,7 +18,9 @@ class PlutoMock : Pluto { var privateKeys = mutableListOf() override fun getDIDPrivateKeyByID(id: String): Flow { - val pk = privateKeys.find { it.keyCurve.curve.value == id } + val pk = privateKeys.find { + it.getCurve() == id + } return flow { emit(pk) } } diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/SecretsResolverTests.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/SecretsResolverTests.kt index 82e3869d4..9daa91ac9 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/SecretsResolverTests.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/mercury/SecretsResolverTests.kt @@ -1,8 +1,6 @@ package io.iohk.atala.prism.walletsdk.mercury -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.PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey import io.iohk.atala.prism.walletsdk.mercury.resolvers.DIDCommSecretsResolver import io.iohk.atala.prism.walletsdk.prismagent.ApolloMock import org.didcommx.didcomm.common.VerificationMaterialFormat @@ -30,8 +28,8 @@ class SecretsResolverTests { @Ignore("Ignore this test for now until we can review with the team.") @Test fun testFindKey() { - val privateKey = PrivateKey(KeyCurve(Curve.X25519), ByteArray(4)) - val kid = privateKey.keyCurve.curve.value + val privateKey = X25519PrivateKey(ByteArray(4)) + val kid = privateKey.getCurve() plutoMock.privateKeys.add(privateKey) val result = sut.findKey(kid) @@ -41,25 +39,25 @@ class SecretsResolverTests { assertTrue { key.kid == kid } assertTrue { key.type == VerificationMethodType.JSON_WEB_KEY_2020 } assertTrue { key.verificationMaterial.format == VerificationMaterialFormat.MULTIBASE } - assertTrue { key.verificationMaterial.value == privateKey.value.toString() } + assertTrue { key.verificationMaterial.value == privateKey.raw.toString() } } @Test fun testFindKeys_kidMatches_isReturned() { - val privateKey = PrivateKey(KeyCurve(Curve.X25519), ByteArray(0)) + val privateKey = X25519PrivateKey(ByteArray(0)) plutoMock.privateKeys.add(privateKey) - val kids = listOf(privateKey.keyCurve.curve.value) + val kids = listOf(privateKey.getCurve()) val result = sut.findKeys(kids) assertTrue { result.size == 1 } - assertContains(result, privateKey.keyCurve.curve.value) + assertContains(result, privateKey.getCurve()) } @Test fun testFindKeys_kidNoMatch_emptySetReturned() { - val privateKey = PrivateKey(KeyCurve(Curve.X25519), ByteArray(0)) - val kids = listOf(privateKey.keyCurve.curve.value) + val privateKey = X25519PrivateKey(ByteArray(0)) + val kids = listOf(privateKey.getCurve()) val result = sut.findKeys(kids) assertTrue { result.isEmpty() } diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt index dc0acbeb0..662329028 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt @@ -1,35 +1,30 @@ package io.iohk.atala.prism.walletsdk.prismagent +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo -import io.iohk.atala.prism.walletsdk.domain.models.CompressedPublicKey -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.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.Seed import io.iohk.atala.prism.walletsdk.domain.models.SeedWords import io.iohk.atala.prism.walletsdk.domain.models.Signature +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey class ApolloMock : Apollo { var createRandomMnemonicsReturn: Array = emptyArray() var createSeedReturn: Seed = Seed(ByteArray(0)) var createRandomSeedReturn: SeedWords = SeedWords(emptyArray(), Seed(ByteArray(0))) - var createKeyPairReturn: KeyPair = KeyPair( - privateKey = PrivateKey(KeyCurve(Curve.ED25519), ByteArray(0)), - publicKey = PublicKey(KeyCurve(Curve.ED25519), ByteArray(0)), + var createKeyPairReturn: KeyPair = Ed25519KeyPair( + privateKey = Ed25519PrivateKey(ByteArray(0)), + publicKey = Ed25519PublicKey(ByteArray(0)), ) - var compressedPublicKeyReturn: CompressedPublicKey = CompressedPublicKey( - PublicKey(KeyCurve(Curve.ED25519), ByteArray(0)), - ByteArray(0), - ) - var publicKeyReturn: PublicKey = PublicKey(KeyCurve(Curve.ED25519), ByteArray(0)) + var compressedPublicKeyReturn = Ed25519PublicKey(ByteArray(0)) + var publicKeyReturn: PublicKey = Ed25519PublicKey(ByteArray(0)) var signMessageReturn: Signature = Signature(ByteArray(0)) var verifySignatureReturn: Boolean = false - var compressedPublicKeyDataReturn: CompressedPublicKey = CompressedPublicKey( - PublicKey(KeyCurve(Curve.ED25519), ByteArray(0)), - ByteArray(0), - ) + var compressedPublicKeyDataReturn: PublicKey = Ed25519PublicKey(ByteArray(0)) var signMessageByteArrayReturn: Signature = Signature(ByteArray(0)) var signMessageStringReturn: Signature = Signature(ByteArray(0)) @@ -51,11 +46,11 @@ class ApolloMock : Apollo { return createKeyPairReturn } - override fun compressedPublicKey(publicKey: PublicKey): CompressedPublicKey { + override fun compressedPublicKey(publicKey: PublicKey): PublicKey { return compressedPublicKeyReturn } - override fun compressedPublicKey(compressedData: ByteArray): CompressedPublicKey = + override fun compressedPublicKey(compressedData: ByteArray): PublicKey = compressedPublicKeyDataReturn override fun publicKey(curve: KeyCurve, x: ByteArray, y: ByteArray): PublicKey = diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/CastorMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/CastorMock.kt index 97d91af95..2556c05e3 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/CastorMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/CastorMock.kt @@ -3,8 +3,8 @@ package io.iohk.atala.prism.walletsdk.prismagent import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Castor import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument -import io.iohk.atala.prism.walletsdk.domain.models.KeyPair -import io.iohk.atala.prism.walletsdk.domain.models.PublicKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey class CastorMock : Castor { var parseDIDReturn: DID? = null diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PlutoMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PlutoMock.kt index 5149de43d..85cb3c2a1 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PlutoMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PlutoMock.kt @@ -7,8 +7,8 @@ import io.iohk.atala.prism.walletsdk.domain.models.Mediator import io.iohk.atala.prism.walletsdk.domain.models.Message import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.pluto.CredentialRecovery import ioiohkatalaprismwalletsdkpluto.data.AvailableClaims import kotlinx.coroutines.flow.Flow diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PolluxMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PolluxMock.kt index ec1563134..7e5fdfe84 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PolluxMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PolluxMock.kt @@ -3,8 +3,8 @@ package io.iohk.atala.prism.walletsdk.prismagent import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pollux import io.iohk.atala.prism.walletsdk.domain.models.Credential import io.iohk.atala.prism.walletsdk.domain.models.DID -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import kotlinx.serialization.json.JsonObject class PolluxMock : Pollux { diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt index 1c9e35368..e2eb14b95 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt @@ -2,12 +2,10 @@ package io.iohk.atala.prism.walletsdk.prismagent /* ktlint-disable import-ordering */ import io.iohk.atala.prism.walletsdk.apollo.ApolloImpl +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey import io.iohk.atala.prism.walletsdk.castor.CastorImpl -import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument -import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve -import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.Seed import io.iohk.atala.prism.walletsdk.domain.models.Signature import io.iohk.atala.prism.walletsdk.logger.PrismLoggerMock @@ -248,7 +246,7 @@ class PrismAgentTests { logger = PrismLoggerMock() ) - val privateKeys = listOf(PrivateKey(KeyCurve(Curve.SECP256K1), byteArrayOf())) + val privateKeys = listOf(Secp256k1PrivateKey(byteArrayOf())) plutoMock.getDIDPrivateKeysReturn = flow { emit(privateKeys) } val did = DID("did", "peer", "asdf1234asdf1234") From fca10fc7f41b0c911ecc82857fcfa11e59568792 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Fri, 15 Sep 2023 11:54:07 -0400 Subject: [PATCH 03/14] fix tests and test sample app --- atala-prism-sdk/build.gradle.kts | 3 ++ .../prism/walletsdk/apollo/ApolloImpl.kt | 26 +++++------ .../apollo/utils/Ed25519PrivateKey.kt | 5 +-- .../apollo/utils/Ed25519PublicKey.kt | 10 ++--- .../apollo/utils/Secp256k1PrivateKey.kt | 5 +-- .../apollo/utils/Secp256k1PublicKey.kt | 13 +++--- .../apollo/utils/X25519PrivateKey.kt | 5 +-- .../walletsdk/apollo/utils/X25519PublicKey.kt | 5 +-- .../prism/walletsdk/domain/models/Message.kt | 1 + .../domain/models/keyManagement/Key.kt | 32 +++++++++++--- .../mercury/forward/ForwardMessage.kt | 2 + .../resolvers/DIDCommSecretsResolver.kt | 25 +---------- .../atala/prism/walletsdk/pluto/PlutoImpl.kt | 43 ++++++------------- 13 files changed, 77 insertions(+), 98 deletions(-) diff --git a/atala-prism-sdk/build.gradle.kts b/atala-prism-sdk/build.gradle.kts index b2a5751c8..b76035910 100644 --- a/atala-prism-sdk/build.gradle.kts +++ b/atala-prism-sdk/build.gradle.kts @@ -204,6 +204,9 @@ android { } } } +dependencies { + testImplementation("org.testng:testng:7.1.0") +} sqldelight { database("PrismPlutoDb") { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt index 0e0868144..9e68babd8 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt @@ -112,19 +112,19 @@ class ApolloImpl : Apollo { * @return A [KeyPair] object containing a private and public key. */ override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair { - return when (privateKey::class) { - Secp256k1PrivateKey::class -> { + return when (privateKey.getCurve()) { + Curve.SECP256K1.value -> { val key = privateKey as Secp256k1PrivateKey - val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(key.getEncoded()) + val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(key.getValue()) Secp256k1KeyPair( privateKey = Secp256k1PrivateKey(kmmPrivateKey.getEncoded()), publicKey = Secp256k1PublicKey(kmmPrivateKey.getPublicKey().getEncoded()) ) } - Ed25519PrivateKey::class -> { + Curve.ED25519.value -> { val key = privateKey as Ed25519PrivateKey - val edPrivateKey = Ed25519PrivateKeyParameters(key.getEncoded(), 0) + val edPrivateKey = Ed25519PrivateKeyParameters(key.getValue(), 0) val edPublicKey = edPrivateKey.generatePublicKey() Ed25519KeyPair( @@ -133,9 +133,9 @@ class ApolloImpl : Apollo { ) } - X25519PrivateKey::class -> { + Curve.X25519.value -> { val key = privateKey as X25519PrivateKey - val xPrivateKey = X25519PrivateKeyParameters(key.getEncoded(), 0) + val xPrivateKey = X25519PrivateKeyParameters(key.getValue(), 0) val xPublicKey = xPrivateKey.generatePublicKey() X25519KeyPair( @@ -223,8 +223,8 @@ class ApolloImpl : Apollo { */ override fun signMessage(privateKey: PrivateKey, message: ByteArray): Signature { if (privateKey.isSignable()) { - return when (privateKey::class) { - Secp256k1PrivateKey::class -> { + return when (privateKey.getCurve()) { + Curve.SECP256K1.value -> { val key = privateKey as Secp256k1PrivateKey val signature = key.sign(message) @@ -233,7 +233,7 @@ class ApolloImpl : Apollo { ) } - Ed25519PrivateKey::class -> { + Curve.ED25519.value -> { val key = privateKey as Ed25519PrivateKey val signature = key.sign(message) @@ -273,13 +273,13 @@ class ApolloImpl : Apollo { */ override fun verifySignature(publicKey: PublicKey, challenge: ByteArray, signature: Signature): Boolean { if (publicKey.canVerify()) { - return when (publicKey::class) { - Secp256k1PublicKey::class -> { + return when (publicKey.getCurve()) { + Curve.SECP256K1.value -> { val key = publicKey as Secp256k1PublicKey key.verify(challenge, signature.value) } - Ed25519PublicKey::class -> { + Curve.ED25519.value -> { val key = publicKey as Ed25519PublicKey key.verify(challenge, signature.value) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt index 04fc0f0ec..56f576ee3 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt @@ -2,7 +2,6 @@ package io.iohk.atala.prism.walletsdk.apollo.utils 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.KeyProperties import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey @@ -13,13 +12,13 @@ import org.bouncycastle.crypto.signers.Ed25519Signer class Ed25519PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { override val type: KeyTypes = KeyTypes.EC - override val keySpecification: MutableMap = mutableMapOf() + override val keySpecification: MutableMap = mutableMapOf() override val size: Int override val raw: ByteArray = nativeValue init { size = raw.size - keySpecification[CurveKey()] = Curve.ED25519.value + keySpecification[CurveKey().property] = Curve.ED25519.value } override fun publicKey(): PublicKey { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt index 6b007f335..b856813a7 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt @@ -1,28 +1,26 @@ package io.iohk.atala.prism.walletsdk.apollo.utils -import io.iohk.atala.prism.apollo.base64.base64UrlDecoded 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.KeyProperties import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.VerifiableKey -import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters +import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters import org.bouncycastle.crypto.signers.Ed25519Signer class Ed25519PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { override val type: KeyTypes = KeyTypes.EC - override val keySpecification: MutableMap = mutableMapOf() + override val keySpecification: MutableMap = mutableMapOf() override val size: Int override val raw: ByteArray = nativeValue init { size = raw.size - keySpecification[CurveKey()] = Curve.ED25519.value + keySpecification[CurveKey().property] = Curve.ED25519.value } override fun verify(message: ByteArray, signature: ByteArray): Boolean { - val key = Ed25519PrivateKeyParameters(raw.base64UrlDecoded.toByteArray().inputStream()).generatePublicKey() + val key = Ed25519PublicKeyParameters(raw, 0) val verifier = Ed25519Signer() verifier.init(false, key) verifier.update(message, 0, message.size) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt index e7826d460..242f1749a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt @@ -6,7 +6,6 @@ import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey 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.KeyProperties import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey @@ -14,13 +13,13 @@ import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.SignableKey class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { override val type: KeyTypes = KeyTypes.EC - override val keySpecification: MutableMap = mutableMapOf() + override val keySpecification: MutableMap = mutableMapOf() override val size: Int override val raw: ByteArray = nativeValue init { size = raw.size - keySpecification[CurveKey()] = Curve.SECP256K1.value + keySpecification[CurveKey().property] = Curve.SECP256K1.value } override fun publicKey(): PublicKey { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt index 6b3b950f3..49928328d 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt @@ -13,7 +13,6 @@ import io.iohk.atala.prism.walletsdk.apollo.utils.ec._ECPoint 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.CustomKey -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyProperties import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.VerifiableKey @@ -29,18 +28,18 @@ import kotlin.experimental.and class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { override val type: KeyTypes = KeyTypes.EC - override val keySpecification: MutableMap = mutableMapOf() + override val keySpecification: MutableMap = mutableMapOf() override val size: Int override val raw: ByteArray = nativeValue init { size = raw.size if (size == ECConfig.PUBLIC_KEY_COMPRESSED_BYTE_SIZE) { - keySpecification[CustomKey("compressed")] = "true" + keySpecification[CustomKey("compressed").property] = "true" } else { - keySpecification[CustomKey("compressed")] = "false" + keySpecification[CustomKey("compressed").property] = "false" } - keySpecification[CurveKey()] = Curve.SECP256K1.value + keySpecification[CurveKey().property] = Curve.SECP256K1.value } override fun verify(message: ByteArray, signature: ByteArray): Boolean { @@ -55,8 +54,8 @@ class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { fun isCompressed(): Boolean { return ( - keySpecification.containsKey(CustomKey("compressed")) && - keySpecification[CustomKey("compressed")] == "true" + keySpecification.containsKey("compressed") && + keySpecification[CustomKey("compressed").property] == "true" ) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt index 839d440d4..916ab94ff 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt @@ -2,7 +2,6 @@ package io.iohk.atala.prism.walletsdk.apollo.utils 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.KeyProperties import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey @@ -10,13 +9,13 @@ import org.bouncycastle.crypto.params.X25519PrivateKeyParameters class X25519PrivateKey(nativeValue: ByteArray) : PrivateKey() { override val type: KeyTypes = KeyTypes.EC - override val keySpecification: MutableMap = mutableMapOf() + override val keySpecification: MutableMap = mutableMapOf() override val size: Int override val raw: ByteArray = nativeValue init { size = raw.size - keySpecification[CurveKey()] = Curve.X25519.value + keySpecification[CurveKey().property] = Curve.X25519.value } override fun publicKey(): PublicKey { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt index 0ef06c30c..b321ae849 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PublicKey.kt @@ -2,18 +2,17 @@ package io.iohk.atala.prism.walletsdk.apollo.utils 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.KeyProperties import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey class X25519PublicKey(nativeValue: ByteArray) : PublicKey() { override val type: KeyTypes = KeyTypes.EC - override val keySpecification: MutableMap = mutableMapOf() + override val keySpecification: MutableMap = mutableMapOf() override val size: Int override val raw: ByteArray = nativeValue init { size = raw.size - keySpecification[CurveKey()] = Curve.X25519.value + keySpecification[CurveKey().property] = Curve.X25519.value } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Message.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Message.kt index fb0aa3bf5..5d8634057 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Message.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Message.kt @@ -16,6 +16,7 @@ import kotlin.time.Duration.Companion.days */ @Serializable data class Message @JvmOverloads constructor( + @EncodeDefault val id: String = UUID.randomUUID4().toString(), val piuri: String, @EncodeDefault val from: DID? = null, diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt index 379c7bd5f..96ccd9de5 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt @@ -7,10 +7,33 @@ import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve abstract class Key { abstract val type: KeyTypes - abstract val keySpecification: MutableMap + abstract val keySpecification: MutableMap abstract val size: Int abstract val raw: ByteArray + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class != other::class) return false + + other as Key + + if (!raw.contentEquals(other.raw)) { + return false + } + if (!keySpecification.containsKey(CurveKey().property) || + keySpecification[CurveKey().property] != other.getProperty(CurveKey().property) + ) { + return false + } + return true + } + + override fun hashCode(): Int { + var result = keySpecification[CurveKey().property].hashCode() + result = 31 * result + raw.contentHashCode() + return result + } + fun getEncoded(): ByteArray { return raw.base64UrlEncoded.encodeToByteArray() } @@ -32,15 +55,14 @@ abstract class Key { } fun getProperty(name: String): String { - val property = getKeyPropertyByName(name) - if (!keySpecification.containsKey(property)) { + if (!keySpecification.containsKey(name)) { throw Exception("KeySpecification do not contain $name") } - return this.keySpecification[property].toString() + return this.keySpecification[name].toString() } fun isCurve(curve: String): Boolean { - val keyCurve = keySpecification[CurveKey()] + val keyCurve = keySpecification[CurveKey().property] return keyCurve == curve } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/forward/ForwardMessage.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/forward/ForwardMessage.kt index 1e3c296e3..2d32a4a2c 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/forward/ForwardMessage.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/forward/ForwardMessage.kt @@ -5,6 +5,7 @@ import io.iohk.atala.prism.walletsdk.domain.models.AttachmentJsonData import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.Message import io.ktor.http.ContentType +import kotlinx.serialization.EncodeDefault import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -15,6 +16,7 @@ class ForwardMessage @JvmOverloads constructor( val from: DID, val to: DID, val encryptedMessage: String, + @EncodeDefault val id: String = UUID.randomUUID().toString() ) { fun makeMessage(): Message { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt index 89c2c5418..f8f486491 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt @@ -1,15 +1,9 @@ package io.iohk.atala.prism.walletsdk.mercury.resolvers import io.iohk.atala.prism.apollo.base64.base64UrlEncoded -import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey -import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey -import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pluto -import io.iohk.atala.prism.walletsdk.domain.models.CastorError -import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.OctetPrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.mercury.OKP import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.runBlocking @@ -34,26 +28,9 @@ class DIDCommSecretsResolver(val pluto: Pluto, val apollo: Apollo) : SecretResol pluto.getDIDPrivateKeyByID(kid) .firstOrNull() ?.let { privateKey -> - val curve = when (privateKey::class) { - Secp256k1PrivateKey::class -> { - Curve.SECP256K1 - } - - Ed25519PrivateKey::class -> { - Curve.ED25519 - } - - X25519PrivateKey::class -> { - Curve.X25519 - } - - else -> { - throw CastorError.KeyCurveNotSupported(KeyPair::class.simpleName ?: "") - } - } val keyPair = apollo.createKeyPair(privateKey = privateKey) val octetJwk = OctetPrivateKey( - crv = curve.value, + crv = privateKey.getCurve(), kty = OKP, d = privateKey.getValue().base64UrlEncoded, x = keyPair.publicKey.getValue().base64UrlEncoded diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt index 5ce4e47d3..92dd0c57a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pluto/PlutoImpl.kt @@ -2,7 +2,7 @@ package io.iohk.atala.prism.walletsdk.pluto import com.squareup.sqldelight.runtime.coroutines.asFlow import com.squareup.sqldelight.runtime.coroutines.mapToList -import io.iohk.atala.prism.apollo.base64.base64DecodedBytes +import io.iohk.atala.prism.apollo.base64.base64UrlDecodedBytes import io.iohk.atala.prism.apollo.base64.base64UrlEncoded import io.iohk.atala.prism.apollo.uuid.UUID import io.iohk.atala.prism.walletsdk.PrismPlutoDb @@ -10,7 +10,6 @@ import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pluto -import io.iohk.atala.prism.walletsdk.domain.models.CastorError import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDPair @@ -20,7 +19,6 @@ import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PlutoError import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.getKeyCurveByNameAndIndex import io.iohk.atala.prism.walletsdk.pluto.data.DbConnection @@ -132,30 +130,13 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { keyPathIndex: Int, metaId: String? ) { - val curve = when (privateKey::class) { - Secp256k1PrivateKey::class -> { - Curve.SECP256K1 - } - - Ed25519PrivateKey::class -> { - Curve.ED25519 - } - - X25519PrivateKey::class -> { - Curve.X25519 - } - - else -> { - throw CastorError.KeyCurveNotSupported(KeyPair::class.simpleName ?: "") - } - } metaId?.let { id -> val list = getInstance().privateKeyQueries.fetchPrivateKeyByID(id).executeAsList() if (list.isEmpty()) { getInstance().privateKeyQueries.insert( PrivateKeyDB( metaId, - curve.value, + privateKey.getCurve(), privateKey.getValue().base64UrlEncoded, keyPathIndex, did.toString() @@ -168,7 +149,7 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { getInstance().privateKeyQueries.insert( PrivateKeyDB( UUID.randomUUID4().toString(), - curve.value, + privateKey.getCurve(), privateKey.getValue().base64UrlEncoded, keyPathIndex, did.toString() @@ -288,15 +269,15 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { ) when (keyCurve.curve) { Curve.SECP256K1 -> { - Secp256k1PrivateKey(didInfo.privateKey.base64DecodedBytes) + Secp256k1PrivateKey(didInfo.privateKey.base64UrlDecodedBytes) } Curve.ED25519 -> { - Ed25519PrivateKey(didInfo.privateKey.base64DecodedBytes) + Ed25519PrivateKey(didInfo.privateKey.base64UrlDecodedBytes) } Curve.X25519 -> { - X25519PrivateKey(didInfo.privateKey.base64DecodedBytes) + X25519PrivateKey(didInfo.privateKey.base64UrlDecodedBytes) } } } catch (e: IllegalStateException) { @@ -318,15 +299,15 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { ) when (keyCurve.curve) { Curve.SECP256K1 -> { - Secp256k1PrivateKey(it.privateKey.base64DecodedBytes) + Secp256k1PrivateKey(it.privateKey.base64UrlDecodedBytes) } Curve.ED25519 -> { - Ed25519PrivateKey(it.privateKey.base64DecodedBytes) + Ed25519PrivateKey(it.privateKey.base64UrlDecodedBytes) } Curve.X25519 -> { - X25519PrivateKey(it.privateKey.base64DecodedBytes) + X25519PrivateKey(it.privateKey.base64UrlDecodedBytes) } } } @@ -367,15 +348,15 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { ) when (keyCurve.curve) { Curve.SECP256K1 -> { - Secp256k1PrivateKey(data.privateKey.base64DecodedBytes) + Secp256k1PrivateKey(data.privateKey.base64UrlDecodedBytes) } Curve.ED25519 -> { - Ed25519PrivateKey(data.privateKey.base64DecodedBytes) + Ed25519PrivateKey(data.privateKey.base64UrlDecodedBytes) } Curve.X25519 -> { - X25519PrivateKey(data.privateKey.base64DecodedBytes) + X25519PrivateKey(data.privateKey.base64UrlDecodedBytes) } } }.toTypedArray() From ce07b4269d496d2edda3bbf499e6eaa5cfc81770 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Tue, 19 Sep 2023 13:17:53 -0400 Subject: [PATCH 04/14] finished testing sample app with the new cryptographic abstraction --- .../domain/models/StorableCredential.kt | 2 ++ .../prism/walletsdk/pollux/JWTCredential.kt | 4 ++++ .../issueCredential/CredentialPreview.kt | 1 + .../issueCredential/OfferCredential.kt | 3 +++ .../java/io/iohk/atala/prism/sampleapp/Sdk.kt | 4 ++-- .../ui/credentials/CredentialsAdapter.kt | 17 ++++++++++------- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/StorableCredential.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/StorableCredential.kt index 2343457ca..8db654177 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/StorableCredential.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/StorableCredential.kt @@ -9,4 +9,6 @@ interface StorableCredential : Credential { val validUntil: String? val revoked: Boolean? val availableClaims: Array + + fun fromStorableCredential(): Credential } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/JWTCredential.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/JWTCredential.kt index 1420a34a7..925e5181a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/JWTCredential.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/pollux/JWTCredential.kt @@ -128,6 +128,10 @@ data class JWTCredential(val data: String) : Credential { return properties.toMap() } + + override fun fromStorableCredential(): Credential { + return c + } } } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/CredentialPreview.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/CredentialPreview.kt index 255a88cc0..1cd64eac2 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/CredentialPreview.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/CredentialPreview.kt @@ -24,6 +24,7 @@ constructor( data class Attribute( val name: String, val value: String, + @SerialName("mime_type") val mimeType: String? ) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/OfferCredential.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/OfferCredential.kt index 46ac22e50..6c224fca5 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/OfferCredential.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/protocols/issueCredential/OfferCredential.kt @@ -78,6 +78,9 @@ data class OfferCredential @JvmOverloads constructor( val fromDID = fromMessage.from val toDID = fromMessage.to + val json = Json { + ignoreUnknownKeys = true + } val body = Json.decodeFromString(fromMessage.body) return OfferCredential( diff --git a/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/Sdk.kt b/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/Sdk.kt index e71ab592b..e156e6aa8 100644 --- a/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/Sdk.kt +++ b/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/Sdk.kt @@ -157,9 +157,9 @@ class Sdk() { private fun initializeHandler() { handler = BasicMediatorHandler( // Roots ID - mediatorDID = DID("did:peer:2.Ez6LSms555YhFthn1WV8ciDBpZm86hK9tp83WojJUmxPGk1hZ.Vz6MkmdBjMyB4TS5UbbQw54szm8yvMMf1ftGV2sQVYAxaeWhE.SeyJpZCI6Im5ldy1pZCIsInQiOiJkbSIsInMiOiJodHRwczovL21lZGlhdG9yLnJvb3RzaWQuY2xvdWQiLCJhIjpbImRpZGNvbW0vdjIiXX0"), +// mediatorDID = DID("did:peer:2.Ez6LSms555YhFthn1WV8ciDBpZm86hK9tp83WojJUmxPGk1hZ.Vz6MkmdBjMyB4TS5UbbQw54szm8yvMMf1ftGV2sQVYAxaeWhE.SeyJpZCI6Im5ldy1pZCIsInQiOiJkbSIsInMiOiJodHRwczovL21lZGlhdG9yLnJvb3RzaWQuY2xvdWQiLCJhIjpbImRpZGNvbW0vdjIiXX0"), // Prism Mediator - // mediatorDID = DID("did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9zaXQtcHJpc20tbWVkaWF0b3IuYXRhbGFwcmlzbS5pbyIsInIiOltdLCJhIjpbImRpZGNvbW0vdjIiXX0"), + mediatorDID = DID("did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9zaXQtcHJpc20tbWVkaWF0b3IuYXRhbGFwcmlzbS5pbyIsInIiOltdLCJhIjpbImRpZGNvbW0vdjIiXX0"), mercury = mercury!!, store = BasicMediatorHandler.PlutoMediatorRepositoryImpl(pluto!!) ) diff --git a/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/ui/credentials/CredentialsAdapter.kt b/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/ui/credentials/CredentialsAdapter.kt index 716ac649f..a375e8f1b 100644 --- a/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/ui/credentials/CredentialsAdapter.kt +++ b/sampleapp/src/main/java/io/iohk/atala/prism/sampleapp/ui/credentials/CredentialsAdapter.kt @@ -8,6 +8,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import io.iohk.atala.prism.sampleapp.R import io.iohk.atala.prism.walletsdk.domain.models.Credential +import io.iohk.atala.prism.walletsdk.domain.models.StorableCredential import io.iohk.atala.prism.walletsdk.domain.models.W3CCredential import io.iohk.atala.prism.walletsdk.pollux.JWTCredential import java.time.Instant @@ -75,9 +76,10 @@ class CredentialsAdapter(private var data: MutableList = mutableList } fun bind(credential: Credential) { - when (credential::class) { + val cred = (credential as StorableCredential).fromStorableCredential() + when (cred::class) { JWTCredential::class -> { - val jwt = credential as JWTCredential + val jwt = cred as JWTCredential type.text = String.format(typeString, "JWT") // TODO: Check what else to display jwt.jwtPayload.nbf?.let { @@ -89,15 +91,16 @@ class CredentialsAdapter(private var data: MutableList = mutableList } W3CCredential::class -> { + val w3c = cred as W3CCredential type.text = String.format(typeString, "W3C") } } } + } - private fun formatTimeStamp(instant: Instant): String { - val localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()) - val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - return localDateTime.format(formatter) - } + private fun formatTimeStamp(instant: Instant): String { + val localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") + return localDateTime.format(formatter) } } From d6798fefb3c088b874948870ce79e4cfa571fa7e Mon Sep 17 00:00:00 2001 From: Cristian G Date: Tue, 19 Sep 2023 15:37:06 -0400 Subject: [PATCH 05/14] fix linting issues --- .../prism/walletsdk/apollo/ApolloImpl.kt | 2 +- .../apollo/utils/Secp256k1PrivateKey.kt | 2 +- .../apollo/utils/Secp256k1PublicKey.kt | 2 +- .../walletsdk/apollo/utils/X25519KeyPair.kt | 2 +- .../castor/did/prismdid/PrismDIDPublicKey.kt | 6 +-- .../walletsdk/castor/shared/CastorShared.kt | 2 +- .../prism/walletsdk/domain/models/KeyCurve.kt | 2 +- .../prism/walletsdk/domain/models/KeyPair.kt | 46 ------------------- .../walletsdk/domain/models/W3CCredential.kt | 5 ++ .../resolvers/DefaultSecretsResolverImpl.kt | 6 +-- .../prism/walletsdk/castor/ApolloMock.kt | 2 +- .../prism/walletsdk/prismagent/ApolloMock.kt | 2 +- 12 files changed, 19 insertions(+), 60 deletions(-) delete mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt index 2852e7cd4..c82721855 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt @@ -229,7 +229,7 @@ class ApolloImpl : Apollo { val signature = key.sign(message) Signature( - value = signature, + value = signature ) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt index 242f1749a..32e6ee3f4 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt @@ -31,7 +31,7 @@ class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { return KMMECDSA.sign( type = ECDSAType.ECDSA_SHA256, data = message, - privateKey = kmmPrivateKey, + privateKey = kmmPrivateKey ) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt index 49928328d..c82061011 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt @@ -48,7 +48,7 @@ class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { type = ECDSAType.ECDSA_SHA256, data = message, publicKey = kmmPublicKey, - signature = signature, + signature = signature ) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt index ba9940663..079677e84 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt @@ -18,7 +18,7 @@ class X25519KeyPair(override var privateKey: PrivateKey, override var publicKey: val keyPair = generator.generateKeyPair() return X25519KeyPair( privateKey = X25519PrivateKey((keyPair.private as X25519PrivateKeyParameters).encoded), - publicKey = X25519PublicKey((keyPair.public as X25519PublicKeyParameters).encoded), + publicKey = X25519PublicKey((keyPair.public as X25519PublicKeyParameters).encoded) ) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt index 0fe47eec4..805af3a72 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt @@ -45,8 +45,8 @@ class PrismDIDPublicKey { id = id, usage = usage.toProto(), keyData = io.iohk.atala.prism.protos.PublicKey.KeyData.CompressedEcKeyData( - compressedPublicKey.toProto(), - ), + compressedPublicKey.toProto() + ) ) } @@ -79,7 +79,7 @@ fun KeyUsage.fromProto(): PrismDIDPublicKey.Usage { fun Secp256k1PublicKey.toProto(): CompressedECKeyData { return CompressedECKeyData( curve = Curve.SECP256K1.value, - data = ByteArr(raw), + data = ByteArr(raw) ) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt index c84880d10..01cc8c81a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/shared/CastorShared.kt @@ -404,7 +404,7 @@ internal class CastorShared { id = didUrl, controller = did, type = publicKey.keyData.getCurve(), - publicKeyMultibase = publicKey.keyData.getValue().base64Encoded, + publicKeyMultibase = publicKey.keyData.getValue().base64Encoded ) partialResult + (didUrl.string() to method) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt index 0339b675c..057aad1db 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyCurve.kt @@ -15,5 +15,5 @@ data class KeyCurve @JvmOverloads constructor( enum class Curve(val value: String) { X25519("X25519"), ED25519("Ed25519"), - SECP256K1("secp256k1"), + SECP256K1("secp256k1") } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt deleted file mode 100644 index 44bec73eb..000000000 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/KeyPair.kt +++ /dev/null @@ -1,46 +0,0 @@ -package io.iohk.atala.prism.walletsdk.domain.models - -import kotlinx.serialization.Serializable -import kotlin.jvm.JvmOverloads - -/** - * Data class representing a pair of private and public keys for a specific key curve. - */ -@Serializable -data class KeyPair( - val keyCurve: KeyCurve = KeyCurve(Curve.SECP256K1), - val privateKey: PrivateKey, - val publicKey: PublicKey -) - -/** - * Data class representing supported key curves for key generation. - */ -@Serializable -data class KeyCurve @JvmOverloads constructor( - val curve: Curve, - val index: Int? = 0 -) - -@Serializable -enum class Curve(val value: String) { - X25519("X25519"), - ED25519("Ed25519"), - SECP256K1("secp256k1") -} - -fun getKeyCurveByNameAndIndex(name: String, index: Int?): KeyCurve { - return when (name) { - Curve.X25519.value -> - KeyCurve(Curve.X25519) - - Curve.ED25519.value -> - KeyCurve(Curve.ED25519) - - Curve.SECP256K1.value -> - KeyCurve(Curve.SECP256K1, index) - - else -> - KeyCurve(Curve.SECP256K1, index) - } -} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/W3CCredential.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/W3CCredential.kt index 949fe8800..75cffcf51 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/W3CCredential.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/W3CCredential.kt @@ -94,6 +94,7 @@ data class W3CCredential @JvmOverloads constructor( get() = null override val availableClaims: Array get() = claims.map { it.key }.toTypedArray() + override val id: String get() = c.id override val issuer: String @@ -131,6 +132,10 @@ data class W3CCredential @JvmOverloads constructor( return properties.toMap() } + + override fun fromStorableCredential(): Credential { + return c + } } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt index 06a4153a1..d5e7714ac 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DefaultSecretsResolverImpl.kt @@ -35,9 +35,9 @@ class DefaultSecretsResolverImpl(val pluto: Pluto) : SecretsResolver { PrivateJWK( secretId, privateKey.getCurve(), - privateKey.getValue().base64UrlEncoded, - ).toString(), - ), + privateKey.getValue().base64UrlEncoded + ).toString() + ) ) } } diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt index 35b376da0..a221d82f7 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt @@ -19,7 +19,7 @@ class ApolloMock : Apollo { var createRandomSeedReturn: SeedWords = SeedWords(emptyArray(), Seed(ByteArray(0))) var createKeyPairReturn: KeyPair = Ed25519KeyPair( privateKey = Ed25519PrivateKey(ByteArray(0)), - publicKey = Ed25519PublicKey(ByteArray(0)), + publicKey = Ed25519PublicKey(ByteArray(0)) ) var compressedPublicKeyReturn: PublicKey = Secp256k1PublicKey(ByteArray(0)) var publicKeyReturn: PublicKey = Ed25519PublicKey(ByteArray(0)) diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt index f226c51e4..fc67be29c 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt @@ -18,7 +18,7 @@ class ApolloMock : Apollo { var createRandomSeedReturn: SeedWords = SeedWords(emptyArray(), Seed(ByteArray(0))) var createKeyPairReturn: KeyPair = Ed25519KeyPair( privateKey = Ed25519PrivateKey(ByteArray(0)), - publicKey = Ed25519PublicKey(ByteArray(0)), + publicKey = Ed25519PublicKey(ByteArray(0)) ) var compressedPublicKeyReturn = Ed25519PublicKey(ByteArray(0)) var publicKeyReturn: PublicKey = Ed25519PublicKey(ByteArray(0)) From 3166fb6c80f0ffc62bc7275316e6094c7bd7f202 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Thu, 21 Sep 2023 09:22:01 -0400 Subject: [PATCH 06/14] remove unnecessary testng import --- atala-prism-sdk/build.gradle.kts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/atala-prism-sdk/build.gradle.kts b/atala-prism-sdk/build.gradle.kts index 9aadf96de..8b858420e 100644 --- a/atala-prism-sdk/build.gradle.kts +++ b/atala-prism-sdk/build.gradle.kts @@ -133,6 +133,8 @@ kotlin { api("org.lighthousegames:logging:1.1.2") implementation("com.ionspin.kotlin:bignum:0.3.7") + +// implementation("org.bouncycastle:bcprov-jdk15on:1.68") } } val commonTest by getting { @@ -204,9 +206,6 @@ android { } } } -dependencies { - testImplementation("org.testng:testng:7.1.0") -} sqldelight { database("PrismPlutoDb") { From a7abb2037777002974165b750710f5305a8e8594 Mon Sep 17 00:00:00 2001 From: Cristian G <113917899+cristianIOHK@users.noreply.github.com> Date: Fri, 22 Sep 2023 12:03:19 -0400 Subject: [PATCH 07/14] Update atala-prism-sdk/build.gradle.kts Co-authored-by: Ahmed Moussa --- atala-prism-sdk/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atala-prism-sdk/build.gradle.kts b/atala-prism-sdk/build.gradle.kts index 8b858420e..37ad4b866 100644 --- a/atala-prism-sdk/build.gradle.kts +++ b/atala-prism-sdk/build.gradle.kts @@ -132,7 +132,7 @@ kotlin { api("org.lighthousegames:logging:1.1.2") - implementation("com.ionspin.kotlin:bignum:0.3.7") + implementation("com.ionspin.kotlin:bignum:0.3.8") // implementation("org.bouncycastle:bcprov-jdk15on:1.68") } From a5b62ebe5c3346efae2c25895f9b3f37f54b5ccb Mon Sep 17 00:00:00 2001 From: Cristian G Date: Fri, 22 Sep 2023 12:20:24 -0400 Subject: [PATCH 08/14] fix PR requested changes --- .../walletsdk/apollo/utils/JVMBigIntegerExt.kt | 3 ++- .../walletsdk/apollo/utils/Secp256k1PublicKey.kt | 6 +++--- .../ec/{_ECCoordinate.kt => KMMECCoordinate.kt} | 2 +- .../prism/walletsdk/apollo/utils/ec/KMMECPoint.kt | 15 +++++++++++++++ .../prism/walletsdk/apollo/utils/ec/_ECPoint.kt | 15 --------------- .../domain/models/keyManagement/PrivateKey.kt | 10 ++++++++++ .../domain/models/keyManagement/PublicKey.kt | 10 ++++++++++ 7 files changed, 41 insertions(+), 20 deletions(-) rename atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/{_ECCoordinate.kt => KMMECCoordinate.kt} (86%) create mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/KMMECPoint.kt delete mode 100644 atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt index 09181265a..53c6c2557 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/JVMBigIntegerExt.kt @@ -4,7 +4,8 @@ import com.ionspin.kotlin.bignum.integer.Sign import java.math.BigInteger fun BigInteger.toUnsignedByteArray(): ByteArray { - return toByteArray().dropWhile { it == 0.toByte() }.toByteArray() + val comparedValue = 0.toByte() + return toByteArray().dropWhile { it == comparedValue }.toByteArray() } fun BigInteger.toKotlinBigInteger(): com.ionspin.kotlin.bignum.integer.BigInteger { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt index c82061011..335b1459f 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt @@ -9,7 +9,7 @@ import io.iohk.atala.prism.apollo.utils.KMMECPoint import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey import io.iohk.atala.prism.apollo.utils.KMMEllipticCurve import io.iohk.atala.prism.walletsdk.apollo.config.ECConfig -import io.iohk.atala.prism.walletsdk.apollo.utils.ec._ECPoint +import io.iohk.atala.prism.walletsdk.apollo.utils.ec.KMMECPoint 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.CustomKey @@ -93,9 +93,9 @@ class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { } companion object { - fun computeCurvePoint(key: BCECPublicKey): _ECPoint { + fun computeCurvePoint(key: BCECPublicKey): io.iohk.atala.prism.walletsdk.apollo.utils.ec.KMMECPoint { val javaPoint = key.w - return _ECPoint(javaPoint.affineX.toKotlinBigInteger(), javaPoint.affineY.toKotlinBigInteger()) + return KMMECPoint(javaPoint.affineX.toKotlinBigInteger(), javaPoint.affineY.toKotlinBigInteger()) } fun secp256k1FromCompressed(compressed: ByteArray): Secp256k1PublicKey { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECCoordinate.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/KMMECCoordinate.kt similarity index 86% rename from atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECCoordinate.kt rename to atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/KMMECCoordinate.kt index 130834734..385f8a666 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECCoordinate.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/KMMECCoordinate.kt @@ -3,7 +3,7 @@ package io.iohk.atala.prism.walletsdk.apollo.utils.ec import com.ionspin.kotlin.bignum.integer.BigInteger import io.iohk.atala.prism.walletsdk.apollo.helpers.padStart -class _ECCoordinate(val coordinate: BigInteger) { +class KMMECCoordinate(val coordinate: BigInteger) { fun bytes(): ByteArray = coordinate.toByteArray().padStart(PRIVATE_KEY_BYTE_SIZE, 0) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/KMMECPoint.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/KMMECPoint.kt new file mode 100644 index 000000000..c0cb2a251 --- /dev/null +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/KMMECPoint.kt @@ -0,0 +1,15 @@ +package io.iohk.atala.prism.walletsdk.apollo.utils.ec + +import com.ionspin.kotlin.bignum.integer.BigInteger + +class KMMECPoint(val x: KMMECCoordinate, val y: KMMECCoordinate) { + constructor(x: String, y: String) : this( + KMMECCoordinate(BigInteger.parseString(x)), + KMMECCoordinate(BigInteger.parseString(y)) + ) + + constructor(x: BigInteger, y: BigInteger) : this( + KMMECCoordinate(x), + KMMECCoordinate(y) + ) +} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt deleted file mode 100644 index 1ade3f708..000000000 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/ec/_ECPoint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.iohk.atala.prism.walletsdk.apollo.utils.ec - -import com.ionspin.kotlin.bignum.integer.BigInteger - -class _ECPoint(val x: _ECCoordinate, val y: _ECCoordinate) { - constructor(x: String, y: String) : this( - _ECCoordinate(BigInteger.parseString(x)), - _ECCoordinate(BigInteger.parseString(y)) - ) - - constructor(x: BigInteger, y: BigInteger) : this( - _ECCoordinate(x), - _ECCoordinate(y) - ) -} diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt index d7f917afa..0714abecf 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PrivateKey.kt @@ -1,11 +1,21 @@ package io.iohk.atala.prism.walletsdk.domain.models.keyManagement +import io.iohk.atala.prism.walletsdk.domain.models.Curve + abstract class PrivateKey : Key() { fun getCurve(): String { return this.getProperty(CurveKey().property) } + fun getCurveInstance(): Curve? { + return try { + Curve.valueOf(this.getProperty(CurveKey().property)) + } catch (e: Exception) { + null + } + } + fun getIndex(): String { return this.getProperty(IndexKey().property) } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt index a26156440..3aacdc57a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/PublicKey.kt @@ -1,11 +1,21 @@ package io.iohk.atala.prism.walletsdk.domain.models.keyManagement +import io.iohk.atala.prism.walletsdk.domain.models.Curve + abstract class PublicKey : Key() { fun getCurve(): String { return this.getProperty(CurveKey().property) } + fun getCurveInstance(): Curve? { + return try { + Curve.valueOf(this.getProperty(CurveKey().property)) + } catch (e: Exception) { + null + } + } + fun getValue(): ByteArray { return this.raw } From 275024e9f270e578d3647b23c66169993419a91c Mon Sep 17 00:00:00 2001 From: Cristian G Date: Fri, 22 Sep 2023 14:42:42 -0400 Subject: [PATCH 09/14] rename _ECPoint to KMMECPoint --- .../atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt index 335b1459f..2b4b0597d 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt @@ -5,7 +5,6 @@ import com.ionspin.kotlin.bignum.integer.base63.toJavaBigInteger import io.iohk.atala.prism.apollo.ecdsa.ECDSAType import io.iohk.atala.prism.apollo.ecdsa.KMMECDSA import io.iohk.atala.prism.apollo.utils.ECPublicKeyInitializationException -import io.iohk.atala.prism.apollo.utils.KMMECPoint import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey import io.iohk.atala.prism.apollo.utils.KMMEllipticCurve import io.iohk.atala.prism.walletsdk.apollo.config.ECConfig @@ -93,7 +92,7 @@ class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { } companion object { - fun computeCurvePoint(key: BCECPublicKey): io.iohk.atala.prism.walletsdk.apollo.utils.ec.KMMECPoint { + fun computeCurvePoint(key: BCECPublicKey): KMMECPoint { val javaPoint = key.w return KMMECPoint(javaPoint.affineX.toKotlinBigInteger(), javaPoint.affineY.toKotlinBigInteger()) } From a23210b1ad72382062caf30aaaaebee4a0a6c6fe Mon Sep 17 00:00:00 2001 From: Cristian G Date: Tue, 26 Sep 2023 16:03:19 -0400 Subject: [PATCH 10/14] Further abstract cryptography and integrate apollo --- .../prism/walletsdk/apollo/ApolloImpl.kt | 309 +++++------------- .../walletsdk/apollo/utils/Ed25519KeyPair.kt | 15 +- .../apollo/utils/Ed25519PrivateKey.kt | 15 +- .../apollo/utils/Ed25519PublicKey.kt | 10 +- .../apollo/utils/Secp256k1KeyPair.kt | 21 +- .../apollo/utils/Secp256k1PrivateKey.kt | 13 +- .../apollo/utils/Secp256k1PublicKey.kt | 103 +----- .../walletsdk/apollo/utils/X25519KeyPair.kt | 15 +- .../apollo/utils/X25519PrivateKey.kt | 7 +- .../walletsdk/domain/buildingblocks/Apollo.kt | 95 +----- .../prism/walletsdk/domain/models/Errors.kt | 44 ++- build.gradle.kts | 4 +- settings.gradle.kts | 2 +- 13 files changed, 160 insertions(+), 493 deletions(-) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt index c82721855..2dad88de2 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt @@ -1,32 +1,27 @@ package io.iohk.atala.prism.walletsdk.apollo -import io.iohk.atala.prism.apollo.derivation.KeyDerivation -import io.iohk.atala.prism.apollo.derivation.MnemonicCode +import io.iohk.atala.prism.apollo.derivation.HDKey import io.iohk.atala.prism.apollo.derivation.MnemonicLengthException -import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey -import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey +import io.iohk.atala.prism.apollo.utils.Mnemonic +import io.iohk.atala.prism.walletsdk.apollo.helpers.BytesOps import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey -import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey -import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1KeyPair import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey -import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey import io.iohk.atala.prism.walletsdk.apollo.utils.X25519KeyPair import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PrivateKey -import io.iohk.atala.prism.walletsdk.apollo.utils.X25519PublicKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.models.ApolloError -import io.iohk.atala.prism.walletsdk.domain.models.CompressedPublicKey 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.SeedWords -import io.iohk.atala.prism.walletsdk.domain.models.Signature -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.CurveKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.DerivationPathKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.IndexKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey -import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters -import org.bouncycastle.crypto.params.X25519PrivateKeyParameters +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.RawKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.SeedKey +import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.TypeKey /** * Apollo defines the set of cryptographic operations that are used in the Atala PRISM. @@ -39,7 +34,7 @@ class ApolloImpl : Apollo { * @return An array of mnemonic phrases. */ override fun createRandomMnemonics(): Array { - return KeyDerivation.randomMnemonicCode().words.toTypedArray() + return Mnemonic.createRandomMnemonics() } /** @@ -52,13 +47,7 @@ class ApolloImpl : Apollo { */ @Throws(MnemonicLengthException::class) override fun createSeed(mnemonics: Array, passphrase: String): Seed { - val mnemonicCode = MnemonicCode(mnemonics.toList()) - return Seed( - value = KeyDerivation.binarySeed( - seed = mnemonicCode, - passphrase = passphrase - ) - ) + return Seed(Mnemonic.createSeed(mnemonics.joinToString(separator = " "), passphrase)) } /** @@ -69,231 +58,89 @@ class ApolloImpl : Apollo { */ override fun createRandomSeed(passphrase: String?): SeedWords { val mnemonics = createRandomMnemonics() - val mnemonicCode = MnemonicCode(mnemonics.toList()) return SeedWords( mnemonics, Seed( - value = KeyDerivation.binarySeed( - seed = mnemonicCode, + value = Mnemonic.createSeed( + mnemonics = mnemonics.joinToString(separator = " "), passphrase = passphrase ?: "" ) ) ) } - /** - * Creates a key pair (a private and public key) using a given seed and key curve. - * - * @param seed A seed object used to generate the key pair. - * @param curve The key curve to use for generating the key pair. - * @return A key pair object containing a private and public key. - */ - override fun createKeyPair(seed: Seed?, curve: KeyCurve): KeyPair { - return when (curve.curve) { - Curve.SECP256K1 -> { - Secp256k1KeyPair.generateKeyPair(seed, curve) - } - - Curve.ED25519 -> { - Ed25519KeyPair.generateKeyPair() - } - - Curve.X25519 -> { - X25519KeyPair.generateKeyPair() - } + override fun createPrivateKey(properties: Map): PrivateKey { + if (!properties.containsKey(TypeKey().property)) { + throw ApolloError.InvalidKeyType(TypeKey().property, KeyTypes.entries.map { it.type }.toTypedArray()) } - } - - /** - * Creates a key pair using a given seed and a specified private key. - * - * @param seed A seed object used to generate the key pair. - * @param privateKey The private key to use for generating the key pair. - * @return A [KeyPair] object containing a private and public key. - */ - override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair { - return when (privateKey.getCurve()) { - Curve.SECP256K1.value -> { - val key = privateKey as Secp256k1PrivateKey - val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(key.getValue()) - Secp256k1KeyPair( - privateKey = Secp256k1PrivateKey(kmmPrivateKey.getEncoded()), - publicKey = Secp256k1PublicKey(kmmPrivateKey.getPublicKey().getEncoded()) - ) - } - - Curve.ED25519.value -> { - val key = privateKey as Ed25519PrivateKey - val edPrivateKey = Ed25519PrivateKeyParameters(key.getValue(), 0) - val edPublicKey = edPrivateKey.generatePublicKey() - - Ed25519KeyPair( - privateKey = Ed25519PrivateKey(edPrivateKey.encoded), - publicKey = Ed25519PublicKey(edPublicKey.encoded) - ) - } - - Curve.X25519.value -> { - val key = privateKey as X25519PrivateKey - val xPrivateKey = X25519PrivateKeyParameters(key.getValue(), 0) - val xPublicKey = xPrivateKey.generatePublicKey() - - X25519KeyPair( - privateKey = X25519PrivateKey(xPrivateKey.encoded), - publicKey = X25519PublicKey(xPublicKey.encoded) - ) - } - - else -> { - throw ApolloError.InvalidKeyCurve() - } + if (!properties.containsKey(CurveKey().property)) { + throw ApolloError.InvalidKeyCurve(CurveKey().property, Curve.entries.map { it.value }.toTypedArray()) } - } - - /** - * Compresses a given public key into a shorter, more efficient form. - * - * @param publicKey The public key to compress. - * @return [CompressedPublicKey] - */ - override fun compressedPublicKey(publicKey: PublicKey): PublicKey { - val compressedRaw = (publicKey as Secp256k1PublicKey).getEncodedCompressed() - return Secp256k1PublicKey(compressedRaw) - } - - /** - * Decompresses a given compressed public key into its original form. - * - * @param compressedData The compressed public key data. - * @return [CompressedPublicKey] - */ - override fun compressedPublicKey(compressedData: ByteArray): PublicKey { - return Secp256k1PublicKey.secp256k1FromCompressed(compressedData) - } - /** - * Create a public key from byte coordinates. - * - * @param curve key curve. - * @param x x coordinate. - * @param y y coordinate. - * @return [PublicKey]. - */ - override fun publicKey(curve: KeyCurve, x: ByteArray, y: ByteArray): PublicKey { - return when (curve.curve) { - Curve.SECP256K1 -> { - val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromByteCoordinates(x, y) - Secp256k1PublicKey(kmmPublicKey.getEncoded()) - } - - else -> { - // Only SECP256K1 can be initialised by using byte Coordinates for EC Curve - throw ApolloError.InvalidKeyCurve() - } - } - } - - /** - * Create a public key from bytes. - * - * @param curve key curve. - * @param x bytes. - * @return [PublicKey]. - */ - override fun publicKey(curve: KeyCurve, x: ByteArray): PublicKey { - return when (curve.curve) { - Curve.SECP256K1 -> { - val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromBytes(x) - Secp256k1PublicKey(kmmPublicKey.getEncoded()) - } - - else -> { - // Other type of keys are initialised using a ByteArray, for now we just support SECP256K1 - TODO() - } - } - } - - /** - * Signs a message using a given private key, returning the signature. - * - * @param privateKey The private key to use for signing the message. - * @param message The message to sign, in binary data form. - * @return The signature of the message. - */ - override fun signMessage(privateKey: PrivateKey, message: ByteArray): Signature { - if (privateKey.isSignable()) { - return when (privateKey.getCurve()) { - Curve.SECP256K1.value -> { - val key = privateKey as Secp256k1PrivateKey - val signature = key.sign(message) - - Signature( - value = signature - ) - } - - Curve.ED25519.value -> { - val key = privateKey as Ed25519PrivateKey - val signature = key.sign(message) - - Signature( - value = signature - ) - } - - else -> { - TODO() + val keyType = properties[TypeKey().property] + val curve = properties[CurveKey().property] + + val keyData = properties[RawKey().property] + + when (keyType) { + KeyTypes.EC -> { + when (curve) { + Curve.ED25519.value -> { + keyData?.let { + if (it !is ByteArray) { + throw ApolloError.InvalidRawData("KeyData must be a ByteArray") + } + return Ed25519PrivateKey(it) + } + val keyPair = Ed25519KeyPair.generateKeyPair() + return keyPair.privateKey + } + + Curve.SECP256K1.value -> { + keyData?.let { + if (it !is ByteArray) { + throw Exception("KeyData must be a ByteArray") + } + return Secp256k1PrivateKey(it) + } + val index = properties[IndexKey().property] ?: 0 + if (index !is Int) { + throw ApolloError.InvalidIndex("Index must be an integer") + } + val derivationPath = + if (properties[DerivationPathKey().property] != null && + properties[DerivationPathKey().property] !is String + ) { + throw ApolloError.InvalidDerivationPath("Derivation path must be a string") + } else { + "m/$index'/0'/0'" + } + + val seed = properties[SeedKey().property] ?: throw Exception("Seed must provide a seed") + if (seed !is String) { + throw ApolloError.InvalidSeed("Seed must be a string") + } + + val seedByteArray = BytesOps.hexToBytes(seed) + + val hdKey = HDKey(seedByteArray, 0, 0) + val derivedHdKey = hdKey.derive(derivationPath) + return Secp256k1PrivateKey(derivedHdKey.getKMMSecp256k1PrivateKey().raw) + } } } - } else { - throw ApolloError.InvalidKeyCurve() - } - } - - /** - * Signs a message using a given private key, returning the signature. - * - * @param privateKey The private key to use for signing the message. - * @param message The message to sign, in string form. - * @return The signature of the message. - */ - override fun signMessage(privateKey: PrivateKey, message: String): Signature { - return signMessage(privateKey, message.encodeToByteArray()) - } - - /** - * Verifies the authenticity of a signature using the corresponding public key, challenge, and - * signature. This function returns a boolean value indicating whether the signature is valid or not. - * - * @param publicKey The public key associated with the signature. - * @param challenge The challenge used to generate the signature. - * @param signature The signature to verify. - * @return A boolean value indicating whether the signature is valid or not. - */ - override fun verifySignature( - publicKey: PublicKey, - challenge: ByteArray, - signature: Signature - ): Boolean { - if (publicKey.canVerify()) { - return when (publicKey.getCurve()) { - Curve.SECP256K1.value -> { - val key = publicKey as Secp256k1PublicKey - key.verify(challenge, signature.value) - } - - Curve.ED25519.value -> { - val key = publicKey as Ed25519PublicKey - key.verify(challenge, signature.value) - } - else -> { - TODO() + KeyTypes.Curve25519 -> { + keyData?.let { + if (it !is ByteArray) { + throw ApolloError.InvalidRawData("KeyData must be a ByteArray") + } + return X25519PrivateKey(it) } + val keyPair = X25519KeyPair.generateKeyPair() + return keyPair.privateKey } - } else { - throw ApolloError.InvalidKeyCurve() } + throw ApolloError.InvalidKeyType(TypeKey().property, KeyTypes.entries.map { it.type }.toTypedArray()) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt index 23b9cff12..dddab644a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519KeyPair.kt @@ -1,13 +1,9 @@ package io.iohk.atala.prism.walletsdk.apollo.utils +import io.iohk.atala.prism.apollo.utils.KMMEdKeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey -import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator -import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters -import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters -import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters -import java.security.SecureRandom class Ed25519KeyPair( override var privateKey: PrivateKey, @@ -16,12 +12,11 @@ class Ed25519KeyPair( companion object { fun generateKeyPair(): Ed25519KeyPair { - val generator = Ed25519KeyPairGenerator() - generator.init(Ed25519KeyGenerationParameters(SecureRandom())) - val pair = generator.generateKeyPair() + val pair = KMMEdKeyPair.generateKeyPair() + return Ed25519KeyPair( - privateKey = Ed25519PrivateKey(nativeValue = (pair.private as Ed25519PrivateKeyParameters).encoded), - publicKey = Ed25519PublicKey(nativeValue = (pair.public as Ed25519PublicKeyParameters).encoded) + privateKey = Ed25519PrivateKey(nativeValue = pair.privateKey.raw), + publicKey = Ed25519PublicKey(nativeValue = pair.publicKey.raw) ) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt index 56f576ee3..60b6e334c 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PrivateKey.kt @@ -1,13 +1,12 @@ package io.iohk.atala.prism.walletsdk.apollo.utils +import io.iohk.atala.prism.apollo.utils.KMMEdPrivateKey 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.KeyTypes 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.SignableKey -import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters -import org.bouncycastle.crypto.signers.Ed25519Signer class Ed25519PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { @@ -22,16 +21,12 @@ class Ed25519PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { } override fun publicKey(): PublicKey { - val private = Ed25519PrivateKeyParameters(raw, 0) - val public = private.generatePublicKey() - return Ed25519PublicKey(public.encoded) + val public = KMMEdPrivateKey(raw).publicKey() + return Ed25519PublicKey(public.raw) } override fun sign(message: ByteArray): ByteArray { - val privateParams = Ed25519PrivateKeyParameters(raw, 0) - val signer = Ed25519Signer() - signer.init(true, privateParams) - signer.update(message, 0, message.size) - return signer.generateSignature() + val private = KMMEdPrivateKey(raw) + return private.sign(message) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt index b856813a7..ca581a17a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Ed25519PublicKey.kt @@ -1,12 +1,11 @@ package io.iohk.atala.prism.walletsdk.apollo.utils +import io.iohk.atala.prism.apollo.utils.KMMEdPublicKey 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.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.VerifiableKey -import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters -import org.bouncycastle.crypto.signers.Ed25519Signer class Ed25519PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { override val type: KeyTypes = KeyTypes.EC @@ -20,10 +19,7 @@ class Ed25519PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { } override fun verify(message: ByteArray, signature: ByteArray): Boolean { - val key = Ed25519PublicKeyParameters(raw, 0) - val verifier = Ed25519Signer() - verifier.init(false, key) - verifier.update(message, 0, message.size) - return verifier.verifySignature(signature) + val public = KMMEdPublicKey(raw) + return public.verify(message, signature) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt index bc73c6a31..2d888d3b6 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt @@ -1,9 +1,7 @@ package io.iohk.atala.prism.walletsdk.apollo.utils -import io.iohk.atala.prism.apollo.derivation.DerivationPath -import io.iohk.atala.prism.apollo.derivation.KeyDerivation -import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey -import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey +import io.iohk.atala.prism.apollo.derivation.HDKey +import io.iohk.atala.prism.walletsdk.domain.models.ApolloError 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.KeyPair @@ -13,18 +11,15 @@ import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey class Secp256k1KeyPair(override var privateKey: PrivateKey, override var publicKey: PublicKey) : KeyPair() { companion object { fun generateKeyPair(seed: Seed?, curve: KeyCurve): Secp256k1KeyPair { - val derivationPath = DerivationPath.fromPath("m/${curve.index}'/0'/0'") + val path = "m/${curve.index}'/0'/0'" if (seed == null) { - // TODO: Custom error for null seed - throw Error("Seed cannot be null") + throw ApolloError.InvalidSeed("Seed cannot be null") } - val extendedKey = KeyDerivation.deriveKey(seed.value, derivationPath) - val kmmKeyPair = extendedKey.keyPair() - val privateKey = kmmKeyPair.privateKey as KMMECSecp256k1PrivateKey - val publicKey = kmmKeyPair.publicKey as KMMECSecp256k1PublicKey + val hdKey = HDKey(seed.value, 0, 0) + val derivedHdKey = hdKey.derive(path) return Secp256k1KeyPair( - privateKey = Secp256k1PrivateKey(privateKey.getEncoded()), - publicKey = Secp256k1PublicKey(publicKey.getEncoded()) + privateKey = Secp256k1PrivateKey(derivedHdKey.getKMMSecp256k1PrivateKey().raw), + publicKey = Secp256k1PublicKey(derivedHdKey.getKMMSecp256k1PrivateKey().getPublicKey().raw) ) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt index 32e6ee3f4..d70f9ea5f 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PrivateKey.kt @@ -1,9 +1,6 @@ package io.iohk.atala.prism.walletsdk.apollo.utils -import io.iohk.atala.prism.apollo.ecdsa.ECDSAType -import io.iohk.atala.prism.apollo.ecdsa.KMMECDSA import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey -import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey 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.KeyTypes @@ -23,15 +20,11 @@ class Secp256k1PrivateKey(nativeValue: ByteArray) : PrivateKey(), SignableKey { } override fun publicKey(): PublicKey { - return Secp256k1PublicKey(KMMECSecp256k1PublicKey.secp256k1FromBytes(raw).getEncoded()) + return Secp256k1PublicKey(KMMECSecp256k1PrivateKey.secp256k1FromByteArray(raw).getPublicKey().raw) } override fun sign(message: ByteArray): ByteArray { - val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromBytes(raw) - return KMMECDSA.sign( - type = ECDSAType.ECDSA_SHA256, - data = message, - privateKey = kmmPrivateKey - ) + val kmmPrivateKey = KMMECSecp256k1PrivateKey.secp256k1FromByteArray(raw) + return kmmPrivateKey.sign(data = message) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt index 2b4b0597d..f1992041b 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1PublicKey.kt @@ -1,29 +1,13 @@ package io.iohk.atala.prism.walletsdk.apollo.utils -import com.ionspin.kotlin.bignum.integer.BigInteger -import com.ionspin.kotlin.bignum.integer.base63.toJavaBigInteger -import io.iohk.atala.prism.apollo.ecdsa.ECDSAType -import io.iohk.atala.prism.apollo.ecdsa.KMMECDSA -import io.iohk.atala.prism.apollo.utils.ECPublicKeyInitializationException import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey -import io.iohk.atala.prism.apollo.utils.KMMEllipticCurve import io.iohk.atala.prism.walletsdk.apollo.config.ECConfig -import io.iohk.atala.prism.walletsdk.apollo.utils.ec.KMMECPoint 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.CustomKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.VerifiableKey -import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey -import org.bouncycastle.jce.ECNamedCurveTable -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.bouncycastle.jce.spec.ECNamedCurveSpec -import java.security.KeyFactory -import java.security.spec.ECParameterSpec -import java.security.spec.ECPoint -import java.security.spec.ECPublicKeySpec -import kotlin.experimental.and class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { override val type: KeyTypes = KeyTypes.EC @@ -43,92 +27,13 @@ class Secp256k1PublicKey(nativeValue: ByteArray) : PublicKey(), VerifiableKey { override fun verify(message: ByteArray, signature: ByteArray): Boolean { val kmmPublicKey = KMMECSecp256k1PublicKey.secp256k1FromBytes(raw) - return KMMECDSA.verify( - type = ECDSAType.ECDSA_SHA256, - data = message, - publicKey = kmmPublicKey, - signature = signature + return kmmPublicKey.verify( + signature = signature, + data = message ) } - fun isCompressed(): Boolean { - return ( - keySpecification.containsKey("compressed") && - keySpecification[CustomKey("compressed").property] == "true" - ) - } - fun getEncodedCompressed(): ByteArray { - if (isCompressed()) { - return raw - } - val size = io.iohk.atala.prism.apollo.utils.ECConfig.PRIVATE_KEY_BYTE_SIZE - val curvePoint = computeCurvePoint(bcecpublicKeyFromSecp256K1()) - val yArr = curvePoint.y.bytes() - val xArr = curvePoint.x.bytes() - val prefix = 2 + (yArr[yArr.size - 1] and 1) - val arr = ByteArray(1 + size) - arr[0] = prefix.toByte() - xArr.copyInto(arr, 1) - return arr - } - - private fun bcecpublicKeyFromSecp256K1(): BCECPublicKey { - val ecParameterSpec = ECNamedCurveTable.getParameterSpec(KMMEllipticCurve.SECP256k1.value) - val ecNamedCurveSpec: ECParameterSpec = ECNamedCurveSpec( - ecParameterSpec.name, - ecParameterSpec.curve, - ecParameterSpec.g, - ecParameterSpec.n - ) - - val bouncyCastlePoint = ecParameterSpec.curve.decodePoint(raw) - val point = - ECPoint(bouncyCastlePoint.xCoord.toBigInteger(), bouncyCastlePoint.yCoord.toBigInteger()) - val spec = ECPublicKeySpec(point, ecNamedCurveSpec) - val provider = BouncyCastleProvider() - val keyFactory = KeyFactory.getInstance("EC", provider) - return keyFactory.generatePublic(spec) as BCECPublicKey - } - - companion object { - fun computeCurvePoint(key: BCECPublicKey): KMMECPoint { - val javaPoint = key.w - return KMMECPoint(javaPoint.affineX.toKotlinBigInteger(), javaPoint.affineY.toKotlinBigInteger()) - } - - fun secp256k1FromCompressed(compressed: ByteArray): Secp256k1PublicKey { - require(compressed.size == ECConfig.PUBLIC_KEY_COMPRESSED_BYTE_SIZE) { - "Compressed byte array's expected length is ${ECConfig.PUBLIC_KEY_COMPRESSED_BYTE_SIZE}, but got ${compressed.size}" - } - val ecParameterSpec = ECNamedCurveTable.getParameterSpec(KMMEllipticCurve.SECP256k1.value) - val bouncyCastlePoint = ecParameterSpec.curve.decodePoint(compressed) - val point = - ECPoint(bouncyCastlePoint.xCoord.toBigInteger(), bouncyCastlePoint.yCoord.toBigInteger()) - return secp256k1FromBigIntegerCoordinates( - point.affineX.toKotlinBigInteger(), - point.affineY.toKotlinBigInteger() - ) - } - - fun secp256k1FromBigIntegerCoordinates(x: BigInteger, y: BigInteger): Secp256k1PublicKey { - val ecPoint = ECPoint(x.toJavaBigInteger(), y.toJavaBigInteger()) - if (!KMMECSecp256k1PublicKey.isPointOnSecp256k1Curve(KMMECPoint(x, y))) { - throw ECPublicKeyInitializationException("ECPoint corresponding to a public key doesn't belong to Secp256k1 curve") - } - val ecParameterSpec = ECNamedCurveTable.getParameterSpec(KMMEllipticCurve.SECP256k1.value) - val ecNamedCurveSpec: ECParameterSpec = ECNamedCurveSpec( - ecParameterSpec.name, - ecParameterSpec.curve, - ecParameterSpec.g, - ecParameterSpec.n - ) - val spec = ECPublicKeySpec(ecPoint, ecNamedCurveSpec) - val provider = BouncyCastleProvider() - val keyFactory = KeyFactory.getInstance("EC", provider) - val publicKey = keyFactory.generatePublic(spec) as BCECPublicKey - - return Secp256k1PublicKey(publicKey.encoded) - } + return KMMECSecp256k1PublicKey(raw).getCompressed() } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt index 079677e84..92f50d572 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519KeyPair.kt @@ -1,24 +1,19 @@ package io.iohk.atala.prism.walletsdk.apollo.utils +import io.iohk.atala.prism.apollo.utils.KMMX25519KeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey -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 class X25519KeyPair(override var privateKey: PrivateKey, override var publicKey: PublicKey) : KeyPair() { companion object { fun generateKeyPair(): X25519KeyPair { - val generator = X25519KeyPairGenerator() - generator.init(X25519KeyGenerationParameters(SecureRandom())) - val keyPair = generator.generateKeyPair() + val pair = KMMX25519KeyPair.generateKeyPair() + return X25519KeyPair( - privateKey = X25519PrivateKey((keyPair.private as X25519PrivateKeyParameters).encoded), - publicKey = X25519PublicKey((keyPair.public as X25519PublicKeyParameters).encoded) + privateKey = X25519PrivateKey(pair.privateKey.raw), + publicKey = X25519PublicKey(pair.publicKey.raw) ) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt index 916ab94ff..f5adce3bc 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/X25519PrivateKey.kt @@ -1,11 +1,11 @@ package io.iohk.atala.prism.walletsdk.apollo.utils +import io.iohk.atala.prism.apollo.utils.KMMX25519PrivateKey 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.KeyTypes import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey -import org.bouncycastle.crypto.params.X25519PrivateKeyParameters class X25519PrivateKey(nativeValue: ByteArray) : PrivateKey() { override val type: KeyTypes = KeyTypes.EC @@ -19,8 +19,7 @@ class X25519PrivateKey(nativeValue: ByteArray) : PrivateKey() { } override fun publicKey(): PublicKey { - val xPrivateKey = X25519PrivateKeyParameters(raw, 0) - val xPublicKey = xPrivateKey.generatePublicKey() - return X25519PublicKey(xPublicKey.encoded) + val private = KMMX25519PrivateKey(raw) + return X25519PublicKey(private.publicKey().raw) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt index 073e3de27..c24c011bc 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/buildingblocks/Apollo.kt @@ -1,14 +1,9 @@ package io.iohk.atala.prism.walletsdk.domain.buildingblocks import io.iohk.atala.prism.apollo.derivation.MnemonicLengthException -import io.iohk.atala.prism.walletsdk.domain.models.CompressedPublicKey -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.SeedWords -import io.iohk.atala.prism.walletsdk.domain.models.Signature -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import kotlin.jvm.Throws /** @@ -43,93 +38,5 @@ interface Apollo { */ fun createRandomSeed(passphrase: String? = ""): SeedWords - /** - * Creates a key pair (a private and public key) using a given seed and key curve. - * - * @param seed A seed object used to generate the key pair. - * @param curve The key curve to use for generating the key pair. - * @return A key pair object containing a private and public key. - */ - // @JsName("createKeyPairFromKeyCurve") - fun createKeyPair(seed: Seed? = null, curve: KeyCurve): KeyPair - - /** - * Creates a key pair using a given seed and a specified private key. - * - * @param seed A seed object used to generate the key pair. - * @param privateKey The private key to use for generating the key pair. - * @return A [KeyPair] object containing a private and public key. - */ - // @JsName("createKeyPairFromPrivateKey") - fun createKeyPair(seed: Seed? = null, privateKey: PrivateKey): KeyPair - - /** - * Compresses a given public key into a shorter, more efficient form. - * - * @param publicKey The public key to compress. - * @return [CompressedPublicKey]. - */ - // @JsName("compressedPublicKeyFromPublicKey") - fun compressedPublicKey(publicKey: PublicKey): PublicKey - - /** - * Decompresses a given compressed public key into its original form. - * - * @param compressedData The compressed public key data. - * @return [CompressedPublicKey]. - */ - // @JsName("compressedPublicKeyFromCompressedData") - fun compressedPublicKey(compressedData: ByteArray): PublicKey - - /** - * Create a public key from byte coordinates. - * - * @param curve key curve. - * @param x x coordinate. - * @param y y coordinate. - * @return [PublicKey]. - */ - // @JsName("publicKeyFromPoints") - fun publicKey(curve: KeyCurve, x: ByteArray, y: ByteArray): PublicKey - - /** - * Create a public key from bytes. - * - * @param curve key curve. - * @param x bytes. - * @return [PublicKey]. - */ - // @JsName("publicKeyFromPoint") - fun publicKey(curve: KeyCurve, x: ByteArray): PublicKey - - /** - * Signs a message using a given private key, returning the signature. - * - * @param privateKey The private key to use for signing the message. - * @param message The message to sign, in binary data form. - * @return The signature of the message. - */ - // @JsName("signByteArrayMessage") - fun signMessage(privateKey: PrivateKey, message: ByteArray): Signature - - /** - * Signs a message using a given private key, returning the signature. - * - * @param privateKey The private key to use for signing the message. - * @param message The message to sign, in string form. - * @return The signature of the message. - */ - // @JsName("signStringMessage") - fun signMessage(privateKey: PrivateKey, message: String): Signature - - /** - * Verifies the authenticity of a signature using the corresponding public key, challenge, and - * signature. This function returns a boolean value indicating whether the signature is valid or not. - * - * @param publicKey The public key associated with the signature. - * @param challenge The challenge used to generate the signature. - * @param signature The signature to verify. - * @return A boolean value indicating whether the signature is valid or not. - */ - fun verifySignature(publicKey: PublicKey, challenge: ByteArray, signature: Signature): Boolean + fun createPrivateKey(properties: Map): PrivateKey } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Errors.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Errors.kt index 538127bd7..172d4528a 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Errors.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/Errors.kt @@ -133,12 +133,52 @@ sealed class ApolloError @JvmOverloads constructor(message: String? = null, caus get() = "JWK is not in a valid format" } - class InvalidKeyCurve : ApolloError() { + class InvalidKeyCurve(val invalidCurve: String, val validCurves: Array) : ApolloError() { override val code: Int get() = 14 override val message: String - get() = "Only SECP256K1 can be initialised by using byte Coordinates for EC Curve" + get() = "Invalid key curve $invalidCurve. Valid options are: ${validCurves.joinToString(", ")}" + } + + class InvalidKeyType(val invalidType: String, val validTypes: Array) : ApolloError() { + + override val code: Int + get() = 15 + override val message: String + get() = "Invalid key type $invalidType. Valid options are: ${validTypes.joinToString(", ")}" + } + + class InvalidIndex(val invalidMessage: String) : ApolloError() { + + override val code: Int + get() = 16 + override val message: String + get() = invalidMessage + } + + class InvalidDerivationPath(val invalidMessage: String) : ApolloError() { + + override val code: Int + get() = 17 + override val message: String + get() = invalidMessage + } + + class InvalidSeed(val invalidMessage: String) : ApolloError() { + + override val code: Int + get() = 18 + override val message: String + get() = invalidMessage + } + + class InvalidRawData(val invalidMessage: String) : ApolloError() { + + override val code: Int + get() = 19 + override val message: String + get() = invalidMessage } } diff --git a/build.gradle.kts b/build.gradle.kts index ccf1ab470..5142a9f5e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,8 +13,8 @@ plugins { buildscript { repositories { - mavenCentral() mavenLocal() + mavenCentral() google() gradlePluginPortal() } @@ -38,8 +38,8 @@ allprojects { this.group = "io.iohk.atala.prism.walletsdk" repositories { - mavenCentral() mavenLocal() + mavenCentral() google() maven("https://plugins.gradle.org/m2/") // Needed for Kotlin coroutines that support new memory management mode diff --git a/settings.gradle.kts b/settings.gradle.kts index 6a9d7030d..46e22e19e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,9 +10,9 @@ pluginManagement { buildscript { repositories { + mavenLocal() gradlePluginPortal() mavenCentral() - mavenLocal() google() maven("https://plugins.gradle.org/m2/") // Needed for Kotlin coroutines that support new memory management mode From 46ee9b0c1826df689802013588b16b0adee45513 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Fri, 29 Sep 2023 14:11:14 -0400 Subject: [PATCH 11/14] feat: integrate apollo and fix unit tests --- atala-prism-sdk/build.gradle.kts | 6 +- .../prism/walletsdk/apollo/ApolloImpl.kt | 4 +- .../apollo/utils/Secp256k1KeyPair.kt | 6 +- .../prism/walletsdk/castor/CastorImpl.kt | 19 ++- .../castor/did/prismdid/PrismDIDPublicKey.kt | 3 +- .../domain/models/keyManagement/Key.kt | 2 +- .../resolvers/DIDCommSecretsResolver.kt | 3 +- .../prism/walletsdk/prismagent/PrismAgent.kt | 45 +++++-- .../prism/walletsdk/apollo/ApolloTests.kt | 114 ++++++------------ .../prism/walletsdk/castor/ApolloMock.kt | 35 +----- .../castor/PrismDIDPublicKeyTests.kt | 20 +-- .../prism/walletsdk/prismagent/ApolloMock.kt | 46 +------ .../walletsdk/prismagent/PrismAgentTests.kt | 20 ++- gradle.properties | 2 +- 14 files changed, 125 insertions(+), 200 deletions(-) diff --git a/atala-prism-sdk/build.gradle.kts b/atala-prism-sdk/build.gradle.kts index 37ad4b866..48a175603 100644 --- a/atala-prism-sdk/build.gradle.kts +++ b/atala-prism-sdk/build.gradle.kts @@ -111,9 +111,8 @@ kotlin { implementation("io.iohk.atala.prism.didcomm:didpeer:$didpeerVersion") - implementation("io.iohk.atala.prism.apollo:base64:$apolloVersion") implementation("io.iohk.atala.prism.apollo:base-asymmetric-encryption:$apolloVersion") - implementation("io.iohk.atala.prism.apollo:ecdsa:$apolloVersion") + implementation("io.iohk.atala.prism.apollo:base64:$apolloVersion") implementation("io.iohk.atala.prism.apollo:hashing:$apolloVersion") implementation("io.iohk.atala.prism.apollo:uuid:$apolloVersion") implementation("io.iohk.atala.prism.apollo:multibase:$apolloVersion") @@ -133,8 +132,6 @@ kotlin { api("org.lighthousegames:logging:1.1.2") implementation("com.ionspin.kotlin:bignum:0.3.8") - -// implementation("org.bouncycastle:bcprov-jdk15on:1.68") } } val commonTest by getting { @@ -142,6 +139,7 @@ kotlin { implementation(kotlin("test")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") implementation("io.ktor:ktor-client-mock:2.3.4") + implementation("junit:junit:4.13.2") } } val jvmMain by getting { diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt index 2dad88de2..3c2bab968 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt @@ -47,7 +47,7 @@ class ApolloImpl : Apollo { */ @Throws(MnemonicLengthException::class) override fun createSeed(mnemonics: Array, passphrase: String): Seed { - return Seed(Mnemonic.createSeed(mnemonics.joinToString(separator = " "), passphrase)) + return Seed(Mnemonic.createSeed(mnemonics, passphrase)) } /** @@ -62,7 +62,7 @@ class ApolloImpl : Apollo { mnemonics, Seed( value = Mnemonic.createSeed( - mnemonics = mnemonics.joinToString(separator = " "), + mnemonics = mnemonics, passphrase = passphrase ?: "" ) ) diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt index 2d888d3b6..b83fc73c8 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/utils/Secp256k1KeyPair.kt @@ -1,7 +1,6 @@ package io.iohk.atala.prism.walletsdk.apollo.utils import io.iohk.atala.prism.apollo.derivation.HDKey -import io.iohk.atala.prism.walletsdk.domain.models.ApolloError 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.KeyPair @@ -10,11 +9,8 @@ import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey class Secp256k1KeyPair(override var privateKey: PrivateKey, override var publicKey: PublicKey) : KeyPair() { companion object { - fun generateKeyPair(seed: Seed?, curve: KeyCurve): Secp256k1KeyPair { + fun generateKeyPair(seed: Seed, curve: KeyCurve): Secp256k1KeyPair { val path = "m/${curve.index}'/0'/0'" - if (seed == null) { - throw ApolloError.InvalidSeed("Seed cannot be null") - } val hdKey = HDKey(seed.value, 0, 0) val derivedHdKey = hdKey.derive(path) return Secp256k1KeyPair( diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt index ab808b43e..989c66ec3 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/CastorImpl.kt @@ -1,15 +1,19 @@ package io.iohk.atala.prism.walletsdk.castor +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey import io.iohk.atala.prism.walletsdk.castor.resolvers.LongFormPrismDIDResolver import io.iohk.atala.prism.walletsdk.castor.resolvers.PeerDIDResolver import io.iohk.atala.prism.walletsdk.castor.shared.CastorShared import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Castor import io.iohk.atala.prism.walletsdk.domain.models.CastorError +import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument import io.iohk.atala.prism.walletsdk.domain.models.DIDResolver -import io.iohk.atala.prism.walletsdk.domain.models.Signature import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey import io.iohk.atala.prism.walletsdk.logger.LogComponent @@ -127,9 +131,16 @@ class CastorImpl(apollo: Apollo, private val logger: PrismLogger = PrismLoggerIm } for (keyPair in keyPairs) { - val verified = apollo.verifySignature(keyPair, challenge, Signature(signature)) - if (verified) { - return true + when (keyPair.getCurve()) { + Curve.SECP256K1.value -> { + val secp = keyPair as Secp256k1KeyPair + return (secp.publicKey as Secp256k1PublicKey).verify(challenge, signature) + } + + Curve.ED25519.value -> { + val ed = keyPair as Ed25519KeyPair + return (ed.publicKey as Ed25519PublicKey).verify(challenge, signature) + } } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt index 805af3a72..bc6c4ec92 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/castor/did/prismdid/PrismDIDPublicKey.kt @@ -1,5 +1,6 @@ package io.iohk.atala.prism.walletsdk.castor.did.prismdid +import io.iohk.atala.prism.apollo.secp256k1.Secp256k1Lib import io.iohk.atala.prism.protos.CompressedECKeyData import io.iohk.atala.prism.protos.KeyUsage import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey @@ -40,7 +41,7 @@ class PrismDIDPublicKey { } fun toProto(): io.iohk.atala.prism.protos.PublicKey { - val compressedPublicKey: Secp256k1PublicKey = apollo.compressedPublicKey(keyData) as Secp256k1PublicKey + val compressedPublicKey = Secp256k1PublicKey(Secp256k1Lib().compressPublicKey(keyData.getValue())) return io.iohk.atala.prism.protos.PublicKey( id = id, usage = usage.toProto(), diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt index 96ccd9de5..dc57c47ba 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt @@ -82,7 +82,7 @@ fun getKeyCurveByNameAndIndex(name: String, index: Int?): KeyCurve { } else -> { - throw ApolloError.InvalidKeyCurve() + throw ApolloError.InvalidKeyCurve(name, Curve.entries.map { it.value }.toTypedArray()) } } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt index f8f486491..fa3f9da07 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/mercury/resolvers/DIDCommSecretsResolver.kt @@ -28,12 +28,11 @@ class DIDCommSecretsResolver(val pluto: Pluto, val apollo: Apollo) : SecretResol pluto.getDIDPrivateKeyByID(kid) .firstOrNull() ?.let { privateKey -> - val keyPair = apollo.createKeyPair(privateKey = privateKey) val octetJwk = OctetPrivateKey( crv = privateKey.getCurve(), kty = OKP, d = privateKey.getValue().base64UrlEncoded, - x = keyPair.publicKey.getValue().base64UrlEncoded + x = privateKey.publicKey().getValue().base64UrlEncoded ) Optional.of( Secret( diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt index 24da30672..334481d25 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgent.kt @@ -3,6 +3,11 @@ package io.iohk.atala.prism.walletsdk.prismagent /* ktlint-disable import-ordering */ import io.iohk.atala.prism.apollo.base64.base64UrlDecoded import io.iohk.atala.prism.apollo.base64.base64UrlEncoded +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519KeyPair import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Castor import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Mercury @@ -10,6 +15,7 @@ import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pluto import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pollux import io.iohk.atala.prism.walletsdk.domain.models.Api import io.iohk.atala.prism.walletsdk.domain.models.ApiImpl +import io.iohk.atala.prism.walletsdk.domain.models.ApolloError import io.iohk.atala.prism.walletsdk.domain.models.AttachmentBase64 import io.iohk.atala.prism.walletsdk.domain.models.AttachmentDescriptor import io.iohk.atala.prism.walletsdk.domain.models.AttachmentJsonData @@ -278,7 +284,7 @@ class PrismAgent { services: Array = emptyArray() ): DID { val index = keyPathIndex ?: (pluto.getPrismLastKeyPathIndex().first() + 1) - val keyPair = apollo.createKeyPair(seed = seed, curve = KeyCurve(Curve.SECP256K1, index)) + val keyPair = Secp256k1KeyPair.generateKeyPair(seed, KeyCurve(Curve.SECP256K1, index)) val did = castor.createPrismDID(masterPublicKey = keyPair.publicKey, services = services) registerPrismDID(did, index, alias, keyPair.privateKey) return did @@ -319,10 +325,8 @@ class PrismAgent { services: Array = emptyArray(), updateMediator: Boolean ): DID { - val keyAgreementKeyPair = - apollo.createKeyPair(seed = seed, curve = KeyCurve(Curve.X25519)) - val authenticationKeyPair = - apollo.createKeyPair(seed = seed, curve = KeyCurve(Curve.ED25519)) + val keyAgreementKeyPair = X25519KeyPair.generateKeyPair() + val authenticationKeyPair = Ed25519KeyPair.generateKeyPair() var tmpServices = services if (updateMediator) { @@ -501,7 +505,26 @@ class PrismAgent { val privateKey = pluto.getDIDPrivateKeysByDID(did).first().first() ?: throw PrismAgentError.CannotFindDIDPrivateKey(did.toString()) - return apollo.signMessage(privateKey, message) + var returnByteArray: ByteArray + when (privateKey.getCurve()) { + Curve.ED25519.value -> { + val ed = privateKey as Ed25519PrivateKey + returnByteArray = ed.sign(message) + } + + Curve.SECP256K1.value -> { + val secp = privateKey as Secp256k1PrivateKey + returnByteArray = secp.sign(message) + } + + else -> { + throw ApolloError.InvalidKeyCurve( + privateKey.getCurve(), + arrayOf(Curve.SECP256K1.value, Curve.ED25519.value) + ) + } + } + return Signature(returnByteArray) } /** @@ -520,8 +543,7 @@ class PrismAgent { throw PolluxError.InvalidPrismDID() } val privateKeyKeyPath = pluto.getPrismDIDKeyPathIndex(did).first() - val privateKey = - apollo.createKeyPair(seed, KeyCurve(Curve.SECP256K1, privateKeyKeyPath)).privateKey + val keyPair = Secp256k1KeyPair.generateKeyPair(seed, KeyCurve(Curve.SECP256K1, privateKeyKeyPath)) val offerDataString = offer.attachments.mapNotNull { when (it.data) { is AttachmentJsonData -> it.data.data @@ -529,7 +551,7 @@ class PrismAgent { } }.first() val offerJsonObject = Json.parseToJsonElement(offerDataString).jsonObject - val jwtString = pollux.createRequestCredentialJWT(did, privateKey, offerJsonObject) + val jwtString = pollux.createRequestCredentialJWT(did, keyPair.privateKey, offerJsonObject) val attachmentDescriptor = AttachmentDescriptor( mediaType = JWT_MEDIA_TYPE, @@ -784,8 +806,7 @@ class PrismAgent { } val privateKeyKeyPath = pluto.getPrismDIDKeyPathIndex(subjectDID).first() - val privateKey = - apollo.createKeyPair(seed, KeyCurve(Curve.SECP256K1, privateKeyKeyPath)).privateKey + val keyPair = Secp256k1KeyPair.generateKeyPair(seed, KeyCurve(Curve.SECP256K1, privateKeyKeyPath)) val requestData = request.attachments.mapNotNull { when (it.data) { is AttachmentJsonData -> it.data.data @@ -795,7 +816,7 @@ class PrismAgent { val requestJsonObject = Json.parseToJsonElement(requestData).jsonObject val jwtString = pollux.createVerifiablePresentationJWT( subjectDID, - privateKey, + keyPair.privateKey, credential, requestJsonObject ) diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt index 9ab0a23ef..b54b9b493 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloTests.kt @@ -1,19 +1,25 @@ package io.iohk.atala.prism.walletsdk.apollo import io.iohk.atala.prism.apollo.base64.base64UrlEncoded -import io.iohk.atala.prism.apollo.derivation.MnemonicChecksumException -import io.iohk.atala.prism.apollo.derivation.MnemonicLengthException import io.iohk.atala.prism.apollo.utils.ECConfig +import io.iohk.atala.prism.apollo.utils.Mnemonic import io.iohk.atala.prism.walletsdk.apollo.derivation.bip39Vectors import io.iohk.atala.prism.walletsdk.apollo.helpers.BytesOps +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.X25519KeyPair 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.KeyPair -import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json -import kotlin.test.BeforeTest -import kotlin.test.Test +import org.junit.Before +import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertFalse @@ -26,10 +32,9 @@ class ApolloTests { val testData = byteArrayOf(-107, 101, 68, 118, 27, 74, 29, 50, -32, 72, 47, -127, -49, 3, -8, -55, -63, -66, 46, 125) - @BeforeTest + @Before fun before() { apollo = ApolloImpl() - keyPair = apollo.createKeyPair(apollo.createRandomSeed().seed, KeyCurve(Curve.SECP256K1)) } @Test @@ -51,7 +56,7 @@ class ApolloTests { @Test fun testComputeRightBinarySeed() { - val password = "TREZOR" + val password = "mnemonicTREZOR" val vectors = Json.decodeFromString>>(bip39Vectors) for (v in vectors) { val (_, mnemonicPhrase, binarySeedHex, _) = v @@ -62,48 +67,35 @@ class ApolloTests { } } - @Test - fun testFailWhenChecksumIsIncorrect() { - val mnemonicCode = Array(24) { "abandon" } - assertFailsWith { - apollo.createSeed(mnemonicCode, "") - } - } - @Test fun testFailWhenInvalidWordIsUsed() { val mnemonicCode = arrayOf("hocus", "pocus", "mnemo", "codus") + Array(24) { "abandon" } - assertFailsWith { + assertFailsWith { apollo.createSeed(mnemonicCode, "") } } - @Test - fun testFailWhenWrongLength() { - assertFailsWith { - apollo.createSeed(arrayOf("abandon"), "") - } - } - @Test fun testKeyPairGeneration() { + keyPair = Secp256k1KeyPair.generateKeyPair(Seed(Mnemonic.createRandomSeed()), KeyCurve(Curve.SECP256K1)) assertEquals(keyPair.publicKey.raw.size, ECConfig.PUBLIC_KEY_BYTE_SIZE) assertEquals(keyPair.privateKey.raw.size, ECConfig.PRIVATE_KEY_BYTE_SIZE) } @Test fun testSignAndVerifyTest() { - val text = "The quick brown fox jumps over the lazy dog" - val signature = apollo.signMessage(keyPair.privateKey, text) + val message = "The quick brown fox jumps over the lazy dog" + keyPair = Secp256k1KeyPair.generateKeyPair(Seed(Mnemonic.createRandomSeed()), KeyCurve(Curve.SECP256K1)) + val signature = (keyPair.privateKey as Secp256k1PrivateKey).sign(message.toByteArray()) - assertEquals(signature.value.size <= ECConfig.SIGNATURE_MAX_BYTE_SIZE, true) + assertEquals(signature.size <= ECConfig.SIGNATURE_MAX_BYTE_SIZE, true) - assertTrue(apollo.verifySignature(keyPair.publicKey, text.encodeToByteArray(), signature)) + assertTrue((keyPair.publicKey as Secp256k1PublicKey).verify(message.encodeToByteArray(), signature)) } @Test fun testCreateKeyPair_whenNoSeedAndKeyCurveEd25519_thenPrivateKeyLengthIsCorrect() { - val keyPair = apollo.createKeyPair(curve = KeyCurve(Curve.ED25519)) + val keyPair = Ed25519KeyPair.generateKeyPair() val privateKey = keyPair.privateKey val publicKey = keyPair.publicKey assertEquals(32, privateKey.raw.size) @@ -112,39 +104,13 @@ class ApolloTests { @Test fun testCreateKeyPair_whenNoSeedAndKeyCurveX25519_thenPrivateKeyLengthIsCorrect() { - val keyPair = apollo.createKeyPair(curve = KeyCurve(Curve.X25519)) + val keyPair = X25519KeyPair.generateKeyPair() val privateKey = keyPair.privateKey val publicKey = keyPair.publicKey assertEquals(32, privateKey.raw.size) assertEquals(32, publicKey.raw.size) } - @Test - fun testCreateKeyPair_whenSecp256k1FromPrivateKey_thenPublicKeyCorrect() { - val seed = apollo.createRandomSeed() - val keyPair = apollo.createKeyPair(seed = seed.seed, curve = KeyCurve(Curve.SECP256K1)) - val expectedPrivateKey = keyPair.privateKey - val expectedPublicKey = keyPair.publicKey - - val resultKeyPair = apollo.createKeyPair(privateKey = keyPair.privateKey) - - assertEquals(expectedPublicKey, resultKeyPair.publicKey) - assertEquals(expectedPrivateKey, resultKeyPair.privateKey) - } - - @Test - fun testCreateKeyPair_whenEd25519FromPrivateKey_thenPublicKeyCorrect() { - val seed = apollo.createRandomSeed() - val keyPair = apollo.createKeyPair(seed = seed.seed, curve = KeyCurve(Curve.ED25519)) - val expectedPrivateKey = keyPair.privateKey - val expectedPublicKey = keyPair.publicKey - - val resultKeyPair = apollo.createKeyPair(privateKey = keyPair.privateKey) - - assertEquals(expectedPublicKey, resultKeyPair.publicKey) - assertEquals(expectedPrivateKey, resultKeyPair.privateKey) - } - @Test fun testCreateKeyPair_whenUsingSeedAndMnemonics_thenKeyPairIsCorrect() { val mnemonics = arrayOf( @@ -173,43 +139,33 @@ class ApolloTests { "return", "height" ) - val seed = apollo.createSeed(mnemonics, "") + val seed = Seed(Mnemonic.createSeed(mnemonics = mnemonics, passphrase = "mnemonic")) val expectedPrivateKeyBase64Url = "xURclKhT6as1Tb9vg4AJRRLPAMWb9dYTTthDvXEKjMc" - val keyPair = apollo.createKeyPair(seed, KeyCurve(Curve.SECP256K1)) + assertEquals( + "7bcb8d37b2d11f998451cc5aec58710c081618b87c3fde1610e0f48d475a276992535a34daef8bcdaa39d1e955df65ef613d2ec7d8d6b815440a9140cf67242b", + BytesOps.bytesToHex(seed.value) + ) + val keyPair = Secp256k1KeyPair.generateKeyPair(seed, KeyCurve(Curve.SECP256K1)) assertEquals(expectedPrivateKeyBase64Url, keyPair.privateKey.raw.base64UrlEncoded) } - @Test - fun testCreateKeyPair_whenX25519FromPrivateKey_thenPublicKeyCorrect() { - val seed = apollo.createRandomSeed() - val keyPair = apollo.createKeyPair(seed = seed.seed, curve = KeyCurve(Curve.X25519)) - val expectedPrivateKey = keyPair.privateKey - val expectedPublicKey = keyPair.publicKey - - val resultKeyPair = apollo.createKeyPair(privateKey = keyPair.privateKey) - - assertEquals(expectedPublicKey, resultKeyPair.publicKey) - assertEquals(expectedPrivateKey, resultKeyPair.privateKey) - } - @Test fun testSignAndVerify_whenSignatureIsCorrect_thenVerifiedCorrectly() { - val keyPair = apollo.createKeyPair(curve = KeyCurve(Curve.ED25519)) + val keyPair = Ed25519KeyPair.generateKeyPair() val message = "This is a test message" - val signature = apollo.signMessage(keyPair.privateKey, message) + val signature = (keyPair.privateKey as Ed25519PrivateKey).sign(message.toByteArray()) - assertTrue(apollo.verifySignature(keyPair.publicKey, message.toByteArray(), signature)) + assertTrue((keyPair.publicKey as Ed25519PublicKey).verify(message.toByteArray(), signature)) } @Test fun testSignAndVerify_whenSignatureIsIncorrect_thenVerifyFails() { - val keyPair = apollo.createKeyPair(curve = KeyCurve(Curve.ED25519)) + val keyPair = Ed25519KeyPair.generateKeyPair() val message = "This is a test message" - val signature = apollo.signMessage(keyPair.privateKey, message) - val modifiedSignature = signature.value - modifiedSignature[0] = 1 - assertFalse(apollo.verifySignature(keyPair.publicKey, message.toByteArray(), signature)) + var signature = (keyPair.privateKey as Ed25519PrivateKey).sign(message.toByteArray()) + signature[0] = 1 + assertFalse((keyPair.publicKey as Ed25519PublicKey).verify(message.toByteArray(), signature)) } } diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt index a221d82f7..eb5d0eb66 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/ApolloMock.kt @@ -5,7 +5,6 @@ import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PublicKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo -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.SeedWords import io.iohk.atala.prism.walletsdk.domain.models.Signature @@ -39,37 +38,7 @@ class ApolloMock : Apollo { return createRandomSeedReturn } - override fun createKeyPair(seed: Seed?, curve: KeyCurve): KeyPair { - return createKeyPairReturn + override fun createPrivateKey(properties: Map): PrivateKey { + TODO("Not yet implemented") } - - override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair { - return createKeyPairReturn - } - - override fun compressedPublicKey(publicKey: PublicKey): PublicKey { - return compressedPublicKeyReturn - } - - override fun compressedPublicKey(compressedData: ByteArray): PublicKey = - compressedPublicKeyDataReturn - - override fun publicKey(curve: KeyCurve, x: ByteArray, y: ByteArray): PublicKey = - publicKeyReturn - - override fun publicKey(curve: KeyCurve, x: ByteArray): PublicKey = - publicKeyReturn - - override fun signMessage(privateKey: PrivateKey, message: ByteArray): Signature = - signMessageByteArrayReturn - - // TODO: Add throw classes - override fun signMessage(privateKey: PrivateKey, message: String): Signature = - signMessageStringReturn - - override fun verifySignature( - publicKey: PublicKey, - challenge: ByteArray, - signature: Signature - ): Boolean = verifySignatureReturn } diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt index 92bad612d..165e74f85 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/castor/PrismDIDPublicKeyTests.kt @@ -1,27 +1,31 @@ package io.iohk.atala.prism.walletsdk.castor import io.iohk.atala.prism.protos.PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey import io.iohk.atala.prism.walletsdk.castor.did.prismdid.PrismDIDPublicKey import io.iohk.atala.prism.walletsdk.castor.did.prismdid.id -import io.iohk.atala.prism.walletsdk.domain.models.Curve -import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest -import kotlin.test.Test +import org.junit.Ignore +import org.junit.Test import kotlin.test.assertContentEquals import kotlin.test.assertEquals class PrismDIDPublicKeyTests { @OptIn(ExperimentalCoroutinesApi::class) + @Ignore("PrismDIDPublicKey requires Secp256k1Lib to be an interface in order to mock its result. Once that is done this test can be added back.") @Test - fun it_should_parse_proto_toPrismDIDOublicKey() = runTest { + fun it_should_parse_proto_toPrismDIDPublicKey() = runTest { val apollo = ApolloMock() - val seed = apollo.createRandomSeed().seed - val keyPair = apollo.createKeyPair( - seed = seed, - curve = KeyCurve(Curve.SECP256K1) + val seed = apollo.createRandomSeed(passphrase = "mnemonics").seed + val keyPair = Ed25519KeyPair( + privateKey = Ed25519PrivateKey(ByteArray(0)), + publicKey = Ed25519PublicKey(ByteArray(0)) ) + val publicKey = PrismDIDPublicKey( apollo = ApolloMock(), id = PrismDIDPublicKey.Usage.MASTER_KEY.id(0), diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt index fc67be29c..7f5be9223 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/ApolloMock.kt @@ -3,14 +3,12 @@ package io.iohk.atala.prism.walletsdk.prismagent import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519KeyPair import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PrivateKey import io.iohk.atala.prism.walletsdk.apollo.utils.Ed25519PublicKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo -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.SeedWords -import io.iohk.atala.prism.walletsdk.domain.models.Signature import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.KeyPair import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PrivateKey -import io.iohk.atala.prism.walletsdk.domain.models.keyManagement.PublicKey class ApolloMock : Apollo { var createRandomMnemonicsReturn: Array = emptyArray() @@ -20,13 +18,7 @@ class ApolloMock : Apollo { privateKey = Ed25519PrivateKey(ByteArray(0)), publicKey = Ed25519PublicKey(ByteArray(0)) ) - var compressedPublicKeyReturn = Ed25519PublicKey(ByteArray(0)) - var publicKeyReturn: PublicKey = Ed25519PublicKey(ByteArray(0)) - var signMessageReturn: Signature = Signature(ByteArray(0)) - var verifySignatureReturn: Boolean = false - var compressedPublicKeyDataReturn: PublicKey = Ed25519PublicKey(ByteArray(0)) - var signMessageByteArrayReturn: Signature = Signature(ByteArray(0)) - var signMessageStringReturn: Signature = Signature(ByteArray(0)) + var createPrivateKey: PrivateKey? = null override fun createRandomMnemonics(): Array = createRandomMnemonicsReturn @@ -38,37 +30,7 @@ class ApolloMock : Apollo { return createRandomSeedReturn } - override fun createKeyPair(seed: Seed?, curve: KeyCurve): KeyPair { - return createKeyPairReturn + override fun createPrivateKey(properties: Map): PrivateKey { + return createPrivateKey ?: Secp256k1PrivateKey(ByteArray(0)) } - - override fun createKeyPair(seed: Seed?, privateKey: PrivateKey): KeyPair { - return createKeyPairReturn - } - - override fun compressedPublicKey(publicKey: PublicKey): PublicKey { - return compressedPublicKeyReturn - } - - override fun compressedPublicKey(compressedData: ByteArray): PublicKey = - compressedPublicKeyDataReturn - - override fun publicKey(curve: KeyCurve, x: ByteArray, y: ByteArray): PublicKey = - publicKeyReturn - - override fun publicKey(curve: KeyCurve, x: ByteArray): PublicKey = - publicKeyReturn - - override fun signMessage(privateKey: PrivateKey, message: ByteArray): Signature = - signMessageByteArrayReturn - - // TODO: Add throw classes - override fun signMessage(privateKey: PrivateKey, message: String): Signature = - signMessageStringReturn - - override fun verifySignature( - publicKey: PublicKey, - challenge: ByteArray, - signature: Signature - ): Boolean = verifySignatureReturn } diff --git a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt index 1855086e9..98e5bbdb2 100644 --- a/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt +++ b/atala-prism-sdk/src/commonTest/kotlin/io/iohk/atala/prism/walletsdk/prismagent/PrismAgentTests.kt @@ -1,11 +1,14 @@ package io.iohk.atala.prism.walletsdk.prismagent /* ktlint-disable import-ordering */ +import io.iohk.atala.prism.apollo.utils.Mnemonic import io.iohk.atala.prism.walletsdk.apollo.ApolloImpl -import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1PrivateKey +import io.iohk.atala.prism.walletsdk.apollo.utils.Secp256k1KeyPair import io.iohk.atala.prism.walletsdk.castor.CastorImpl +import io.iohk.atala.prism.walletsdk.domain.models.Curve import io.iohk.atala.prism.walletsdk.domain.models.DID import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument +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.Signature import io.iohk.atala.prism.walletsdk.logger.PrismLoggerMock @@ -16,8 +19,8 @@ import io.iohk.atala.prism.walletsdk.prismagent.protocols.outOfBand.PrismOnboard import io.ktor.http.HttpStatusCode import kotlinx.coroutines.flow.flow import kotlinx.coroutines.test.runTest -import kotlin.test.BeforeTest -import kotlin.test.Test +import org.junit.Before +import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertFalse @@ -36,7 +39,7 @@ class PrismAgentTests { lateinit var mediationHandlerMock: MediationHandlerMock lateinit var connectionManager: ConnectionManager - @BeforeTest + @Before fun setup() { apolloMock = ApolloMock() castorMock = CastorMock() @@ -50,7 +53,7 @@ class PrismAgentTests { @Test fun testCreateNewPrismDID_shouldCreateNewDID_whenCalled() = runTest { - val seed = Seed(ByteArray(0)) + val seed = Seed(Mnemonic.createRandomSeed()) val validDID = DID("did", "test", "123") castorMock.createPrismDIDReturn = validDID val agent = PrismAgent( @@ -246,7 +249,12 @@ class PrismAgentTests { logger = PrismLoggerMock() ) - val privateKeys = listOf(Secp256k1PrivateKey(byteArrayOf())) + val privateKeys = listOf( + Secp256k1KeyPair.generateKeyPair( + seed = Seed(Mnemonic.createRandomSeed()), + curve = KeyCurve(Curve.SECP256K1) + ).privateKey + ) plutoMock.getDIDPrivateKeysReturn = flow { emit(privateKeys) } val did = DID("did", "peer", "asdf1234asdf1234") diff --git a/gradle.properties b/gradle.properties index 6e0c6ad35..8b37e6241 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ kotlin.code.style = official android.useAndroidX = true kotlin.mpp.enableCInteropCommonization = true kotlin.native.cacheKind.iosSimulatorArm64 = none -apollo_version = 1.7.0-alpha +apollo_version = 1.0.1 didpeer_version = 1.0.3-alpha From de4cbb1d63aee405d6c05777f6a9c090c03d6d87 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Mon, 2 Oct 2023 13:44:09 -0400 Subject: [PATCH 12/14] fix: gradle issues --- atala-prism-sdk/build.gradle.kts | 13 ++++++++----- .../iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt | 6 +++--- .../walletsdk/domain/models/keyManagement/Key.kt | 2 +- build.gradle.kts | 10 +++++----- gradle.properties | 1 + 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/atala-prism-sdk/build.gradle.kts b/atala-prism-sdk/build.gradle.kts index 48a175603..e1187e480 100644 --- a/atala-prism-sdk/build.gradle.kts +++ b/atala-prism-sdk/build.gradle.kts @@ -39,7 +39,7 @@ koverReport { } kotlin { - androidTarget { + android { publishAllLibraryVariants() } @@ -100,7 +100,7 @@ kotlin { kotlin.srcDir("${project(":protosLib").buildDir}/generated/source/proto/main/kotlin") resources.srcDir("${project(":protosLib").projectDir}/src/main") dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") @@ -137,7 +137,7 @@ kotlin { val commonTest by getting { dependencies { implementation(kotlin("test")) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.2") implementation("io.ktor:ktor-client-mock:2.3.4") implementation("junit:junit:4.13.2") } @@ -156,7 +156,7 @@ kotlin { } val androidMain by getting { dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2") implementation("io.ktor:ktor-client-okhttp:2.3.4") implementation("org.bouncycastle:bcprov-jdk15on:1.68") implementation("com.squareup.sqldelight:android-driver:1.5.5") @@ -174,7 +174,10 @@ kotlin { */ all { - languageSettings.optIn("kotlin.RequiresOptIn") + languageSettings { + optIn("kotlin.RequiresOptIn") + optIn("kotlin.ExperimentalStdlibApi") + } } } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt index 3c2bab968..18e82c90c 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/apollo/ApolloImpl.kt @@ -71,10 +71,10 @@ class ApolloImpl : Apollo { override fun createPrivateKey(properties: Map): PrivateKey { if (!properties.containsKey(TypeKey().property)) { - throw ApolloError.InvalidKeyType(TypeKey().property, KeyTypes.entries.map { it.type }.toTypedArray()) + throw ApolloError.InvalidKeyType(TypeKey().property, KeyTypes.values().map { it.type }.toTypedArray()) } if (!properties.containsKey(CurveKey().property)) { - throw ApolloError.InvalidKeyCurve(CurveKey().property, Curve.entries.map { it.value }.toTypedArray()) + throw ApolloError.InvalidKeyCurve(CurveKey().property, Curve.values().map { it.value }.toTypedArray()) } val keyType = properties[TypeKey().property] @@ -141,6 +141,6 @@ class ApolloImpl : Apollo { return keyPair.privateKey } } - throw ApolloError.InvalidKeyType(TypeKey().property, KeyTypes.entries.map { it.type }.toTypedArray()) + throw ApolloError.InvalidKeyType(TypeKey().property, KeyTypes.values().map { it.type }.toTypedArray()) } } diff --git a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt index dc57c47ba..bdf4945a8 100644 --- a/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt +++ b/atala-prism-sdk/src/commonMain/kotlin/io/iohk/atala/prism/walletsdk/domain/models/keyManagement/Key.kt @@ -82,7 +82,7 @@ fun getKeyCurveByNameAndIndex(name: String, index: Int?): KeyCurve { } else -> { - throw ApolloError.InvalidKeyCurve(name, Curve.entries.map { it.value }.toTypedArray()) + throw ApolloError.InvalidKeyCurve(name, Curve.values().map { it.value }.toTypedArray()) } } } diff --git a/build.gradle.kts b/build.gradle.kts index 5142a9f5e..9125628ac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,9 +2,9 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin plugins { - id("org.jetbrains.kotlin.android") version "1.9.10" apply false - kotlin("jvm") version "1.9.10" - kotlin("plugin.serialization") version "1.9.10" + id("org.jetbrains.kotlin.android") version "1.8.20" apply false + kotlin("jvm") version "1.8.20" + kotlin("plugin.serialization") version "1.8.20" id("maven-publish") id("dev.petuska.npm.publish") version "3.2.1" id("org.jlleitschuh.gradle.ktlint") version "11.5.1" @@ -19,8 +19,8 @@ buildscript { gradlePluginPortal() } dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10") - classpath("com.android.tools.build:gradle:7.4.0") // 7.4.2 is still not supported + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20") + classpath("com.android.tools.build:gradle:7.2.2") // 7.4.2 is still not supported classpath("com.google.protobuf:protobuf-gradle-plugin:0.9.1") classpath("com.squareup.sqldelight:gradle-plugin:1.5.5") classpath("com.github.piacenti:antlr-kotlin-gradle-plugin:0.0.14") diff --git a/gradle.properties b/gradle.properties index 8b37e6241..11241a437 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,3 +6,4 @@ kotlin.mpp.enableCInteropCommonization = true kotlin.native.cacheKind.iosSimulatorArm64 = none apollo_version = 1.0.1 didpeer_version = 1.0.3-alpha +kotlin.mpp.androidSourceSetLayoutVersion = 2 \ No newline at end of file From 66c434e2b9c88c4b80768ac23ebf8021ffcaeed2 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Mon, 2 Oct 2023 15:32:32 -0400 Subject: [PATCH 13/14] revert coroutines version downgrade --- atala-prism-sdk/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atala-prism-sdk/build.gradle.kts b/atala-prism-sdk/build.gradle.kts index e1187e480..68cfc677c 100644 --- a/atala-prism-sdk/build.gradle.kts +++ b/atala-prism-sdk/build.gradle.kts @@ -100,7 +100,7 @@ kotlin { kotlin.srcDir("${project(":protosLib").buildDir}/generated/source/proto/main/kotlin") resources.srcDir("${project(":protosLib").projectDir}/src/main") dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") @@ -137,7 +137,7 @@ kotlin { val commonTest by getting { dependencies { implementation(kotlin("test")) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.2") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") implementation("io.ktor:ktor-client-mock:2.3.4") implementation("junit:junit:4.13.2") } @@ -156,7 +156,7 @@ kotlin { } val androidMain by getting { dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") implementation("io.ktor:ktor-client-okhttp:2.3.4") implementation("org.bouncycastle:bcprov-jdk15on:1.68") implementation("com.squareup.sqldelight:android-driver:1.5.5") From 1cea036a26ecf67a36c0d9fc6e5aa42427f5da50 Mon Sep 17 00:00:00 2001 From: Cristian G Date: Tue, 3 Oct 2023 10:52:58 -0400 Subject: [PATCH 14/14] feat: use latest apollo 1.0.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 11241a437..fb61a6543 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,6 +4,6 @@ kotlin.code.style = official android.useAndroidX = true kotlin.mpp.enableCInteropCommonization = true kotlin.native.cacheKind.iosSimulatorArm64 = none -apollo_version = 1.0.1 +apollo_version = 1.0.2 didpeer_version = 1.0.3-alpha kotlin.mpp.androidSourceSetLayoutVersion = 2 \ No newline at end of file