diff --git a/build.sbt b/build.sbt index 6094a14de5..11256b8ff3 100644 --- a/build.sbt +++ b/build.sbt @@ -82,6 +82,7 @@ lazy val V = new { val jwtCirceVersion = "9.1.2" val zioPreludeVersion = "1.0.0-RC16" + val apollo = "1.2.13" val bouncyCastle = "1.70" val jsonSchemaValidator = "1.3.2" @@ -160,6 +161,18 @@ lazy val D = new { val monocle: ModuleID = "dev.optics" %% "monocle-core" % V.monocle % Test val monocleMacro: ModuleID = "dev.optics" %% "monocle-macro" % V.monocle % Test + val apollo = "io.iohk.atala.prism.apollo" % "apollo-jvm" % V.apollo + // We have to exclude bouncycastle since for some reason bitcoinj depends on bouncycastle jdk15to18 + // (i.e. JDK 1.5 to 1.8), but we are using JDK 11 + val prismCrypto = "io.iohk.atala" % "prism-crypto-jvm" % V.prismSdk excludeAll + ExclusionRule( + organization = "org.bouncycastle" + ) + // Added here to make prism-crypto works. + // Once migrated to apollo, re-evaluate if this should be removed. + val bouncyBcpkix = "org.bouncycastle" % "bcpkix-jdk15on" % V.bouncyCastle + val bouncyBcprov = "org.bouncycastle" % "bcprov-jdk15on" % V.bouncyCastle + // LIST of Dependencies val doobieDependencies: Seq[ModuleID] = Seq(doobiePostgres, doobiePostgresCirce, doobieHikari, flyway) @@ -186,6 +199,19 @@ lazy val D_Shared = new { ) } +lazy val D_SharedCrypto = new { + lazy val dependencies: Seq[ModuleID] = + Seq( + D.apollo, + D.bouncyBcpkix, + D.bouncyBcprov, + D.prismCrypto, // TODO: remove after migrated all primitives to apollo + D.zioTest, + D.zioTestSbt, + D.zioTestMagnolia, + ) +} + lazy val D_SharedTest = new { lazy val dependencies: Seq[ModuleID] = D_Shared.dependencies ++ Seq( @@ -218,15 +244,6 @@ lazy val D_Connect = new { } lazy val D_Castor = new { - - // We have to exclude bouncycastle since for some reason bitcoinj depends on bouncycastle jdk15to18 - // (i.e. JDK 1.5 to 1.8), but we are using JDK 11 - val prismCrypto = "io.iohk.atala" % "prism-crypto-jvm" % V.prismSdk excludeAll - ExclusionRule( - organization = "org.bouncycastle" - ) - val prismIdentity = "io.iohk.atala" % "prism-identity-jvm" % V.prismSdk - // Dependency Modules val baseDependencies: Seq[ModuleID] = Seq( @@ -235,7 +252,6 @@ lazy val D_Castor = new { D.zioMock, D.zioTestSbt, D.zioTestMagnolia, - prismIdentity, ) // Project Dependencies @@ -258,13 +274,6 @@ lazy val D_Pollux = new { val quillDoobie = "io.getquill" %% "quill-doobie" % V.quill exclude ("org.scala-lang.modules", "scala-java8-compat_3") - // We have to exclude bouncycastle since for some reason bitcoinj depends on bouncycastle jdk15to18 - // (i.e. JDK 1.5 to 1.8), but we are using JDK 11 - val prismCrypto = "io.iohk.atala" % "prism-crypto-jvm" % V.prismSdk excludeAll - ExclusionRule( - organization = "org.bouncycastle" - ) - // Dependency Modules val baseDependencies: Seq[ModuleID] = Seq( D.zio, @@ -276,7 +285,7 @@ lazy val D_Pollux = new { D.zioMock, D.munit, D.munitZio, - prismCrypto, + D.prismCrypto, // shared, logback, slf4jApi, @@ -342,12 +351,6 @@ lazy val D_Pollux_AnonCreds = new { } lazy val D_PrismAgent = new { - - // Added here to make prism-crypto works. - // Once migrated to apollo, re-evaluate if this should be removed. - val bouncyBcpkix = "org.bouncycastle" % "bcpkix-jdk15on" % V.bouncyCastle - val bouncyBcprov = "org.bouncycastle" % "bcprov-jdk15on" % V.bouncyCastle - val logback = "ch.qos.logback" % "logback-classic" % V.logback val tapirSwaggerUiBundle = "com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-bundle" % V.tapir @@ -391,7 +394,7 @@ lazy val D_PrismAgent = new { D.micrometer, D.micrometerPrometheusRegistry ) - val bouncyDependencies: Seq[ModuleID] = Seq(bouncyBcpkix, bouncyBcprov) + val bouncyDependencies: Seq[ModuleID] = Seq(D.bouncyBcpkix, D.bouncyBcprov) val tapirDependencies: Seq[ModuleID] = Seq( tapirSwaggerUiBundle, @@ -459,31 +462,37 @@ val commonSetttings = Seq( // ##### shared ###### // ##################### -lazy val shared = (project in file("shared")) - // .configure(publishConfigure) +lazy val shared = (project in file("shared/core")) .settings(commonSetttings) .settings( organization := "io.iohk.atala", organizationName := "Input Output Global", - buildInfoPackage := "io.iohk.atala.shared", name := "shared", crossPaths := false, libraryDependencies ++= D_Shared.dependencies ) - .enablePlugins(BuildInfoPlugin) -lazy val sharedTest = (project in file("shared-test")) +lazy val sharedCrypto = (project in file("shared/crypto")) + .settings(commonSetttings) + .settings( + organization := "io.iohk.atala", + organizationName := "Input Output Global", + name := "shared-crypto", + crossPaths := false, + libraryDependencies ++= D_SharedCrypto.dependencies + ) + .dependsOn(shared) + +lazy val sharedTest = (project in file("shared/test")) .settings(commonSetttings) .settings( organization := "io.iohk.atala", organizationName := "Input Output Global", - buildInfoPackage := "io.iohk.atala.sharedtest", - name := "sharedtest", + name := "shared-test", crossPaths := false, libraryDependencies ++= D_SharedTest.dependencies ) .dependsOn(shared) - .enablePlugins(BuildInfoPlugin) // ######################### // ### Models & Services ### @@ -711,6 +720,7 @@ lazy val castorCore = project libraryDependencies ++= D_Castor.coreDependencies ) .dependsOn(shared, prismNodeClient) + .dependsOn(sharedCrypto % "compile->compile;test->test") // ##################### // ##### pollux ###### @@ -830,6 +840,7 @@ lazy val prismAgentWalletAPI = project eventNotification ) .dependsOn(sharedTest % "test->test") + .dependsOn(sharedCrypto % "compile->compile;test->test") lazy val prismAgentServer = project .in(file("prism-agent/service/server")) @@ -838,6 +849,11 @@ lazy val prismAgentServer = project name := "prism-agent", fork := true, libraryDependencies ++= D_PrismAgent.serverDependencies, + excludeDependencies ++= Seq( + // Exclude `protobuf-javalite` from all dependencies since we're using scalapbRuntime which already include `protobuf-java` + // Having both may introduce conflict on some api https://github.com/protocolbuffers/protobuf/issues/8104 + ExclusionRule("com.google.protobuf", "protobuf-javalite") + ), Compile / mainClass := Some("io.iohk.atala.agent.server.MainApp"), Docker / maintainer := "atala-coredid@iohk.io", Docker / dockerUsername := Some("input-output-hk"), @@ -880,6 +896,7 @@ releaseProcess := Seq[ReleaseStep]( lazy val aggregatedProjects: Seq[ProjectReference] = Seq( shared, + sharedCrypto, sharedTest, models, protocolConnection, diff --git a/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/service/MockDIDService.scala b/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/service/MockDIDService.scala index 94b1bd9439..14fc883494 100644 --- a/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/service/MockDIDService.scala +++ b/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/service/MockDIDService.scala @@ -2,15 +2,19 @@ package io.iohk.atala.castor.core.service import io.iohk.atala.castor.core.model.did.* import io.iohk.atala.castor.core.model.error -import io.iohk.atala.prism.crypto.EC -import io.iohk.atala.prism.crypto.keys.ECKeyPair +import io.iohk.atala.shared.crypto.Apollo +import io.iohk.atala.shared.crypto.Secp256k1KeyPair import io.iohk.atala.shared.models.Base64UrlString import zio.mock.{Expectation, Mock, Proxy} import zio.test.Assertion -import zio.{IO, URLayer, ZIO, ZLayer, mock} +import zio.{IO, URLayer, ZIO, ZLayer, mock, Unsafe, Runtime} +import java.util.concurrent.TimeUnit import scala.collection.immutable.ArraySeq +import scala.concurrent.Await +import scala.concurrent.duration.Duration +// FIXME: move this to test code object MockDIDService extends Mock[DIDService] { object ScheduleOperation extends Effect[SignedPrismDIDOperation, error.DIDOperationError, ScheduleDIDOperationOutcome] @@ -40,9 +44,15 @@ object MockDIDService extends Mock[DIDService] { def createDID( verificationRelationship: VerificationRelationship - ): (PrismDIDOperation.Create, ECKeyPair, DIDMetadata, DIDData) = { - val masterKeyPair = EC.INSTANCE.generateKeyPair() - val keyPair = EC.INSTANCE.generateKeyPair() + ): (PrismDIDOperation.Create, Secp256k1KeyPair, DIDMetadata, DIDData) = { + // FIXME: unsafe bridge just to avoid refactoring the whole test into ZIO[?, ?, KeyPair] + def unsafeRun(effect: ZIO[Any, Nothing, Secp256k1KeyPair]): Secp256k1KeyPair = { + val f = Unsafe.unsafe { implicit unsafe => Runtime.default.unsafe.runToFuture(effect) } + Await.result(f, Duration(10, TimeUnit.SECONDS)) + } + val masterKeyPair = unsafeRun(Apollo.default.secp256k1.generateKeyPair) + val keyPair = unsafeRun(Apollo.default.secp256k1.generateKeyPair) + val createOperation = PrismDIDOperation.Create( publicKeys = Seq( InternalPublicKey( @@ -50,7 +60,7 @@ object MockDIDService extends Mock[DIDService] { purpose = InternalKeyPurpose.Master, publicKeyData = PublicKeyData.ECCompressedKeyData( crv = EllipticCurve.SECP256K1, - data = Base64UrlString.fromByteArray(masterKeyPair.getPublicKey.getEncodedCompressed) + data = Base64UrlString.fromByteArray(masterKeyPair.publicKey.getEncodedCompressed) ) ), PublicKey( @@ -58,7 +68,7 @@ object MockDIDService extends Mock[DIDService] { purpose = verificationRelationship, publicKeyData = PublicKeyData.ECCompressedKeyData( crv = EllipticCurve.SECP256K1, - data = Base64UrlString.fromByteArray(keyPair.getPublicKey.getEncodedCompressed) + data = Base64UrlString.fromByteArray(keyPair.publicKey.getEncodedCompressed) ) ), ), diff --git a/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/util/DIDOperationValidator.scala b/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/util/DIDOperationValidator.scala index 939b71408d..ef496100ac 100644 --- a/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/util/DIDOperationValidator.scala +++ b/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/util/DIDOperationValidator.scala @@ -46,6 +46,7 @@ class DIDOperationValidator(config: Config) extends BaseOperationValidator { private object CreateOperationValidator extends BaseOperationValidator { def validate(config: Config)(operation: PrismDIDOperation.Create): Either[OperationValidationError, Unit] = { for { + // TODO: validate public key content _ <- validateMaxPublicKeysAccess(config)(operation, extractKeyIds) _ <- validateMaxServiceAccess(config)(operation, extractServiceIds) _ <- validateUniquePublicKeyId(operation, extractKeyIds) diff --git a/connect/lib/core/src/test/scala/io/iohk/atala/connect/core/repository/ConnectionRepositorySpecSuite.scala b/connect/lib/core/src/test/scala/io/iohk/atala/connect/core/repository/ConnectionRepositorySpecSuite.scala index b7ecd2834f..12e4d9876f 100644 --- a/connect/lib/core/src/test/scala/io/iohk/atala/connect/core/repository/ConnectionRepositorySpecSuite.scala +++ b/connect/lib/core/src/test/scala/io/iohk/atala/connect/core/repository/ConnectionRepositorySpecSuite.scala @@ -6,14 +6,13 @@ import io.iohk.atala.mercury.model.DidId import io.iohk.atala.mercury.protocol.connection.{ConnectionRequest, ConnectionResponse} import io.iohk.atala.mercury.protocol.invitation.v2.Invitation import io.iohk.atala.shared.models.{WalletAccessContext, WalletId} +import zio.Exit.Failure import zio.test.* import zio.{Cause, Exit, ZIO, ZLayer} import java.time.Instant import java.time.temporal.ChronoUnit import java.util.UUID -import zio.Exit.Success -import zio.Exit.Failure object ConnectionRepositorySpecSuite { diff --git a/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/model/error/CredentialStatusListServiceError.scala b/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/model/error/CredentialStatusListServiceError.scala index 21354d0040..d0ffc298b9 100644 --- a/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/model/error/CredentialStatusListServiceError.scala +++ b/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/model/error/CredentialStatusListServiceError.scala @@ -1,7 +1,6 @@ package io.iohk.atala.pollux.core.model.error import io.iohk.atala.pollux.core.model.DidCommID -import io.iohk.atala.pollux.vc.jwt.W3cCredentialPayload import java.util.UUID diff --git a/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/repository/CredentialStatusListRepository.scala b/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/repository/CredentialStatusListRepository.scala index 978bcd87fb..f6c3958797 100644 --- a/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/repository/CredentialStatusListRepository.scala +++ b/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/repository/CredentialStatusListRepository.scala @@ -1,11 +1,8 @@ package io.iohk.atala.pollux.core.repository -import io.iohk.atala.castor.core.model.did.CanonicalPrismDID -import io.iohk.atala.mercury.protocol.issuecredential.{IssueCredential, RequestCredential} import io.iohk.atala.pollux.core.model.* -import io.iohk.atala.pollux.core.model.IssueCredentialRecord.ProtocolState import io.iohk.atala.pollux.vc.jwt.Issuer -import io.iohk.atala.shared.models.{WalletAccessContext, WalletId} +import io.iohk.atala.shared.models.WalletAccessContext import zio.* import java.util.UUID diff --git a/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/service/MockCredentialService.scala b/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/service/MockCredentialService.scala index 21b7d82e73..75ba7a19f8 100644 --- a/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/service/MockCredentialService.scala +++ b/pollux/lib/core/src/main/scala/io/iohk/atala/pollux/core/service/MockCredentialService.scala @@ -6,8 +6,6 @@ import io.iohk.atala.mercury.model.DidId import io.iohk.atala.mercury.protocol.issuecredential.{IssueCredential, OfferCredential, RequestCredential} import io.iohk.atala.pollux.core.model.error.CredentialServiceError import io.iohk.atala.pollux.core.model.{DidCommID, IssueCredentialRecord} -import io.iohk.atala.pollux.vc.jwt.W3cCredentialPayload -import io.iohk.atala.prism.crypto.MerkleInclusionProof import io.iohk.atala.shared.models.WalletAccessContext import zio.mock.{Mock, Proxy} import zio.{IO, URLayer, ZIO, ZLayer, mock} @@ -57,8 +55,6 @@ object MockCredentialService extends Mock[CredentialService] { object AcceptCredentialRequest extends Effect[DidCommID, CredentialServiceError, IssueCredentialRecord] object GenerateJWTCredential extends Effect[(DidCommID, String), CredentialServiceError, IssueCredentialRecord] object GenerateAnonCredsCredential extends Effect[DidCommID, CredentialServiceError, IssueCredentialRecord] - object MarkCredentialRecordsAsPublishQueued - extends Effect[Seq[(W3cCredentialPayload, MerkleInclusionProof)], CredentialServiceError, Int] object ReceiveCredentialIssue extends Effect[IssueCredential, CredentialServiceError, IssueCredentialRecord] object MarkOfferSent extends Effect[DidCommID, CredentialServiceError, IssueCredentialRecord] object MarkRequestSent extends Effect[DidCommID, CredentialServiceError, IssueCredentialRecord] diff --git a/pollux/lib/sql-doobie/src/main/scala/io/iohk/atala/pollux/sql/repository/JdbcPresentationRepository.scala b/pollux/lib/sql-doobie/src/main/scala/io/iohk/atala/pollux/sql/repository/JdbcPresentationRepository.scala index 19acb64d76..377d769ff1 100644 --- a/pollux/lib/sql-doobie/src/main/scala/io/iohk/atala/pollux/sql/repository/JdbcPresentationRepository.scala +++ b/pollux/lib/sql-doobie/src/main/scala/io/iohk/atala/pollux/sql/repository/JdbcPresentationRepository.scala @@ -15,11 +15,9 @@ import io.iohk.atala.mercury.protocol.presentproof.* import io.iohk.atala.pollux.core.model.* import io.iohk.atala.pollux.core.model.PresentationRecord.ProtocolState import io.iohk.atala.pollux.core.repository.PresentationRepository -import io.iohk.atala.prism.crypto.MerkleInclusionProof import io.iohk.atala.shared.db.ContextAwareTask import io.iohk.atala.shared.db.Implicits.* import io.iohk.atala.shared.models.WalletAccessContext -import io.iohk.atala.shared.utils.BytesOps import zio.* import zio.interop.catz.* import zio.json.* @@ -81,14 +79,6 @@ class JdbcPresentationRepository( .transactWallet(xa) } - // deserializes from the hex string - private def deserializeInclusionProof(proof: String): MerkleInclusionProof = - MerkleInclusionProof.decode( - String( - BytesOps.hexToBytes(proof) - ) - ) - // Uncomment to have Doobie LogHandler in scope and automatically output SQL statements in logs // given logHandler: LogHandler = LogHandler.jdkLogHandler @@ -136,8 +126,6 @@ class JdbcPresentationRepository( Get[String].map(decode[ProposePresentation](_).getOrElse(???)) given proposePresentationPut: Put[ProposePresentation] = Put[String].contramap(_.asJson.toString) - given inclusionProofGet: Get[MerkleInclusionProof] = Get[String].map(deserializeInclusionProof) - override def createPresentationRecord(record: PresentationRecord): RIO[WalletAccessContext, Int] = { val cxnIO = sql""" | INSERT INTO public.presentation_records( diff --git a/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/DidJWT.scala b/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/DidJWT.scala index 13f750a3b2..909782cd86 100644 --- a/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/DidJWT.scala +++ b/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/DidJWT.scala @@ -6,19 +6,11 @@ import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton import com.nimbusds.jose.jwk.{Curve, ECKey} import com.nimbusds.jwt.{JWTClaimsSet, SignedJWT} import io.circe.* -import io.circe.syntax.* import zio.* import pdi.jwt.algorithms.JwtECDSAAlgorithm import pdi.jwt.{JwtAlgorithm, JwtCirce} -import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} import java.security.* -import io.iohk.atala.shared.utils.Json as JsonUtils -import io.iohk.atala.shared.utils.Base64Utils as Base64Utils - -import scodec.bits.* - -import java.time.* opaque type JWT = String diff --git a/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/MultiKey.scala b/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/MultiKey.scala index 0addd169ed..765387358b 100644 --- a/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/MultiKey.scala +++ b/pollux/lib/vc-jwt/src/main/scala/io/iohk/atala/pollux/vc/jwt/MultiKey.scala @@ -2,7 +2,6 @@ package io.iohk.atala.pollux.vc.jwt import io.circe.* import io.circe.syntax.* -import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} case class MultiKey( publicKeyMultibase: Option[MultiBaseString] = None, diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala index d7a1275b48..6d23979251 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala @@ -6,7 +6,6 @@ import io.grpc.ManagedChannelBuilder import io.iohk.atala.agent.server.config.AppConfig import io.iohk.atala.agent.server.config.SecretStorageBackend import io.iohk.atala.agent.server.config.ValidatedVaultConfig -import io.iohk.atala.agent.walletapi.crypto.Apollo import io.iohk.atala.agent.walletapi.memory.{ DIDSecretStorageInMemory, GenericSecretStorageInMemory, @@ -40,6 +39,7 @@ import io.iohk.atala.iam.authorization.core.PermissionManagement import io.iohk.atala.iam.authorization.keycloak.admin.KeycloakPermissionManagementService import io.iohk.atala.pollux.vc.jwt.{PrismDidResolver, DidResolver as JwtDidResolver} import io.iohk.atala.prism.protos.node_api.NodeServiceGrpc +import io.iohk.atala.shared.crypto.Apollo import io.iohk.atala.shared.db.{ContextAwareTask, DbConfig, TransactorLayer} import org.keycloak.authorization.client.AuthzClient import zio.* @@ -80,7 +80,7 @@ object SystemModule { } object AppModule { - val apolloLayer: ULayer[Apollo] = Apollo.prism14Layer + val apolloLayer: ULayer[Apollo] = Apollo.layer val didJwtResolverLayer: URLayer[DIDService, JwtDidResolver] = ZLayer.fromFunction(PrismDidResolver(_)) diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/PrismAgentApp.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/PrismAgentApp.scala index 47495dcf52..253dc6a645 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/PrismAgentApp.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/PrismAgentApp.scala @@ -25,7 +25,7 @@ import io.iohk.atala.iam.entity.http.EntityServerEndpoints import io.iohk.atala.iam.wallet.http.WalletManagementServerEndpoints import io.iohk.atala.issue.controller.IssueServerEndpoints import io.iohk.atala.mercury.{DidOps, HttpClient} -import io.iohk.atala.pollux.core.service.{CredentialService, CredentialStatusListService, PresentationService} +import io.iohk.atala.pollux.core.service.{CredentialService, PresentationService} import io.iohk.atala.pollux.credentialdefinition.CredentialDefinitionRegistryServerEndpoints import io.iohk.atala.pollux.credentialschema.{SchemaRegistryServerEndpoints, VerificationPolicyServerEndpoints} import io.iohk.atala.pollux.vc.jwt.DidResolver as JwtDidResolver diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/jobs/PresentBackgroundJobs.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/jobs/PresentBackgroundJobs.scala index 1a430c8769..6f7e3f3b00 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/jobs/PresentBackgroundJobs.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/jobs/PresentBackgroundJobs.scala @@ -9,11 +9,7 @@ import io.iohk.atala.agent.server.jobs.BackgroundJobError.{ InvalidState, NotImplemented } -import io.iohk.atala.agent.walletapi.model.error.DIDSecretStorageError.WalletNotFoundError -import io.iohk.atala.agent.walletapi.service.ManagedDIDService -import io.iohk.atala.agent.walletapi.storage.DIDNonSecretStorage import io.iohk.atala.castor.core.model.did.* -import io.iohk.atala.castor.core.service.DIDService import io.iohk.atala.mercury.* import io.iohk.atala.mercury.model.* import io.iohk.atala.mercury.protocol.presentproof.* @@ -24,7 +20,6 @@ import io.iohk.atala.pollux.core.model.error.{CredentialServiceError, Presentati import io.iohk.atala.pollux.core.service.serdes.AnoncredCredentialProofsV1 import io.iohk.atala.pollux.core.service.{CredentialService, PresentationService} import io.iohk.atala.pollux.vc.jwt.{JWT, JwtPresentation, DidResolver as JwtDidResolver} -import io.iohk.atala.resolvers.DIDResolver import io.iohk.atala.shared.utils.DurationOps.toMetricsSeconds import io.iohk.atala.shared.utils.aspects.CustomMetricsAspect import zio.* diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/api/http/ErrorResponse.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/api/http/ErrorResponse.scala index 297a09c947..262a0ee3a2 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/api/http/ErrorResponse.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/api/http/ErrorResponse.scala @@ -1,8 +1,7 @@ package io.iohk.atala.api.http import io.iohk.atala.api.http.ErrorResponse.annotations -import io.iohk.atala.connect.controller.http.Connection -import io.iohk.atala.shared.models.{Failure, WalletAccessContext} +import io.iohk.atala.shared.models.Failure import sttp.model.StatusCode import sttp.tapir.Schema import sttp.tapir.Schema.annotations.{description, encodedExample} diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/castor/controller/DIDRegistrarController.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/castor/controller/DIDRegistrarController.scala index 4ed6f95d70..1b53a054e5 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/castor/controller/DIDRegistrarController.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/castor/controller/DIDRegistrarController.scala @@ -57,8 +57,6 @@ object DIDRegistrarController { given Conversion[CreateManagedDIDError, ErrorResponse] = { case CreateManagedDIDError.InvalidArgument(msg) => ErrorResponse.unprocessableEntity(detail = Some(msg)) - case CreateManagedDIDError.KeyGenerationError(e) => - ErrorResponse.internalServerError(detail = Some(e.toString)) case CreateManagedDIDError.WalletStorageError(e) => ErrorResponse.internalServerError(detail = Some(e.toString)) case CreateManagedDIDError.InvalidOperation(e) => diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/credentialstatus/controller/CredentialStatusServiceEndpoints.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/credentialstatus/controller/CredentialStatusServiceEndpoints.scala index 5736175b44..3e2a720e84 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/credentialstatus/controller/CredentialStatusServiceEndpoints.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/credentialstatus/controller/CredentialStatusServiceEndpoints.scala @@ -1,6 +1,5 @@ package io.iohk.atala.credentialstatus.controller -import io.iohk.atala.iam.authentication.{Authenticator, Authorizer} import io.iohk.atala.agent.walletapi.model.BaseEntity import io.iohk.atala.api.http.{ErrorResponse, RequestContext} import io.iohk.atala.iam.authentication.Authenticator diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/iam/wallet/http/controller/WalletManagementController.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/iam/wallet/http/controller/WalletManagementController.scala index a9a2fc5a0d..13d01d95d4 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/iam/wallet/http/controller/WalletManagementController.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/iam/wallet/http/controller/WalletManagementController.scala @@ -49,8 +49,6 @@ trait WalletManagementController { object WalletManagementController { given walletServiceErrorConversion: Conversion[WalletManagementServiceError, ErrorResponse] = { - case WalletManagementServiceError.SeedGenerationError(cause) => - ErrorResponse.internalServerError(detail = Some(cause.getMessage())) case WalletManagementServiceError.UnexpectedStorageError(cause) => ErrorResponse.internalServerError(detail = Some(cause.getMessage())) case WalletManagementServiceError.TooManyWebhookError(limit, actual) => diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/agent/server/AgentInitializationSpec.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/agent/server/AgentInitializationSpec.scala index 4acb8f88e9..c43fc1f3e1 100644 --- a/prism-agent/service/server/src/test/scala/io/iohk/atala/agent/server/AgentInitializationSpec.scala +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/agent/server/AgentInitializationSpec.scala @@ -1,7 +1,7 @@ package io.iohk.atala.agent.server import io.iohk.atala.agent.server.config.AppConfig -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper +import io.iohk.atala.agent.server.config.SecretStorageBackend import io.iohk.atala.agent.walletapi.service.EntityServiceImpl import io.iohk.atala.agent.walletapi.service.WalletManagementService import io.iohk.atala.agent.walletapi.service.WalletManagementServiceImpl @@ -12,6 +12,7 @@ import io.iohk.atala.agent.walletapi.storage.WalletNonSecretStorage import io.iohk.atala.agent.walletapi.storage.WalletSecretStorage import io.iohk.atala.iam.authentication.apikey.ApiKeyAuthenticatorImpl import io.iohk.atala.iam.authentication.apikey.JdbcAuthenticationRepository +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAccessContext import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.WalletId @@ -23,7 +24,6 @@ import zio.test.Assertion.* import zio.test.ZIOSpecDefault import java.net.URL -import io.iohk.atala.agent.server.config.SecretStorageBackend object AgentInitializationSpec extends ZIOSpecDefault, PostgresTestContainerSupport, ApolloSpecHelper { diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/apikey/ApiKeyAuthenticatorSpec.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/apikey/ApiKeyAuthenticatorSpec.scala index 75973104de..23aa3096e7 100644 --- a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/apikey/ApiKeyAuthenticatorSpec.scala +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/apikey/ApiKeyAuthenticatorSpec.scala @@ -1,7 +1,6 @@ package io.iohk.atala.iam.authentication.apikey import com.dimafeng.testcontainers.PostgreSQLContainer -import io.iohk.atala.agent.walletapi.crypto.Apollo import io.iohk.atala.agent.walletapi.model.{Entity, Wallet} import io.iohk.atala.agent.walletapi.service.{ EntityService, @@ -13,6 +12,7 @@ import io.iohk.atala.agent.walletapi.sql.{JdbcEntityRepository, JdbcWalletNonSec import io.iohk.atala.container.util.MigrationAspects.* import io.iohk.atala.iam.authentication.AuthenticationError import io.iohk.atala.iam.authentication.AuthenticationError.InvalidCredentials +import io.iohk.atala.shared.crypto.Apollo import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.WalletId import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport @@ -51,7 +51,7 @@ object ApiKeyAuthenticatorSpec extends ZIOSpecDefault, PostgresTestContainerSupp JdbcAuthenticationRepository.layer, EntityServiceImpl.layer, JdbcEntityRepository.layer, - Apollo.prism14Layer, + Apollo.layer, WalletManagementServiceImpl.layer, JdbcWalletNonSecretStorage.layer, JdbcWalletSecretStorage.layer, diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/oidc/KeycloakAuthenticatorSpec.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/oidc/KeycloakAuthenticatorSpec.scala index a2ae0923a7..24a7f1b6c7 100644 --- a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/oidc/KeycloakAuthenticatorSpec.scala +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authentication/oidc/KeycloakAuthenticatorSpec.scala @@ -1,6 +1,5 @@ package io.iohk.atala.iam.authentication.oidc -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.model.EntityRole import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.service.WalletManagementService @@ -9,6 +8,7 @@ import io.iohk.atala.agent.walletapi.sql.JdbcWalletNonSecretStorage import io.iohk.atala.agent.walletapi.sql.JdbcWalletSecretStorage import io.iohk.atala.iam.authentication.AuthenticationError import io.iohk.atala.iam.authorization.keycloak.admin.KeycloakPermissionManagementService +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.WalletId import io.iohk.atala.sharedtest.containers.KeycloakAdminClient diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala index 90c4658b6d..0fa7d18ab7 100644 --- a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala @@ -1,6 +1,5 @@ package io.iohk.atala.iam.authorization.core -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.model.Entity import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.service.EntityService @@ -12,6 +11,7 @@ import io.iohk.atala.agent.walletapi.sql.JdbcWalletNonSecretStorage import io.iohk.atala.agent.walletapi.sql.JdbcWalletSecretStorage import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.ServiceError import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.WalletNotFoundById +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.WalletId import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala index 7f95f15064..65fd8084d3 100644 --- a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala @@ -1,6 +1,5 @@ package io.iohk.atala.iam.authorization.keycloak.admin -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.service.WalletManagementServiceImpl import io.iohk.atala.agent.walletapi.service.{WalletManagementService, WalletManagementServiceError} @@ -15,8 +14,9 @@ import io.iohk.atala.iam.authentication.oidc.{ KeycloakEntity } import io.iohk.atala.iam.authorization.core.PermissionManagement -import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.WalletNotFoundById import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.UnexpectedError +import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.WalletNotFoundById +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.{WalletAccessContext, WalletId} import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/system/controller/SystemControllerTestTools.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/system/controller/SystemControllerTestTools.scala index 12d3203cbd..930007b7bf 100644 --- a/prism-agent/service/server/src/test/scala/io/iohk/atala/system/controller/SystemControllerTestTools.scala +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/system/controller/SystemControllerTestTools.scala @@ -1,6 +1,5 @@ package io.iohk.atala.system.controller -import io.iohk.atala.api.http.ErrorResponse import sttp.client3.testing.SttpBackendStub import sttp.client3.{DeserializationException, Response, UriContext} import sttp.tapir.server.interceptor.CustomiseInterceptors diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/crypto/Apollo.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/crypto/Apollo.scala deleted file mode 100644 index 04480d8c96..0000000000 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/crypto/Apollo.scala +++ /dev/null @@ -1,47 +0,0 @@ -package io.iohk.atala.agent.walletapi.crypto - -import io.iohk.atala.castor.core.model.did.EllipticCurve -import io.iohk.atala.agent.walletapi.util.Prism14CompatUtil.* -import zio.* - -import scala.util.Try - -final case class ECKeyPair(publicKey: ECPublicKey, privateKey: ECPrivateKey) - -trait ECPublicKey { - def curve: EllipticCurve - def toJavaPublicKey: java.security.interfaces.ECPublicKey - def verify(data: Array[Byte], signature: Array[Byte]): Try[Unit] - def encode: Array[Byte] -} - -trait ECPrivateKey { - def curve: EllipticCurve - def toJavaPrivateKey: java.security.interfaces.ECPrivateKey - def sign(data: Array[Byte]): Try[Array[Byte]] - def encode: Array[Byte] - def computePublicKey: ECPublicKey - override final def toString(): String = "" -} - -trait ECKeyFactory { - def publicKeyFromCoordinate(curve: EllipticCurve, x: BigInt, y: BigInt): Try[ECPublicKey] - def publicKeyFromEncoded(curve: EllipticCurve, bytes: Array[Byte]): Try[ECPublicKey] - def privateKeyFromEncoded(curve: EllipticCurve, bytes: Array[Byte]): Try[ECPrivateKey] - def generateKeyPair(curve: EllipticCurve): Task[ECKeyPair] - def deriveKeyPair(curve: EllipticCurve, seed: Array[Byte])(path: DerivationPath*): Task[ECKeyPair] - def randomBip32Seed(): Task[(Array[Byte], Seq[String])] -} - -enum DerivationPath { - case Normal(i: Int) extends DerivationPath - case Hardened(i: Int) extends DerivationPath -} - -trait Apollo { - def ecKeyFactory: ECKeyFactory -} - -object Apollo { - val prism14Layer: ULayer[Apollo] = ZLayer.succeed(Prism14Apollo) -} diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/crypto/Prism14Apollo.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/crypto/Prism14Apollo.scala deleted file mode 100644 index 734db619e0..0000000000 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/crypto/Prism14Apollo.scala +++ /dev/null @@ -1,164 +0,0 @@ -package io.iohk.atala.agent.walletapi.crypto - -import io.iohk.atala.castor.core.model.did.EllipticCurve - -import scala.util.{Failure, Success, Try} -import java.security.KeyFactory -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.bouncycastle.jce.ECNamedCurveTable -import org.bouncycastle.jce.spec.ECNamedCurveSpec - -import java.security.spec.{ECPrivateKeySpec, ECPublicKeySpec} -import io.iohk.atala.agent.walletapi.util.Prism14CompatUtil.* -import io.iohk.atala.prism.crypto.EC -import zio.* -import io.iohk.atala.prism.crypto.derivation.KeyDerivation -import io.iohk.atala.prism.crypto.derivation.DerivationAxis -import scala.jdk.CollectionConverters.* - -final case class Prism14ECPublicKey(publicKey: io.iohk.atala.prism.crypto.keys.ECPublicKey) extends ECPublicKey { - - override def curve: EllipticCurve = EllipticCurve.SECP256K1 - - override def encode: Array[Byte] = publicKey.getEncodedCompressed - - override def toJavaPublicKey: java.security.interfaces.ECPublicKey = { - val x = publicKey.getCurvePoint.getX.getCoordinate.toScalaBigInt - val y = publicKey.getCurvePoint.getY.getCoordinate.toScalaBigInt - val keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider()) - val ecParameterSpec = ECNamedCurveTable.getParameterSpec(EllipticCurve.SECP256K1.name) - val ecNamedCurveSpec = ECNamedCurveSpec( - ecParameterSpec.getName(), - ecParameterSpec.getCurve(), - ecParameterSpec.getG(), - ecParameterSpec.getN() - ) - val ecPublicKeySpec = ECPublicKeySpec(java.security.spec.ECPoint(x.bigInteger, y.bigInteger), ecNamedCurveSpec) - keyFactory.generatePublic(ecPublicKeySpec).asInstanceOf[java.security.interfaces.ECPublicKey] - } - - override def verify(data: Array[Byte], signature: Array[Byte]): Try[Unit] = Try { - val sig = EC.INSTANCE.toSignatureFromBytes(signature) - EC.INSTANCE.verifyBytes(data, publicKey, sig) - }.flatMap(isValid => if (isValid) Success(()) else Failure(Exception("The signature verification does not match"))) - - override def hashCode(): Int = publicKey.getHexEncoded().hashCode() - - override def equals(x: Any): Boolean = { - x match { - case Prism14ECPublicKey(otherPK) => publicKey.getHexEncoded() == otherPK.getHexEncoded() - case _ => false - } - } - -} - -final case class Prism14ECPrivateKey(privateKey: io.iohk.atala.prism.crypto.keys.ECPrivateKey) extends ECPrivateKey { - - override def curve: EllipticCurve = EllipticCurve.SECP256K1 - - override def toJavaPrivateKey: java.security.interfaces.ECPrivateKey = { - val bytes = privateKey.getEncoded() - val keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider()) - val ecParameterSpec = ECNamedCurveTable.getParameterSpec(EllipticCurve.SECP256K1.name) - val ecNamedCurveSpec = ECNamedCurveSpec( - ecParameterSpec.getName(), - ecParameterSpec.getCurve(), - ecParameterSpec.getG(), - ecParameterSpec.getN() - ) - val ecPrivateKeySpec = ECPrivateKeySpec(java.math.BigInteger(1, bytes), ecNamedCurveSpec) - keyFactory.generatePrivate(ecPrivateKeySpec).asInstanceOf[java.security.interfaces.ECPrivateKey] - } - - override def encode: Array[Byte] = privateKey.getEncoded - - override def sign(data: Array[Byte]): Try[Array[Byte]] = - Try(EC.INSTANCE.signBytes(data, privateKey).getEncoded) - - override def computePublicKey: ECPublicKey = - Prism14ECPublicKey(EC.INSTANCE.toPublicKeyFromPrivateKey(privateKey)) - - override def hashCode(): Int = privateKey.getHexEncoded().hashCode() - - override def equals(x: Any): Boolean = { - x match { - case Prism14ECPrivateKey(otherPK) => privateKey.getHexEncoded() == otherPK.getHexEncoded() - case _ => false - } - } - -} - -// TODO: support operation of other key types -object Prism14ECKeyFactory extends ECKeyFactory { - - override def privateKeyFromEncoded(curve: EllipticCurve, bytes: Array[Byte]): Try[ECPrivateKey] = - curve match { - case EllipticCurve.SECP256K1 => - Try( - Prism14ECPrivateKey(EC.INSTANCE.toPrivateKeyFromBytes(bytes)) - ) - case crv => Failure(Exception(s"Operation on curve ${crv.name} is not yet supported")) - } - - override def publicKeyFromEncoded(curve: EllipticCurve, bytes: Array[Byte]): Try[ECPublicKey] = - curve match { - case EllipticCurve.SECP256K1 => - Try(EC.INSTANCE.toPublicKeyFromBytes(bytes)) - .orElse(Try(EC.INSTANCE.toPublicKeyFromCompressed(bytes))) - .map(Prism14ECPublicKey.apply) - case crv => Failure(Exception(s"Operation on curve ${crv.name} is not yet supported")) - } - - override def publicKeyFromCoordinate(curve: EllipticCurve, x: BigInt, y: BigInt): Try[ECPublicKey] = - curve match { - case EllipticCurve.SECP256K1 => - Try(Prism14ECPublicKey(EC.INSTANCE.toPublicKeyFromBigIntegerCoordinates(x.toKotlinBigInt, y.toKotlinBigInt))) - case crv => Failure(Exception(s"Operation on curve ${crv.name} is not yet supported")) - } - - override def generateKeyPair(curve: EllipticCurve): Task[ECKeyPair] = { - curve match { - case EllipticCurve.SECP256K1 => - ZIO.attempt { - val keyPair = EC.INSTANCE.generateKeyPair() - ECKeyPair(Prism14ECPublicKey(keyPair.getPublicKey), Prism14ECPrivateKey(keyPair.getPrivateKey)) - } - case crv => ZIO.fail(Exception(s"Operation on curve ${crv.name} is not yet supported")) - } - } - - override def deriveKeyPair(curve: EllipticCurve, seed: Array[Byte])(path: DerivationPath*): Task[ECKeyPair] = { - curve match { - case EllipticCurve.SECP256K1 => - ZIO.attempt { - val extendedKey = path - .foldLeft(KeyDerivation.INSTANCE.derivationRoot(seed)) { case (extendedKey, p) => - val axis = p match { - case DerivationPath.Hardened(i) => DerivationAxis.hardened(i) - case DerivationPath.Normal(i) => DerivationAxis.normal(i) - } - extendedKey.derive(axis) - } - val prism14KeyPair = extendedKey.keyPair() - ECKeyPair( - Prism14ECPublicKey(prism14KeyPair.getPublicKey()), - Prism14ECPrivateKey(prism14KeyPair.getPrivateKey()) - ) - } - case crv => ZIO.fail(Exception(s"Operation on curve ${crv.name} is not yet supported")) - } - } - - override def randomBip32Seed(): Task[(Array[Byte], Seq[String])] = ZIO.attempt { - val mnemonic = KeyDerivation.INSTANCE.randomMnemonicCode() - val words = mnemonic.getWords().asScala.toList - KeyDerivation.INSTANCE.binarySeed(mnemonic, "") -> words - } - -} - -object Prism14Apollo extends Apollo { - override def ecKeyFactory: ECKeyFactory = Prism14ECKeyFactory -} diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/KeyManagement.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/KeyManagement.scala index f2bd8f8d0e..4fce80980f 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/KeyManagement.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/KeyManagement.scala @@ -1,10 +1,10 @@ package io.iohk.atala.agent.walletapi.model -import io.iohk.atala.agent.walletapi.crypto.DerivationPath -import io.iohk.atala.agent.walletapi.crypto.ECKeyPair import io.iohk.atala.castor.core.model.did.InternalKeyPurpose import io.iohk.atala.castor.core.model.did.VerificationRelationship import io.iohk.atala.prism.crypto.Sha256 +import io.iohk.atala.shared.crypto.{DerivationPath, Secp256k1KeyPair as ECKeyPair} + import scala.collection.immutable.ArraySeq import scala.language.implicitConversions diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/CreateManagedDIDError.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/CreateManagedDIDError.scala index 57cbca9269..c2390f97ea 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/CreateManagedDIDError.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/CreateManagedDIDError.scala @@ -6,7 +6,6 @@ sealed trait CreateManagedDIDError extends Throwable object CreateManagedDIDError { final case class InvalidArgument(msg: String) extends CreateManagedDIDError - final case class KeyGenerationError(cause: Throwable) extends CreateManagedDIDError final case class WalletStorageError(cause: Throwable) extends CreateManagedDIDError final case class InvalidOperation(cause: castor.OperationValidationError) extends CreateManagedDIDError } diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/UpdateManagedDIDError.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/UpdateManagedDIDError.scala index 9dbef5410b..ba317f40db 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/UpdateManagedDIDError.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/model/error/UpdateManagedDIDError.scala @@ -10,7 +10,6 @@ object UpdateManagedDIDError { final case class DIDNotPublished(did: CanonicalPrismDID) extends UpdateManagedDIDError final case class DIDAlreadyDeactivated(did: CanonicalPrismDID) extends UpdateManagedDIDError final case class InvalidArgument(msg: String) extends UpdateManagedDIDError - final case class KeyGenerationError(cause: Throwable) extends UpdateManagedDIDError final case class WalletStorageError(cause: Throwable) extends UpdateManagedDIDError final case class OperationError(cause: castor.DIDOperationError) extends UpdateManagedDIDError final case class InvalidOperation(cause: castor.OperationValidationError) extends UpdateManagedDIDError diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceImpl.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceImpl.scala index 543c49f5b2..06910b6e50 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceImpl.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceImpl.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.service -import io.iohk.atala.agent.walletapi.crypto.Apollo import io.iohk.atala.agent.walletapi.model.* import io.iohk.atala.agent.walletapi.model.error.{*, given} import io.iohk.atala.agent.walletapi.service.ManagedDIDService.DEFAULT_MASTER_KEY_ID @@ -13,6 +12,7 @@ import io.iohk.atala.castor.core.service.DIDService import io.iohk.atala.castor.core.util.DIDOperationValidator import io.iohk.atala.mercury.PeerDID import io.iohk.atala.mercury.model.DidId +import io.iohk.atala.shared.crypto.Apollo import io.iohk.atala.shared.models.WalletAccessContext import zio.* diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceWithEventNotificationImpl.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceWithEventNotificationImpl.scala index 9b3237f3e8..b22b5da747 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceWithEventNotificationImpl.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceWithEventNotificationImpl.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.service -import io.iohk.atala.agent.walletapi.crypto.Apollo import io.iohk.atala.agent.walletapi.model.ManagedDIDDetail import io.iohk.atala.agent.walletapi.model.error.CommonWalletStorageError import io.iohk.atala.agent.walletapi.storage.WalletSecretStorage @@ -11,6 +10,7 @@ import io.iohk.atala.castor.core.model.error.DIDOperationError import io.iohk.atala.castor.core.service.DIDService import io.iohk.atala.castor.core.util.DIDOperationValidator import io.iohk.atala.event.notification.{Event, EventNotificationService} +import io.iohk.atala.shared.crypto.Apollo import io.iohk.atala.shared.models.WalletAccessContext import zio.* diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/MockManagedDIDService.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/MockManagedDIDService.scala index b582361454..58f5e4610f 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/MockManagedDIDService.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/MockManagedDIDService.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.service -import io.iohk.atala.agent.walletapi.crypto.{Prism14ECPrivateKey, Prism14ECPublicKey} import io.iohk.atala.agent.walletapi.model.* import io.iohk.atala.agent.walletapi.model.error.* import io.iohk.atala.agent.walletapi.storage.DIDNonSecretStorage @@ -12,7 +11,7 @@ import io.iohk.atala.castor.core.model.did.{ } import io.iohk.atala.mercury.PeerDID import io.iohk.atala.mercury.model.DidId -import io.iohk.atala.prism.crypto.keys.ECKeyPair +import io.iohk.atala.shared.crypto.Secp256k1KeyPair import zio.mock.* import zio.test.Assertion import zio.{mock, *} @@ -94,16 +93,11 @@ object MockManagedDIDService extends Mock[ManagedDIDService] { ) ) - def javaKeyPairWithDIDExpectation(ecKeyPair: ECKeyPair): Expectation[ManagedDIDService] = + def javaKeyPairWithDIDExpectation(ecKeyPair: Secp256k1KeyPair): Expectation[ManagedDIDService] = MockManagedDIDService.JavaKeyPairWithDID( assertion = Assertion.anything, result = Expectation.value( - Some( - ( - Prism14ECPrivateKey(ecKeyPair.getPrivateKey).toJavaPrivateKey, - Prism14ECPublicKey(ecKeyPair.getPublicKey).toJavaPublicKey - ) - ) + Some((ecKeyPair.privateKey.toJavaPrivateKey, ecKeyPair.publicKey.toJavaPublicKey)) ) ) } diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementService.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementService.scala index 2974a14393..3b7b9e47b0 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementService.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementService.scala @@ -17,7 +17,6 @@ sealed trait WalletManagementServiceError { } object WalletManagementServiceError { - final case class SeedGenerationError(cause: Throwable) extends WalletManagementServiceError final case class UnexpectedStorageError(cause: Throwable) extends WalletManagementServiceError final case class TooManyWebhookError(limit: Int, actual: Int) extends WalletManagementServiceError final case class DuplicatedWalletId(id: WalletId) extends WalletManagementServiceError @@ -32,7 +31,6 @@ object WalletManagementServiceError { } given Conversion[WalletManagementServiceError, Throwable] = { - case SeedGenerationError(cause) => Exception("Unable to generate wallet seed.", cause) case UnexpectedStorageError(cause) => Exception(cause) case TooManyWebhookError(limit, actual) => Exception(s"Too many webhook created for a wallet. Limit $limit, Actual $actual.") diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceImpl.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceImpl.scala index 94858f11e4..082178ac82 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceImpl.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceImpl.scala @@ -1,11 +1,11 @@ package io.iohk.atala.agent.walletapi.service -import io.iohk.atala.agent.walletapi.crypto.Apollo import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.model.WalletSeed import io.iohk.atala.agent.walletapi.storage.WalletNonSecretStorage import io.iohk.atala.agent.walletapi.storage.WalletSecretStorage import io.iohk.atala.event.notification.EventNotificationConfig +import io.iohk.atala.shared.crypto.Apollo import io.iohk.atala.shared.models.WalletAccessContext import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.WalletId @@ -32,11 +32,12 @@ class WalletManagementServiceImpl( ZIO.fail(WalletManagementServiceError.TooManyPermittedWallet()) } seed <- seed.fold( - apollo.ecKeyFactory - .randomBip32Seed() - .map(_._1) - .flatMap(bytes => ZIO.fromEither(WalletSeed.fromByteArray(bytes)).mapError(Exception(_))) - .mapError(WalletManagementServiceError.SeedGenerationError.apply) + apollo.secp256k1.randomBip32Seed + .flatMap { case (bytes, _) => + ZIO + .fromEither(WalletSeed.fromByteArray(bytes)) + .orDieWith(msg => Exception(s"Wallet seed generation failed: $msg")) + } )(ZIO.succeed) createdWallet <- nonSecretStorage .createWallet(wallet, seed.sha256Digest) diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDCreateHandler.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDCreateHandler.scala index 9b03f015f2..e21f2e02ad 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDCreateHandler.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDCreateHandler.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.service.handler -import io.iohk.atala.agent.walletapi.crypto.Apollo import io.iohk.atala.agent.walletapi.model.CreateDIDHdKey import io.iohk.atala.agent.walletapi.model.ManagedDIDState import io.iohk.atala.agent.walletapi.model.ManagedDIDTemplate @@ -11,6 +10,7 @@ import io.iohk.atala.agent.walletapi.storage.DIDNonSecretStorage import io.iohk.atala.agent.walletapi.storage.WalletSecretStorage import io.iohk.atala.agent.walletapi.util.OperationFactory import io.iohk.atala.castor.core.model.did.PrismDIDOperation +import io.iohk.atala.shared.crypto.Apollo import io.iohk.atala.shared.models.WalletAccessContext import zio.* diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDUpdateHandler.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDUpdateHandler.scala index 580137150f..93670fd857 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDUpdateHandler.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/DIDUpdateHandler.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.service.handler -import io.iohk.atala.agent.walletapi.crypto.Apollo import io.iohk.atala.agent.walletapi.model.DIDUpdateLineage import io.iohk.atala.agent.walletapi.model.KeyManagementMode import io.iohk.atala.agent.walletapi.model.ManagedDIDState @@ -16,6 +15,7 @@ import io.iohk.atala.castor.core.model.did.PrismDIDOperation import io.iohk.atala.castor.core.model.did.PrismDIDOperation.Update import io.iohk.atala.castor.core.model.did.ScheduledDIDOperationStatus import io.iohk.atala.castor.core.model.did.SignedPrismDIDOperation +import io.iohk.atala.shared.crypto.Apollo import io.iohk.atala.shared.models.WalletAccessContext import scala.collection.immutable.ArraySeq import zio.* diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/PublicationHandler.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/PublicationHandler.scala index 8c63b55ea5..debc2ff156 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/PublicationHandler.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/service/handler/PublicationHandler.scala @@ -28,8 +28,7 @@ class PublicationHandler(didService: DIDService, keyResolver: KeyResolver)(maste ZIO.die(Exception("master-key must exists in the wallet for signing DID operation and submit to Node")) ) signedOperation <- ZIO - .fromTry(masterKeyPair.privateKey.sign(operation.toAtalaOperation.toByteArray)) - .mapError[E](CommonCryptographyError.apply) + .succeed(masterKeyPair.privateKey.sign(operation.toAtalaOperation.toByteArray)) .map(signature => SignedPrismDIDOperation( operation = operation, diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/KeyResolver.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/KeyResolver.scala index 01ee234300..d5c02f9216 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/KeyResolver.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/KeyResolver.scala @@ -1,30 +1,33 @@ package io.iohk.atala.agent.walletapi.util -import io.iohk.atala.agent.walletapi.crypto.Apollo -import io.iohk.atala.agent.walletapi.crypto.ECKeyPair +import io.iohk.atala.shared.crypto.Apollo +import io.iohk.atala.shared.crypto.Secp256k1KeyPair import io.iohk.atala.agent.walletapi.model.KeyManagementMode import io.iohk.atala.agent.walletapi.model.ManagedDIDState import io.iohk.atala.agent.walletapi.model.WalletSeed import io.iohk.atala.agent.walletapi.storage.DIDNonSecretStorage import io.iohk.atala.agent.walletapi.storage.WalletSecretStorage -import io.iohk.atala.castor.core.model.did.EllipticCurve import io.iohk.atala.castor.core.model.did.PrismDID import io.iohk.atala.shared.models.WalletAccessContext import zio.* class KeyResolver(apollo: Apollo, nonSecretStorage: DIDNonSecretStorage, walletSecretStorage: WalletSecretStorage) { - def getKey(state: ManagedDIDState, keyId: String): RIO[WalletAccessContext, Option[ECKeyPair]] = { + def getKey(state: ManagedDIDState, keyId: String): RIO[WalletAccessContext, Option[Secp256k1KeyPair]] = { val did = state.createOperation.did getKey(did, state.keyMode, keyId) } - def getKey(did: PrismDID, keyMode: KeyManagementMode, keyId: String): RIO[WalletAccessContext, Option[ECKeyPair]] = { + def getKey( + did: PrismDID, + keyMode: KeyManagementMode, + keyId: String + ): RIO[WalletAccessContext, Option[Secp256k1KeyPair]] = { keyMode match { case KeyManagementMode.HD => resolveHdKey(did, keyId) } } - private def resolveHdKey(did: PrismDID, keyId: String): RIO[WalletAccessContext, Option[ECKeyPair]] = { + private def resolveHdKey(did: PrismDID, keyId: String): RIO[WalletAccessContext, Option[Secp256k1KeyPair]] = { for { maybeSeed <- walletSecretStorage.getWalletSeed maybeKeyPair <- maybeSeed.fold(ZIO.none) { seed => @@ -33,8 +36,8 @@ class KeyResolver(apollo: Apollo, nonSecretStorage: DIDNonSecretStorage, walletS .flatMap { case None => ZIO.none case Some(path) => - apollo.ecKeyFactory - .deriveKeyPair(EllipticCurve.SECP256K1, seed.toByteArray)(path.derivationPath: _*) + apollo.secp256k1 + .deriveKeyPair(seed.toByteArray)(path.derivationPath: _*) .asSome } } diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/OperationFactory.scala b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/OperationFactory.scala index a334edc7b7..883ea4b9a0 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/OperationFactory.scala +++ b/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/OperationFactory.scala @@ -1,6 +1,8 @@ package io.iohk.atala.agent.walletapi.util -import io.iohk.atala.agent.walletapi.crypto.{ECKeyPair, ECPublicKey} +import io.iohk.atala.agent.walletapi.model.HdKeyIndexCounter +import io.iohk.atala.agent.walletapi.model.ManagedDIDHdKeyPath +import io.iohk.atala.agent.walletapi.model.error.{CreateManagedDIDError, UpdateManagedDIDError} import io.iohk.atala.agent.walletapi.model.{ DIDPublicKeyTemplate, ManagedDIDTemplate, @@ -10,7 +12,7 @@ import io.iohk.atala.agent.walletapi.model.{ UpdateDIDHdKey, UpdateDIDRandKey } -import io.iohk.atala.agent.walletapi.model.error.{CreateManagedDIDError, UpdateManagedDIDError} +import io.iohk.atala.castor.core.model.did.EllipticCurve import io.iohk.atala.castor.core.model.did.{ CanonicalPrismDID, InternalKeyPurpose, @@ -20,14 +22,11 @@ import io.iohk.atala.castor.core.model.did.{ PublicKeyData, UpdateDIDAction } +import io.iohk.atala.shared.crypto.{Apollo, Secp256k1KeyPair as ECKeyPair, Secp256k1PublicKey as ECPublicKey} import io.iohk.atala.shared.models.Base64UrlString import zio.* import scala.collection.immutable.ArraySeq -import io.iohk.atala.agent.walletapi.model.HdKeyIndexCounter -import io.iohk.atala.agent.walletapi.crypto.Apollo -import io.iohk.atala.castor.core.model.did.EllipticCurve -import io.iohk.atala.agent.walletapi.model.ManagedDIDHdKeyPath private[util] final case class KeyDerivationOutcome[PK]( publicKey: PK, @@ -56,7 +55,7 @@ class OperationFactory(apollo: Apollo) { didTemplate: ManagedDIDTemplate ): IO[CreateManagedDIDError, (PrismDIDOperation.Create, CreateDIDHdKey)] = { val initKeysWithCounter = (Vector.empty[(PublicKey, ManagedDIDHdKeyPath)], HdKeyIndexCounter.zero(didIndex)) - val result = for { + for { keysWithCounter <- ZIO.foldLeft(didTemplate.publicKeys)(initKeysWithCounter) { case ((keys, keyCounter), template) => derivePublicKey(seed)(template, keyCounter) @@ -80,22 +79,20 @@ class OperationFactory(apollo: Apollo) { internalKeyPaths = Map(masterKeyOutcome.publicKey.id -> masterKeyOutcome.path), ) } yield operation -> hdKeys - - result.mapError(CreateManagedDIDError.KeyGenerationError.apply) } def makeCreateOperationRandKey( masterKeyId: String )(didTemplate: ManagedDIDTemplate): IO[CreateManagedDIDError, (PrismDIDOperation.Create, CreateDIDRandKey)] = { for { - randomSeed <- apollo.ecKeyFactory.randomBip32Seed().mapBoth(CreateManagedDIDError.KeyGenerationError.apply, _._1) + randomSeed <- apollo.secp256k1.randomBip32Seed.map(_._1) operationWithHdKey <- makeCreateOperationHdKey(masterKeyId, randomSeed)(0, didTemplate) (operation, hdKeys) = operationWithHdKey keyPairs <- ZIO.foreach(hdKeys.keyPaths) { case (id, path) => - deriveSecp256k1KeyPair(randomSeed, path).mapBoth(CreateManagedDIDError.KeyGenerationError.apply, id -> _) + deriveSecp256k1KeyPair(randomSeed, path).map(id -> _) } internalKeyPairs <- ZIO.foreach(hdKeys.internalKeyPaths) { case (id, path) => - deriveSecp256k1KeyPair(randomSeed, path).mapBoth(CreateManagedDIDError.KeyGenerationError.apply, id -> _) + deriveSecp256k1KeyPair(randomSeed, path).map(id -> _) } } yield operation -> CreateDIDRandKey( keyPairs = keyPairs, @@ -113,9 +110,8 @@ class OperationFactory(apollo: Apollo) { (Vector.empty[(UpdateManagedDIDAction, Option[(PublicKey, ManagedDIDHdKeyPath)])], fromKeyCounter) val actionsWithKeyMaterial = ZIO.foldLeft(actions)(initKeysWithCounter) { case ((acc, keyCounter), action) => val derivation = action match { - case UpdateManagedDIDAction.AddKey(template) => - derivePublicKey(seed)(template, keyCounter).mapError(UpdateManagedDIDError.KeyGenerationError.apply).asSome - case _ => ZIO.none + case UpdateManagedDIDAction.AddKey(template) => derivePublicKey(seed)(template, keyCounter).asSome + case _ => ZIO.none } derivation.map { case Some(outcome) => (acc :+ (action -> Some((outcome.publicKey, outcome.path))), outcome.nextCounter) @@ -152,7 +148,7 @@ class OperationFactory(apollo: Apollo) { actions: Seq[UpdateManagedDIDAction] ): IO[UpdateManagedDIDError, (PrismDIDOperation.Update, UpdateDIDRandKey)] = { for { - randomSeed <- apollo.ecKeyFactory.randomBip32Seed().mapBoth(UpdateManagedDIDError.KeyGenerationError.apply, _._1) + randomSeed <- apollo.secp256k1.randomBip32Seed.map(_._1) operationWithHdKey <- makeUpdateOperationHdKey(randomSeed)( did, previousOperationHash, @@ -161,7 +157,7 @@ class OperationFactory(apollo: Apollo) { ) (operation, hdKeys) = operationWithHdKey keyPairs <- ZIO.foreach(hdKeys.newKeyPaths) { case (id, path) => - deriveSecp256k1KeyPair(randomSeed, path).mapBoth(UpdateManagedDIDError.KeyGenerationError.apply, id -> _) + deriveSecp256k1KeyPair(randomSeed, path).map(id -> _) } } yield operation -> UpdateDIDRandKey(newKeyPairs = keyPairs) } @@ -190,7 +186,7 @@ class OperationFactory(apollo: Apollo) { private def derivePublicKey(seed: Array[Byte])( template: DIDPublicKeyTemplate, keyCounter: HdKeyIndexCounter - ): Task[KeyDerivationOutcome[PublicKey]] = { + ): UIO[KeyDerivationOutcome[PublicKey]] = { val purpose = template.purpose val keyPath = keyCounter.path(purpose) for { @@ -203,7 +199,7 @@ class OperationFactory(apollo: Apollo) { id: String, purpose: InternalKeyPurpose, keyCounter: HdKeyIndexCounter - ): Task[KeyDerivationOutcome[InternalPublicKey]] = { + ): UIO[KeyDerivationOutcome[InternalPublicKey]] = { val keyPath = keyCounter.path(purpose) for { keyPair <- deriveSecp256k1KeyPair(seed, keyPath) @@ -211,13 +207,12 @@ class OperationFactory(apollo: Apollo) { } yield KeyDerivationOutcome(internalPublicKey, keyPath, keyCounter.next(purpose)) } - private def deriveSecp256k1KeyPair(seed: Array[Byte], path: ManagedDIDHdKeyPath): Task[ECKeyPair] = { - apollo.ecKeyFactory.deriveKeyPair(EllipticCurve.SECP256K1, seed)(path.derivationPath: _*) - } + private def deriveSecp256k1KeyPair(seed: Array[Byte], path: ManagedDIDHdKeyPath): UIO[ECKeyPair] = + apollo.secp256k1.deriveKeyPair(seed)(path.derivationPath: _*) private def toPublicKeyData(publicKey: ECPublicKey): PublicKeyData = PublicKeyData.ECCompressedKeyData( - crv = publicKey.curve, - data = Base64UrlString.fromByteArray(publicKey.encode), + crv = EllipticCurve.SECP256K1, + data = Base64UrlString.fromByteArray(publicKey.getEncodedCompressed), ) } diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/benchmark/KeyDerivation.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/benchmark/KeyDerivation.scala index fa71d8db0e..dede81bd06 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/benchmark/KeyDerivation.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/benchmark/KeyDerivation.scala @@ -1,12 +1,10 @@ package io.iohk.atala.agent.walletapi.benchmark -import io.iohk.atala.agent.walletapi.crypto.Apollo -import io.iohk.atala.agent.walletapi.crypto.DerivationPath -import io.iohk.atala.agent.walletapi.crypto.ECKeyPair -import io.iohk.atala.agent.walletapi.crypto.ECPrivateKey import io.iohk.atala.agent.walletapi.vault.KVCodec import io.iohk.atala.agent.walletapi.vault.VaultKVClient -import io.iohk.atala.castor.core.model.did.EllipticCurve +import io.iohk.atala.shared.crypto.Apollo +import io.iohk.atala.shared.crypto.DerivationPath +import io.iohk.atala.shared.crypto.Secp256k1PrivateKey import io.iohk.atala.shared.models.Base64UrlString import io.iohk.atala.shared.models.HexString import io.iohk.atala.test.container.VaultTestContainerSupport @@ -19,15 +17,15 @@ object KeyDerivation extends ZIOSpecDefault, VaultTestContainerSupport { private val seedHex = "00" * 64 private val seed = HexString.fromStringUnsafe(seedHex).toByteArray - private def codec(apollo: Apollo): KVCodec[ECPrivateKey] = new { - override def encode(value: ECPrivateKey): Map[String, String] = { - val encodedKey = Base64UrlString.fromByteArray(value.encode).toString() + private def codec(apollo: Apollo): KVCodec[Secp256k1PrivateKey] = new { + override def encode(value: Secp256k1PrivateKey): Map[String, String] = { + val encodedKey = Base64UrlString.fromByteArray(value.getEncoded).toString() Map("value" -> encodedKey) } - override def decode(kv: Map[String, String]): Try[ECPrivateKey] = { + override def decode(kv: Map[String, String]): Try[Secp256k1PrivateKey] = { val encodedBytes = Base64UrlString.fromString(kv.get("value").get).toOption.get.toByteArray - apollo.ecKeyFactory.privateKeyFromEncoded(EllipticCurve.SECP256K1, encodedBytes) + apollo.secp256k1.privateKeyFromEncoded(encodedBytes) } } @@ -37,8 +35,8 @@ object KeyDerivation extends ZIOSpecDefault, VaultTestContainerSupport { } override def spec = suite("Key derivation benchmark")( - deriveKeyBenchmark.provide(Apollo.prism14Layer), - queryKeyBenchmark.provide(vaultKvClientLayer(), Apollo.prism14Layer) + deriveKeyBenchmark.provide(Apollo.layer), + queryKeyBenchmark.provide(vaultKvClientLayer(), Apollo.layer) ) @@ TestAspect.sequential @@ TestAspect.timed @@ TestAspect.tag("benchmark") @@ TestAspect.ignore private val deriveKeyBenchmark = suite("Key derivation benchmark")( @@ -62,8 +60,8 @@ object KeyDerivation extends ZIOSpecDefault, VaultTestContainerSupport { durationList <- ZIO .foreachPar(1 to 50_000) { i => Live.live { - apollo.ecKeyFactory - .deriveKeyPair(EllipticCurve.SECP256K1, seed)(derivationPath(keyIndex = i): _*) + apollo.secp256k1 + .deriveKeyPair(seed)(derivationPath(keyIndex = i): _*) .timed .map(_._1) } @@ -79,15 +77,15 @@ object KeyDerivation extends ZIOSpecDefault, VaultTestContainerSupport { for { vaultClient <- ZIO.service[VaultKVClient] apollo <- ZIO.service[Apollo] - keyPair <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) + keyPair <- apollo.secp256k1.generateKeyPair _ <- ZIO .foreach(1 to 50_000) { i => - given KVCodec[ECPrivateKey] = codec(apollo) + given KVCodec[Secp256k1PrivateKey] = codec(apollo) vaultClient.set(s"secret/did/prism/key-$i", keyPair.privateKey) } durationList <- ZIO .foreachPar(1 to 50_000) { i => - given KVCodec[ECPrivateKey] = codec(apollo) + given KVCodec[Secp256k1PrivateKey] = codec(apollo) Live.live { vaultClient.get(s"secret/did/prism/key-$i").timed.map(_._1) } } .withParallelism(parallelism) @@ -102,8 +100,7 @@ object KeyDerivation extends ZIOSpecDefault, VaultTestContainerSupport { apollo <- ZIO.service[Apollo] _ <- ZIO .foreach(1 to n) { i => - apollo.ecKeyFactory - .deriveKeyPair(EllipticCurve.SECP256K1, seed)(derivationPath(keyIndex = i): _*) + apollo.secp256k1.deriveKeyPair(seed)(derivationPath(keyIndex = i): _*) } } yield () } diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/crypto/ApolloSpecHelper.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/crypto/ApolloSpecHelper.scala deleted file mode 100644 index f66859fca6..0000000000 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/crypto/ApolloSpecHelper.scala +++ /dev/null @@ -1,8 +0,0 @@ -package io.iohk.atala.agent.walletapi.crypto - -import zio.* - -trait ApolloSpecHelper { - protected val apollo: Apollo = Prism14Apollo - protected val apolloLayer: ULayer[Apollo] = Apollo.prism14Layer -} diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceSpec.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceSpec.scala index 017b7928fa..8b987078b5 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceSpec.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/ManagedDIDServiceSpec.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.service -import io.iohk.atala.agent.walletapi.crypto.{Apollo, ApolloSpecHelper} import io.iohk.atala.agent.walletapi.model.* import io.iohk.atala.agent.walletapi.model.error.{ CreateManagedDIDError, @@ -15,7 +14,9 @@ import io.iohk.atala.castor.core.model.did.* import io.iohk.atala.castor.core.model.error import io.iohk.atala.castor.core.service.DIDService import io.iohk.atala.castor.core.util.DIDOperationValidator +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAccessContext +import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport import io.iohk.atala.test.container.{DBTestUtils, VaultTestContainerSupport} import zio.* @@ -23,7 +24,6 @@ import zio.test.* import zio.test.Assertion.* import scala.collection.immutable.ArraySeq -import io.iohk.atala.shared.models.WalletAdministrationContext object ManagedDIDServiceSpec extends ZIOSpecDefault, diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala index 5ae0beb1e9..60d18eed1c 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.service -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.model.WalletSeed import io.iohk.atala.agent.walletapi.service.WalletManagementServiceError.DuplicatedWalletSeed @@ -9,6 +8,7 @@ import io.iohk.atala.agent.walletapi.sql.JdbcWalletNonSecretStorage import io.iohk.atala.agent.walletapi.sql.JdbcWalletSecretStorage import io.iohk.atala.agent.walletapi.storage.WalletSecretStorage import io.iohk.atala.agent.walletapi.vault.VaultWalletSecretStorage +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAccessContext import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.WalletId diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/DIDSecretStorageSpec.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/DIDSecretStorageSpec.scala index 5bf81da6ce..3822e6f195 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/DIDSecretStorageSpec.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/DIDSecretStorageSpec.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.storage -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.memory.DIDSecretStorageInMemory import io.iohk.atala.agent.walletapi.memory.WalletSecretStorageInMemory import io.iohk.atala.agent.walletapi.model.Wallet @@ -13,13 +12,14 @@ import io.iohk.atala.agent.walletapi.sql.{ } import io.iohk.atala.agent.walletapi.vault.{VaultDIDSecretStorage, VaultWalletSecretStorage} import io.iohk.atala.mercury.PeerDID +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAccessContext +import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport import io.iohk.atala.test.container.{DBTestUtils, VaultTestContainerSupport} import zio.* import zio.test.* import zio.test.Assertion.* -import io.iohk.atala.shared.models.WalletAdministrationContext object DIDSecretStorageSpec extends ZIOSpecDefault, diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/GenericSecretStorageSpec.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/GenericSecretStorageSpec.scala index 87ac10110b..51a564d3e2 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/GenericSecretStorageSpec.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/GenericSecretStorageSpec.scala @@ -1,11 +1,11 @@ package io.iohk.atala.agent.walletapi.storage -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.memory.GenericSecretStorageInMemory import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.service.{WalletManagementService, WalletManagementServiceImpl} import io.iohk.atala.agent.walletapi.sql.{JdbcGenericSecretStorage, JdbcWalletNonSecretStorage, JdbcWalletSecretStorage} import io.iohk.atala.agent.walletapi.vault.{VaultGenericSecretStorage, VaultWalletSecretStorage} +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAccessContext import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport @@ -17,6 +17,7 @@ import zio.test.Assertion.* import java.util.UUID import scala.util.Try + object GenericSecretStorageSpec extends ZIOSpecDefault, StorageSpecHelper, diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/JdbcDIDNonSecretStorageSpec.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/JdbcDIDNonSecretStorageSpec.scala index f7c08b81f2..1762405ae2 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/JdbcDIDNonSecretStorageSpec.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/JdbcDIDNonSecretStorageSpec.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.storage -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.model.ManagedDIDState import io.iohk.atala.agent.walletapi.model.PublicationState import io.iohk.atala.agent.walletapi.service.WalletManagementService @@ -11,6 +10,7 @@ import io.iohk.atala.agent.walletapi.sql.JdbcWalletSecretStorage import io.iohk.atala.castor.core.model.did.PrismDID import io.iohk.atala.castor.core.model.did.PrismDIDOperation import io.iohk.atala.castor.core.model.did.ScheduledDIDOperationStatus +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAccessContext import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport import io.iohk.atala.test.container.DBTestUtils diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/StorageSpecHelper.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/StorageSpecHelper.scala index f7198664b0..e8ba0ffad5 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/StorageSpecHelper.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/storage/StorageSpecHelper.scala @@ -1,6 +1,5 @@ package io.iohk.atala.agent.walletapi.storage -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.model.DIDPublicKeyTemplate import io.iohk.atala.agent.walletapi.model.DIDUpdateLineage import io.iohk.atala.agent.walletapi.model.ManagedDIDState @@ -9,11 +8,11 @@ import io.iohk.atala.agent.walletapi.model.PublicationState import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.service.WalletManagementService import io.iohk.atala.agent.walletapi.util.OperationFactory -import io.iohk.atala.castor.core.model.did.EllipticCurve import io.iohk.atala.castor.core.model.did.PrismDID import io.iohk.atala.castor.core.model.did.PrismDIDOperation import io.iohk.atala.castor.core.model.did.ScheduledDIDOperationStatus import io.iohk.atala.castor.core.model.did.VerificationRelationship +import io.iohk.atala.shared.crypto.ApolloSpecHelper import io.iohk.atala.shared.models.WalletAccessContext import io.iohk.atala.shared.models.WalletAdministrationContext import zio.* @@ -38,7 +37,7 @@ trait StorageSpecHelper extends ApolloSpecHelper { updatedAt = Instant.EPOCH ) - protected def generateKeyPair() = apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) + protected def generateKeyPair() = apollo.secp256k1.generateKeyPair protected def generateCreateOperation(keyIds: Seq[String]) = OperationFactory(apollo).makeCreateOperationRandKey("master0")( diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/util/OperationFactorySpec.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/util/OperationFactorySpec.scala index 937cccbeb1..c68e1076f2 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/util/OperationFactorySpec.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/util/OperationFactorySpec.scala @@ -1,21 +1,12 @@ package io.iohk.atala.agent.walletapi.util +import io.iohk.atala.agent.walletapi.model.* +import io.iohk.atala.castor.core.model.did.* +import io.iohk.atala.shared.crypto.ApolloSpecHelper +import io.iohk.atala.shared.models.HexString import zio.* import zio.test.* import zio.test.Assertion.* -import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper -import io.iohk.atala.shared.models.HexString -import io.iohk.atala.agent.walletapi.model.ManagedDIDTemplate -import io.iohk.atala.castor.core.model.did.InternalPublicKey -import io.iohk.atala.castor.core.model.did.InternalKeyPurpose -import io.iohk.atala.agent.walletapi.model.DIDPublicKeyTemplate -import io.iohk.atala.castor.core.model.did.VerificationRelationship -import io.iohk.atala.castor.core.model.did.PrismDID -import io.iohk.atala.agent.walletapi.model.HdKeyIndexCounter -import io.iohk.atala.agent.walletapi.model.UpdateManagedDIDAction -import io.iohk.atala.castor.core.model.did.PrismDIDOperation -import io.iohk.atala.agent.walletapi.model.VerificationRelationshipCounter -import io.iohk.atala.castor.core.model.did.UpdateDIDAction object OperationFactorySpec extends ZIOSpecDefault, ApolloSpecHelper { diff --git a/shared/CHANGELOG.md b/shared/CHANGELOG.md deleted file mode 100644 index 99f505fb61..0000000000 --- a/shared/CHANGELOG.md +++ /dev/null @@ -1,23 +0,0 @@ -# [shared-v0.3.0](https://github.com/input-output-hk/atala-prism-building-blocks/compare/shared-v0.2.0...shared-v0.3.0) (2023-03-28) - - -### Features - -* add general test postgresql container support ([#481](https://github.com/input-output-hk/atala-prism-building-blocks/issues/481)) ([3b1fc8d](https://github.com/input-output-hk/atala-prism-building-blocks/commit/3b1fc8dda752bb81f5eeef31f24663ea58e0bf73)) -* **pollux:** implement Issue Credential v2 Protocol ([#144](https://github.com/input-output-hk/atala-prism-building-blocks/issues/144)) ([a80702f](https://github.com/input-output-hk/atala-prism-building-blocks/commit/a80702f5b255d8079085a6ec27c87baa6a23ac59)), closes [#92](https://github.com/input-output-hk/atala-prism-building-blocks/issues/92) - -# [shared-v0.2.0](https://github.com/input-output-hk/atala-prism-building-blocks/compare/shared-v0.1.0...shared-v0.2.0) (2022-11-21) - - -### Features - -* **shared:** add base64 helper function ([#135](https://github.com/input-output-hk/atala-prism-building-blocks/issues/135)) ([70555c9](https://github.com/input-output-hk/atala-prism-building-blocks/commit/70555c906121a7bc26e30c15dbf8f9d7721a100a)) - -# shared-v1.0.0 (2022-11-21) - - -### Features - -* define key-management interface (3) ([#71](https://github.com/input-output-hk/atala-prism-building-blocks/issues/71)) ([47dc3cd](https://github.com/input-output-hk/atala-prism-building-blocks/commit/47dc3cd8857971b96a88ae6f9cf0e2163e6cf08e)) -* **iris:** ATL-1791 Implement blockchain syncer functionality ([#49](https://github.com/input-output-hk/atala-prism-building-blocks/issues/49)) ([431b657](https://github.com/input-output-hk/atala-prism-building-blocks/commit/431b6575b8df2f4744285b1c5e2dd56072fa874c)) -* **shared:** add base64 helper function ([#135](https://github.com/input-output-hk/atala-prism-building-blocks/issues/135)) ([70555c9](https://github.com/input-output-hk/atala-prism-building-blocks/commit/70555c906121a7bc26e30c15dbf8f9d7721a100a)) diff --git a/shared/src/main/scala/io/iohk/atala/shared/db/ContextAwareTask.scala b/shared/core/src/main/scala/io/iohk/atala/shared/db/ContextAwareTask.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/db/ContextAwareTask.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/db/ContextAwareTask.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/db/DbConfig.scala b/shared/core/src/main/scala/io/iohk/atala/shared/db/DbConfig.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/db/DbConfig.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/db/DbConfig.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/db/TransactorLayer.scala b/shared/core/src/main/scala/io/iohk/atala/shared/db/TransactorLayer.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/db/TransactorLayer.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/db/TransactorLayer.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/http/GenericUriResolver.scala b/shared/core/src/main/scala/io/iohk/atala/shared/http/GenericUriResolver.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/http/GenericUriResolver.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/http/GenericUriResolver.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/models/Base64UrlString.scala b/shared/core/src/main/scala/io/iohk/atala/shared/models/Base64UrlString.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/models/Base64UrlString.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/models/Base64UrlString.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/models/Failure.scala b/shared/core/src/main/scala/io/iohk/atala/shared/models/Failure.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/models/Failure.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/models/Failure.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/models/HexString.scala b/shared/core/src/main/scala/io/iohk/atala/shared/models/HexString.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/models/HexString.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/models/HexString.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/models/MultiTenancy.scala b/shared/core/src/main/scala/io/iohk/atala/shared/models/MultiTenancy.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/models/MultiTenancy.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/models/MultiTenancy.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/Base64Utils.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/Base64Utils.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/Base64Utils.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/Base64Utils.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/BytesOps.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/BytesOps.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/BytesOps.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/BytesOps.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/DurationOps.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/DurationOps.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/DurationOps.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/DurationOps.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/Json.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/Json.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/Json.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/Json.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/Traverse.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/Traverse.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/Traverse.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/Traverse.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/aspects/CustomMetricsAspect.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/aspects/CustomMetricsAspect.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/aspects/CustomMetricsAspect.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/aspects/CustomMetricsAspect.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/proto/Path.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/proto/Path.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/proto/Path.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/proto/Path.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/proto/ValidationError.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/proto/ValidationError.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/proto/ValidationError.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/proto/ValidationError.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/utils/proto/package.scala b/shared/core/src/main/scala/io/iohk/atala/shared/utils/proto/package.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/utils/proto/package.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/utils/proto/package.scala diff --git a/shared/src/main/scala/io/iohk/atala/shared/validation/ValidationUtils.scala b/shared/core/src/main/scala/io/iohk/atala/shared/validation/ValidationUtils.scala similarity index 100% rename from shared/src/main/scala/io/iohk/atala/shared/validation/ValidationUtils.scala rename to shared/core/src/main/scala/io/iohk/atala/shared/validation/ValidationUtils.scala diff --git a/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/Apollo.scala b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/Apollo.scala new file mode 100644 index 0000000000..cea9f5da40 --- /dev/null +++ b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/Apollo.scala @@ -0,0 +1,142 @@ +package io.iohk.atala.shared.crypto + +import io.iohk.atala.shared.models.HexString +import org.bouncycastle.jce.ECNamedCurveTable +import org.bouncycastle.jce.provider.BouncyCastleProvider +import org.bouncycastle.jce.spec.ECNamedCurveSpec +import zio.* + +import java.security.KeyFactory +import java.security.spec.{ECPrivateKeySpec, ECPublicKeySpec} +import scala.util.Try + +trait Apollo { + def secp256k1: Secp256k1KeyOps + def ed25519: Ed25519KeyOps + def x25519: X25519KeyOps +} + +object Apollo { + def layer: ULayer[Apollo] = ZLayer.succeed(default) + + // TODO: migrate to KMP Apollo and support other key types + def default: Apollo = new { + override def secp256k1: Secp256k1KeyOps = Prism14Secp256k1Ops + override def ed25519: Ed25519KeyOps = ??? + override def x25519: X25519KeyOps = ??? + } +} + +trait Encodable { + def getEncoded: Array[Byte] +} + +trait Signable { + def sign(data: Array[Byte]): Array[Byte] +} + +trait Verifiable { + def verify(data: Array[Byte], signature: Array[Byte]): Try[Unit] +} + +trait PublicKey extends Encodable +trait PrivateKey extends Encodable { + type Pub <: PublicKey + def toPublicKey: Pub + override final def toString(): String = "" +} + +enum DerivationPath { + case Normal(i: Int) extends DerivationPath + case Hardened(i: Int) extends DerivationPath +} + +final case class ECPoint(x: BigInt, y: BigInt) + +// secp256k1 +final case class Secp256k1KeyPair(publicKey: Secp256k1PublicKey, privateKey: Secp256k1PrivateKey) +trait Secp256k1PublicKey extends PublicKey, Verifiable { + def getEncodedCompressed: Array[Byte] + + def getEncodedUncompressed: Array[Byte] + + def getECPoint: ECPoint + + override final def hashCode(): Int = HexString.fromByteArray(getEncoded).hashCode() + + override final def equals(x: Any): Boolean = x match { + case otherPK: Secp256k1PublicKey => + HexString.fromByteArray(this.getEncoded) == HexString.fromByteArray(otherPK.getEncoded) + case _ => false + } + + def toJavaPublicKey: java.security.interfaces.ECPublicKey = { + val point = getECPoint + val x = point.x + val y = point.y + val keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider()) + val ecParameterSpec = ECNamedCurveTable.getParameterSpec("secp256k1") + val ecNamedCurveSpec = ECNamedCurveSpec( + ecParameterSpec.getName(), + ecParameterSpec.getCurve(), + ecParameterSpec.getG(), + ecParameterSpec.getN() + ) + val ecPublicKeySpec = ECPublicKeySpec(java.security.spec.ECPoint(x.bigInteger, y.bigInteger), ecNamedCurveSpec) + keyFactory.generatePublic(ecPublicKeySpec).asInstanceOf[java.security.interfaces.ECPublicKey] + } +} +trait Secp256k1PrivateKey extends PrivateKey, Signable { + type Pub = Secp256k1PublicKey + + override final def hashCode(): Int = HexString.fromByteArray(getEncoded).hashCode() + + override final def equals(x: Any): Boolean = x match { + case otherPK: Secp256k1PrivateKey => + HexString.fromByteArray(this.getEncoded) == HexString.fromByteArray(otherPK.getEncoded) + case _ => false + } + + def toJavaPrivateKey: java.security.interfaces.ECPrivateKey = { + val bytes = getEncoded + val keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider()) + val ecParameterSpec = ECNamedCurveTable.getParameterSpec("secp256k1") + val ecNamedCurveSpec = ECNamedCurveSpec( + ecParameterSpec.getName(), + ecParameterSpec.getCurve(), + ecParameterSpec.getG(), + ecParameterSpec.getN() + ) + val ecPrivateKeySpec = ECPrivateKeySpec(java.math.BigInteger(1, bytes), ecNamedCurveSpec) + keyFactory.generatePrivate(ecPrivateKeySpec).asInstanceOf[java.security.interfaces.ECPrivateKey] + } +} +trait Secp256k1KeyOps { + def publicKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PublicKey] + def privateKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PrivateKey] + def generateKeyPair: UIO[Secp256k1KeyPair] + def randomBip32Seed: UIO[(Array[Byte], Seq[String])] + def deriveKeyPair(seed: Array[Byte])(path: DerivationPath*): UIO[Secp256k1KeyPair] +} + +// ed25519 +final case class Ed25519KeyPair(publicKey: Ed25519PublicKey, privateKey: Ed25519PrivateKey) +trait Ed25519PublicKey extends PublicKey +trait Ed25519PrivateKey extends PrivateKey, Signable { + type Pub = Ed25519PublicKey +} +trait Ed25519KeyOps { + def publicKeyFromEncoded(bytes: Array[Byte]): Try[Ed25519PublicKey] + def privateKeyFromEncoded(bytes: Array[Byte]): Try[Ed25519PrivateKey] +} + +// x25519 +final case class X25519KeyPair(publicKey: X25519PublicKey, privateKey: X25519PrivateKey) +trait X25519PublicKey extends PublicKey +trait X25519PrivateKey extends PrivateKey { + type Pub = X25519PublicKey +} +trait X25519KeyOps { + def publicKeyFromEncoded(bytes: Array[Byte]): Try[X25519PublicKey] + def privateKeyFromEncoded(bytes: Array[Byte]): Try[X25519PrivateKey] +} diff --git a/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/KmpApollo.scala b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/KmpApollo.scala new file mode 100644 index 0000000000..a5410add2f --- /dev/null +++ b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/KmpApollo.scala @@ -0,0 +1,97 @@ +package io.iohk.atala.shared.crypto + +import io.iohk.atala.prism.apollo.derivation +import io.iohk.atala.prism.apollo.derivation.MnemonicHelper +import io.iohk.atala.prism.apollo.secp256k1.Secp256k1Lib +import io.iohk.atala.prism.apollo.securerandom.SecureRandom +import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PrivateKey +import io.iohk.atala.prism.apollo.utils.KMMECSecp256k1PublicKey +import zio.* + +import scala.jdk.CollectionConverters.* +import scala.util.{Try, Success, Failure} + +final case class KmpSecp256k1PublicKey(publicKey: KMMECSecp256k1PublicKey) extends Secp256k1PublicKey { + + override def getECPoint: ECPoint = { + val point = publicKey.getCurvePoint() + val x = BigInt(1, point.getX()) + val y = BigInt(1, point.getY()) + ECPoint(x, y) + } + + override def getEncoded: Array[Byte] = publicKey.getCompressed() + + override def getEncodedCompressed: Array[Byte] = getEncoded + + override def getEncodedUncompressed: Array[Byte] = + KmpSecp256k1KeyOps.secpLib.uncompressPublicKey(getEncodedCompressed) + + override def verify(data: Array[Byte], signature: Array[Byte]): Try[Unit] = + Try(publicKey.verify(signature, data)) + .flatMap(isValid => if (isValid) Success(()) else Failure(Exception("The signature verification does not match"))) +} + +final case class KmpSecp256k1PrivateKey(privateKey: KMMECSecp256k1PrivateKey) extends Secp256k1PrivateKey { + override def sign(data: Array[Byte]): Array[Byte] = privateKey.sign(data) + + override def toPublicKey: Secp256k1PublicKey = KmpSecp256k1PublicKey(privateKey.getPublicKey()) + + override def getEncoded: Array[Byte] = privateKey.getEncoded() +} + +object KmpSecp256k1KeyOps extends Secp256k1KeyOps { + private[crypto] val secpLib: Secp256k1Lib = Secp256k1Lib() + private[crypto] val secureRandom: SecureRandom = SecureRandom() + + override def publicKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PublicKey] = + Try { + val publicKey = KMMECSecp256k1PublicKey.Companion.secp256k1FromBytes(bytes) + val point = publicKey.getCurvePoint() + val isOnCurve = KMMECSecp256k1PublicKey.Companion.isPointOnSecp256k1Curve(point) + if (isOnCurve) KmpSecp256k1PublicKey(publicKey) + else throw new Exception("The public key is not on the secp256k1 curve") + } + + override def privateKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PrivateKey] = + Try(KMMECSecp256k1PrivateKey.Companion.secp256k1FromByteArray(bytes)).map(KmpSecp256k1PrivateKey(_)) + + override def generateKeyPair: UIO[Secp256k1KeyPair] = + ZIO.attemptBlocking { + val randBytes = secureRandom.nextBytes(32) + val privateKey = KMMECSecp256k1PrivateKey(randBytes) + val publicKey = privateKey.getPublicKey + Secp256k1KeyPair( + KmpSecp256k1PublicKey(publicKey), + KmpSecp256k1PrivateKey(privateKey) + ) + }.orDie + + def randomBip32Seed: UIO[(Array[Byte], Seq[String])] = + ZIO.attemptBlocking { + val words = MnemonicHelper.Companion.createRandomMnemonics() + val seed = MnemonicHelper.Companion.createSeed(words, "") + seed -> words.asScala.toList + }.orDie + + def deriveKeyPair(seed: Array[Byte])(path: DerivationPath*): UIO[Secp256k1KeyPair] = + ZIO.attemptBlocking { + val pathStr = path + .foldLeft(derivation.DerivationPath.empty()) { case (path, p) => + p match { + case DerivationPath.Hardened(i) => path.derive(derivation.DerivationAxis.hardened(i)) + case DerivationPath.Normal(i) => path.derive(derivation.DerivationAxis.normal(i)) + } + } + .toString() + val hdKey = derivation.HDKey(seed, 0, 0).derive(pathStr) + val privateKey = hdKey.getKMMSecp256k1PrivateKey() + val publicKey = privateKey.getPublicKey() + + Secp256k1KeyPair( + KmpSecp256k1PublicKey(publicKey), + KmpSecp256k1PrivateKey(privateKey) + ) + }.orDie + +} diff --git a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/Prism14CompatUtil.scala b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/KmpCompatUtil.scala similarity index 84% rename from prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/Prism14CompatUtil.scala rename to shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/KmpCompatUtil.scala index 23cc8c9cb6..6cd6dbebb5 100644 --- a/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/util/Prism14CompatUtil.scala +++ b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/KmpCompatUtil.scala @@ -1,9 +1,9 @@ -package io.iohk.atala.agent.walletapi.util +package io.iohk.atala.shared.crypto import com.ionspin.kotlin.bignum.integer.BigInteger import com.ionspin.kotlin.bignum.integer.util.ConversionUtilsKt -object Prism14CompatUtil { +object KmpCompatUtil { extension (n: BigInteger) { def toScalaBigInt: BigInt = BigInt(ConversionUtilsKt.toTwosComplementByteArray(n)) diff --git a/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/Prism14Apollo.scala b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/Prism14Apollo.scala new file mode 100644 index 0000000000..a3b6a07e9c --- /dev/null +++ b/shared/crypto/src/main/scala/io/iohk/atala/shared/crypto/Prism14Apollo.scala @@ -0,0 +1,91 @@ +package io.iohk.atala.shared.crypto + +import io.iohk.atala.prism.crypto.EC +import io.iohk.atala.prism.crypto.derivation.DerivationAxis +import io.iohk.atala.prism.crypto.derivation.KeyDerivation +import zio.* + +import scala.jdk.CollectionConverters.* +import scala.util.{Try, Success, Failure} + +final case class Prism14Secp256k1PublicKey(publicKey: io.iohk.atala.prism.crypto.keys.ECPublicKey) + extends Secp256k1PublicKey { + + override def getEncoded: Array[Byte] = getEncodedCompressed + + override def getEncodedUncompressed: Array[Byte] = publicKey.getEncoded() + + override def getEncodedCompressed: Array[Byte] = publicKey.getEncodedCompressed() + + override def getECPoint: ECPoint = { + import KmpCompatUtil.* + val point = publicKey.getCurvePoint + val x = point.getX.getCoordinate.toScalaBigInt + val y = point.getY.getCoordinate.toScalaBigInt + ECPoint(x, y) + } + + override def verify(data: Array[Byte], signature: Array[Byte]): Try[Unit] = Try { + val sig = EC.INSTANCE.toSignatureFromBytes(signature) + EC.INSTANCE.verifyBytes(data, publicKey, sig) + }.flatMap(isValid => if (isValid) Success(()) else Failure(Exception("The signature verification does not match"))) + +} + +final case class Prism14Secp256k1PrivateKey(privateKey: io.iohk.atala.prism.crypto.keys.ECPrivateKey) + extends Secp256k1PrivateKey { + + override def toPublicKey: Secp256k1PublicKey = Prism14Secp256k1PublicKey( + EC.INSTANCE.toPublicKeyFromPrivateKey(privateKey) + ) + + override def getEncoded: Array[Byte] = privateKey.getEncoded() + + override def sign(data: Array[Byte]): Array[Byte] = EC.INSTANCE.signBytes(data, privateKey).getEncoded + +} + +object Prism14Secp256k1Ops extends Secp256k1KeyOps { + + override def generateKeyPair: UIO[Secp256k1KeyPair] = + ZIO.attemptBlocking { + val keyPair = EC.INSTANCE.generateKeyPair() + Secp256k1KeyPair( + Prism14Secp256k1PublicKey(keyPair.getPublicKey()), + Prism14Secp256k1PrivateKey(keyPair.getPrivateKey()), + ) + }.orDie + + override def privateKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PrivateKey] = + Try(Prism14Secp256k1PrivateKey(EC.INSTANCE.toPrivateKeyFromBytes(bytes))) + + override def publicKeyFromEncoded(bytes: Array[Byte]): Try[Secp256k1PublicKey] = + Try(EC.INSTANCE.toPublicKeyFromBytes(bytes)) + .orElse(Try(EC.INSTANCE.toPublicKeyFromCompressed(bytes))) + .map(Prism14Secp256k1PublicKey.apply) + + override def deriveKeyPair(seed: Array[Byte])(path: DerivationPath*): UIO[Secp256k1KeyPair] = + ZIO.attempt { + val extendedKey = path + .foldLeft(KeyDerivation.INSTANCE.derivationRoot(seed)) { case (extendedKey, p) => + val axis = p match { + case DerivationPath.Hardened(i) => DerivationAxis.hardened(i) + case DerivationPath.Normal(i) => DerivationAxis.normal(i) + } + extendedKey.derive(axis) + } + val prism14KeyPair = extendedKey.keyPair() + Secp256k1KeyPair( + Prism14Secp256k1PublicKey(prism14KeyPair.getPublicKey()), + Prism14Secp256k1PrivateKey(prism14KeyPair.getPrivateKey()) + ) + }.orDie + + override def randomBip32Seed: UIO[(Array[Byte], Seq[String])] = + ZIO.attemptBlocking { + val mnemonic = KeyDerivation.INSTANCE.randomMnemonicCode() + val words = mnemonic.getWords().asScala.toList + KeyDerivation.INSTANCE.binarySeed(mnemonic, "") -> words + }.orDie + +} diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/crypto/ApolloSpec.scala b/shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/ApolloSpec.scala similarity index 65% rename from prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/crypto/ApolloSpec.scala rename to shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/ApolloSpec.scala index d79f645d40..f02cff4c10 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/crypto/ApolloSpec.scala +++ b/shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/ApolloSpec.scala @@ -1,9 +1,8 @@ -package io.iohk.atala.agent.walletapi.crypto +package io.iohk.atala.shared.crypto import zio.* import zio.test.* import zio.test.Assertion.* -import io.iohk.atala.castor.core.model.did.EllipticCurve import io.iohk.atala.shared.models.HexString object ApolloSpec extends ZIOSpecDefault { @@ -12,19 +11,19 @@ object ApolloSpec extends ZIOSpecDefault { val tests = Seq( publicKeySpec, privateKeySpec, - ecKeyFactorySpec, - ecKeyFactoryBip32Spec + secp256k1Spec, + bip32Spec, ) - suite("Apollo - Prism14 implementation")(tests: _*).provideLayer(Apollo.prism14Layer) + suite("Apollo - KMP implementation")(tests: _*).provideLayer(Apollo.layer) } - private val publicKeySpec = suite("ECPublicKey")( + private val publicKeySpec = suite("Secp256k1PublicKey")( test("same public key bytes must be equal and have same hashCode") { for { apollo <- ZIO.service[Apollo] - keyPair <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) + keyPair <- apollo.secp256k1.generateKeyPair pk1 = keyPair.publicKey - pk2 = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, pk1.encode).get + pk2 = apollo.secp256k1.publicKeyFromEncoded(pk1.getEncoded).get } yield assert(pk1)(equalTo(pk2)) && assert(pk1 == pk2)(isTrue) && assert(pk1.hashCode())(equalTo(pk2.hashCode())) @@ -32,8 +31,8 @@ object ApolloSpec extends ZIOSpecDefault { test("different public key bytes must not be equal and have different hashCode") { for { apollo <- ZIO.service[Apollo] - keyPair1 <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) - keyPair2 <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) + keyPair1 <- apollo.secp256k1.generateKeyPair + keyPair2 <- apollo.secp256k1.generateKeyPair pk1 = keyPair1.publicKey pk2 = keyPair2.publicKey } yield assert(pk1)(not(equalTo(pk2))) && @@ -49,7 +48,7 @@ object ApolloSpec extends ZIOSpecDefault { val bytes = HexString.fromString(compressed).get.toByteArray for { apollo <- ZIO.service[Apollo] - pk = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get + pk = apollo.secp256k1.publicKeyFromEncoded(bytes).get javaPk = pk.toJavaPublicKey } yield assert(javaPk.getAlgorithm())(equalTo("EC")) && assert(javaPk.getW().getAffineX().toString())( @@ -58,37 +57,16 @@ object ApolloSpec extends ZIOSpecDefault { assert(javaPk.getW().getAffineY().toString())( equalTo("36684214325164537089180371592352190153822062261502257266280631050350493669941") ) - }, - test("sign a message and verify using public key") { - val message = BigInt("42").toByteArray - for { - apollo <- ZIO.service[Apollo] - keyPair <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) - privateKey = keyPair.privateKey - publicKey = privateKey.computePublicKey - signature = privateKey.sign(message).get - } yield assert(publicKey.verify(message, signature))(isSuccess) - }, - test("sign a message and verify using different public key should fail") { - val message = BigInt("42").toByteArray - for { - apollo <- ZIO.service[Apollo] - keyPair1 <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) - keyPair2 <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) - privateKey = keyPair1.privateKey - publicKey = keyPair2.publicKey - signature = privateKey.sign(message).get - } yield assert(publicKey.verify(message, signature))(isFailure) } ) - private val privateKeySpec = suite("ECPrivateKey")( + private val privateKeySpec = suite("Secp256k1PrivateKey")( test("same private key bytes must be equal and have same hashCode") { for { apollo <- ZIO.service[Apollo] - keyPair <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) + keyPair <- apollo.secp256k1.generateKeyPair pk1 = keyPair.privateKey - pk2 = apollo.ecKeyFactory.privateKeyFromEncoded(EllipticCurve.SECP256K1, pk1.encode).get + pk2 = apollo.secp256k1.privateKeyFromEncoded(pk1.getEncoded).get } yield assert(pk1)(equalTo(pk2)) && assert(pk1 == pk2)(isTrue) && assert(pk1.hashCode())(equalTo(pk2.hashCode())) @@ -96,8 +74,8 @@ object ApolloSpec extends ZIOSpecDefault { test("different private key bytes must not be equal and have different hashCode") { for { apollo <- ZIO.service[Apollo] - keyPair1 <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) - keyPair2 <- apollo.ecKeyFactory.generateKeyPair(EllipticCurve.SECP256K1) + keyPair1 <- apollo.secp256k1.generateKeyPair + keyPair2 <- apollo.secp256k1.generateKeyPair pk1 = keyPair1.privateKey pk2 = keyPair2.privateKey } yield assert(pk1)(not(equalTo(pk2))) && @@ -113,7 +91,7 @@ object ApolloSpec extends ZIOSpecDefault { val bytes = HexString.fromString(compressed).get.toByteArray for { apollo <- ZIO.service[Apollo] - pk = apollo.ecKeyFactory.privateKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get + pk = apollo.secp256k1.privateKeyFromEncoded(bytes).get javaPk = pk.toJavaPrivateKey } yield assert(javaPk.getAlgorithm())(equalTo("EC")) && assert(javaPk.getS().toByteArray())(equalTo(bytes)) @@ -127,8 +105,8 @@ object ApolloSpec extends ZIOSpecDefault { val bytes = HexString.fromString(compressed).get.toByteArray for { apollo <- ZIO.service[Apollo] - privateKey = apollo.ecKeyFactory.privateKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get - publicKey = privateKey.computePublicKey + privateKey = apollo.secp256k1.privateKeyFromEncoded(bytes).get + publicKey = privateKey.toPublicKey javaPk = publicKey.toJavaPublicKey } yield assert(javaPk.getAlgorithm())(equalTo("EC")) && assert(javaPk.getW().getAffineX().toString())( @@ -137,14 +115,45 @@ object ApolloSpec extends ZIOSpecDefault { assert(javaPk.getW().getAffineY().toString())( equalTo("36684214325164537089180371592352190153822062261502257266280631050350493669941") ) + }, + test("sign a message and verify using public key") { + val message = BigInt("42").toByteArray + for { + apollo <- ZIO.service[Apollo] + keyPair <- apollo.secp256k1.generateKeyPair + privateKey = keyPair.privateKey + publicKey = privateKey.toPublicKey + signature = privateKey.sign(message) + } yield assert(publicKey.verify(message, signature))(isSuccess) + }, + test("sign a message and verify using different public key should fail") { + val message = BigInt("42").toByteArray + for { + apollo <- ZIO.service[Apollo] + keyPair1 <- apollo.secp256k1.generateKeyPair + keyPair2 <- apollo.secp256k1.generateKeyPair + privateKey = keyPair1.privateKey + publicKey = keyPair2.publicKey + signature = privateKey.sign(message) + } yield assert(publicKey.verify(message, signature))(isFailure) + }, + test("sign the same message multiple time should produce different signature") { + val message = BigInt("42").toByteArray + for { + apollo <- ZIO.service[Apollo] + keyPair <- apollo.secp256k1.generateKeyPair + privateKey = keyPair.privateKey + signature1 = privateKey.sign(message) + signature2 = privateKey.sign(message) + } yield assert(signature1)(not(equalTo(signature2))) } ) - private val ecKeyFactorySpec = suite("ECKeyFactory")( + private val secp256k1Spec = suite("Secp256k1Ops")( test("decode invalid public key should fail") { for { apollo <- ZIO.service[Apollo] - decodeResult = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, Array.emptyByteArray) + decodeResult = apollo.secp256k1.publicKeyFromEncoded(Array.emptyByteArray) } yield assert(decodeResult)(isFailure) }, test("decode valid uncompressed secp256k1 public key successfully") { @@ -157,7 +166,7 @@ object ApolloSpec extends ZIOSpecDefault { val bytes = HexString.fromString(uncompressed).get.toByteArray for { apollo <- ZIO.service[Apollo] - _ = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get + _ = apollo.secp256k1.publicKeyFromEncoded(bytes).get } yield assertCompletes }, test("decode valid compressed secp256k1 public key successfully (even)") { @@ -169,7 +178,7 @@ object ApolloSpec extends ZIOSpecDefault { val bytes = HexString.fromString(compressed).get.toByteArray for { apollo <- ZIO.service[Apollo] - _ = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get + _ = apollo.secp256k1.publicKeyFromEncoded(bytes).get } yield assertCompletes }, test("decode valid compressed secp256k1 public key successfully (odd)") { @@ -181,28 +190,9 @@ object ApolloSpec extends ZIOSpecDefault { val bytes = HexString.fromString(compressed).get.toByteArray for { apollo <- ZIO.service[Apollo] - _ = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get + _ = apollo.secp256k1.publicKeyFromEncoded(bytes).get } yield assertCompletes }, - test("decode public key yield same result as giving EC point") { - // priv: 0x2789649b57d8f5df144a817f660b494e7a86d465ba86a638a2b525884c5c5849 - // pub: 0x037b7e17f0524db221af0dd74bd21dec2fc6d0955bbfd43ec7d96ca61dbee2d9d1 - // x: 55857268325124588620525700020439091507381445732605907422424441486941792426449 - // y: 36684214325164537089180371592352190153822062261502257266280631050350493669941 - val compressed = "037b7e17f0524db221af0dd74bd21dec2fc6d0955bbfd43ec7d96ca61dbee2d9d1" - val bytes = HexString.fromString(compressed).get.toByteArray - for { - apollo <- ZIO.service[Apollo] - pk1 = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get - pk2 = apollo.ecKeyFactory - .publicKeyFromCoordinate( - EllipticCurve.SECP256K1, - BigInt("55857268325124588620525700020439091507381445732605907422424441486941792426449"), - BigInt("36684214325164537089180371592352190153822062261502257266280631050350493669941") - ) - .get - } yield assert(pk1)(equalTo(pk2)) - }, test("decode compressed and uncompressed of the same key") { // priv: 0xe005dfce415d0ff46485fa37a0f035cf02fedf4b611248eb851a6b563dcf61ed // pub: 0x0236e35f02c325a0cdc3c98968ca5cd51601b0fd8a6e29de4dd73bf0415987bd68 @@ -216,14 +206,20 @@ object ApolloSpec extends ZIOSpecDefault { val bytes2 = HexString.fromString(uncompressed).get.toByteArray for { apollo <- ZIO.service[Apollo] - pk1 = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, bytes).get - pk2 = apollo.ecKeyFactory.publicKeyFromEncoded(EllipticCurve.SECP256K1, bytes2).get + pk1 = apollo.secp256k1.publicKeyFromEncoded(bytes).get + pk2 = apollo.secp256k1.publicKeyFromEncoded(bytes2).get } yield assert(pk1)(equalTo(pk2)) } ) + // TODO: Uncomment tests when KMP apollo supports BIP32 fully + // KMP apollo only supports hardened derivation path + // https://github.com/input-output-hk/atala-prism-apollo/blob/4b9b2079690093f25922da1f660c27ffcb718c08/apollo/src/commonMain/kotlin/io/iohk/atala/prism/apollo/derivation/HDKey.kt#L176 + // 1. tests with normal path are commented out + // 2. TestVector1 is skipped since KMP apollo only accepts 64 bytes seed + // // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vectors - private val ecKeyFactoryBip32Spec = { + private val bip32Spec = { def assertHDKey(seedHex: String)(pathStr: String, expectedPrivateKeyHex: String) = { val path = pathStr .drop(1) @@ -238,14 +234,14 @@ object ApolloSpec extends ZIOSpecDefault { val seed = HexString.fromStringUnsafe(seedHex).toByteArray for { apollo <- ZIO.service[Apollo] - keyPair <- apollo.ecKeyFactory.deriveKeyPair(EllipticCurve.SECP256K1, seed)(path: _*) - } yield assert(keyPair.privateKey.encode)( + keyPair <- apollo.secp256k1.deriveKeyPair(seed)(path: _*) + } yield assert(keyPair.privateKey.getEncoded)( equalTo(HexString.fromStringUnsafe(expectedPrivateKeyHex).toByteArray) ) } } - val testVector1 = assertHDKey("000102030405060708090a0b0c0d0e0f") + // val testVector1 = assertHDKey("000102030405060708090a0b0c0d0e0f") val testVector2 = assertHDKey( "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542" ) @@ -253,58 +249,58 @@ object ApolloSpec extends ZIOSpecDefault { "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be" ) - suite("ECKeyFactory - BIP32")( - suite("Test vector 1")( - testVector1( - "m", - "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35" - ), - testVector1( - "m/0'", - "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea" - ), - testVector1( - "m/0'/1", - "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368" - ), - testVector1( - "m/0'/1/2'", - "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca" - ), - testVector1( - "m/0'/1/2'/2", - "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4" - ), - testVector1( - "m/0'/1/2'/2/1000000000", - "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8" - ), - ), + suite("secp256k1 - BIP32")( + // suite("Test vector 1")( + // testVector1( + // "m", + // "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35" + // ), + // testVector1( + // "m/0'", + // "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea" + // ), + // testVector1( + // "m/0'/1", + // "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368" + // ), + // testVector1( + // "m/0'/1/2'", + // "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca" + // ), + // testVector1( + // "m/0'/1/2'/2", + // "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4" + // ), + // testVector1( + // "m/0'/1/2'/2/1000000000", + // "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8" + // ), + // ), suite("Test vector 2")( testVector2( "m", "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e" ), - testVector2( - "m/0", - "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e" - ), - testVector2( - "m/0/2147483647'", - "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93" - ), - testVector2( - "m/0/2147483647'/1", - "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7" - ), - testVector2( - "m/0/2147483647'/1/2147483646'", - "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d" - ), - testVector2( - "m/0/2147483647'/1/2147483646'/2", - "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23" - ), + // testVector2( + // "m/0", + // "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e" + // ), + // testVector2( + // "m/0/2147483647'", + // "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93" + // ), + // testVector2( + // "m/0/2147483647'/1", + // "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7" + // ), + // testVector2( + // "m/0/2147483647'/1/2147483646'", + // "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d" + // ), + // testVector2( + // "m/0/2147483647'/1/2147483646'/2", + // "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23" + // ), ), suite("Test vector 3")( testVector3( diff --git a/shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/ApolloSpecHelper.scala b/shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/ApolloSpecHelper.scala new file mode 100644 index 0000000000..98e278a6dc --- /dev/null +++ b/shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/ApolloSpecHelper.scala @@ -0,0 +1,8 @@ +package io.iohk.atala.shared.crypto + +import zio.* + +trait ApolloSpecHelper { + protected val apollo: Apollo = Apollo.default + protected val apolloLayer: ULayer[Apollo] = Apollo.layer +} diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/util/Prism14CompatUtilSpec.scala b/shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/KmpCompatUtilSpec.scala similarity index 80% rename from prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/util/Prism14CompatUtilSpec.scala rename to shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/KmpCompatUtilSpec.scala index e3e5b5245f..c786b92414 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/util/Prism14CompatUtilSpec.scala +++ b/shared/crypto/src/test/scala/io/iohk/atala/shared/crypto/KmpCompatUtilSpec.scala @@ -1,14 +1,15 @@ -package io.iohk.atala.agent.walletapi.util +package io.iohk.atala.shared.crypto import com.ionspin.kotlin.bignum.integer.BigInteger -import io.iohk.atala.agent.walletapi.util.Prism14CompatUtil.* import zio.* import zio.test.* import zio.test.Assertion.* -object Prism14CompatUtilSpec extends ZIOSpecDefault { +object KmpCompatUtilSpec extends ZIOSpecDefault { - override def spec = suite("Prism14CompatUtil")( + import KmpCompatUtil.* + + override def spec = suite("KmpCompatUtil")( test("scala to kotlin and back for zero") { val bigInt1 = BigInt(0) val bigInt2 = bigInt1.toKotlinBigInt.toScalaBigInt diff --git a/shared/src/main/scala/io/iohk/atala/shared/HashValue.scala b/shared/src/main/scala/io/iohk/atala/shared/HashValue.scala deleted file mode 100644 index 18db7f310b..0000000000 --- a/shared/src/main/scala/io/iohk/atala/shared/HashValue.scala +++ /dev/null @@ -1,58 +0,0 @@ -package io.iohk.atala.shared - -import java.util.Locale -import com.typesafe.config.ConfigMemorySize -import io.iohk.atala.shared.utils.BytesOps - -import scala.collection.immutable.ArraySeq -import scala.util.matching.Regex - -trait HashValue extends Any { - - def value: ArraySeq[Byte] - - override def toString: String = { - BytesOps.bytesToHex(value) - } - - override def equals(obj: Any): Boolean = { - if (obj == null || obj.getClass != this.getClass) - return false - - value.equals(obj.asInstanceOf[HashValue].value) - } -} - -trait HashValueFrom[A] { - protected val config: HashValueConfig - - protected def constructor(value: ArraySeq[Byte]): A - - def from(string: String): Option[A] = { - val lowercaseString = string.toLowerCase(Locale.ROOT) - - lowercaseString match { - case config.HexPattern() => - val bytes = lowercaseString - .grouped(2) - .toList - .map { hex => - Integer.parseInt(hex, 16).asInstanceOf[Byte] - } - Some(constructor(ArraySeq.from(bytes))) - case _ => None - } - } - - def from(bytes: Iterable[Byte]): Option[A] = { - if (bytes.size == config.size.toBytes) { - Some(constructor(ArraySeq.from(bytes))) - } else { - None - } - } -} - -case class HashValueConfig(size: ConfigMemorySize) { - private[shared] val HexPattern: Regex = s"^[a-f0-9]{${2 * size.toBytes}}$$".r -} diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakContainerCustom.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakContainerCustom.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakContainerCustom.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakContainerCustom.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainer.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainer.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainer.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainer.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupport.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupport.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupport.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupport.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupportSpec.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupportSpec.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupportSpec.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/KeycloakTestContainerSupportSpec.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgreSQLContainerCustom.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgreSQLContainerCustom.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgreSQLContainerCustom.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgreSQLContainerCustom.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresLayer.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresLayer.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresLayer.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresLayer.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainer.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainer.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainer.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainer.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainerSupport.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainerSupport.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainerSupport.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/PostgresTestContainerSupport.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultContainerCustom.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultContainerCustom.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultContainerCustom.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultContainerCustom.scala diff --git a/shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultTestContainer.scala b/shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultTestContainer.scala similarity index 100% rename from shared-test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultTestContainer.scala rename to shared/test/src/test/scala/io/iohk/atala/sharedtest/containers/VaultTestContainer.scala