Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: add shared-crypto module and apollo wrapper for other key types #958

Merged
merged 2 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 50 additions & 33 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ lazy val V = new {
val jwtCirceVersion = "9.1.2"
val zioPreludeVersion = "1.0.0-RC16"

val apollo = "1.2.14"
val bouncyCastle = "1.70"

val jsonSchemaValidator = "1.3.2"
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that you've replaced some usages of old SDK crypto with apollo, like for example in MockDidService, do you know how close we are from removing the dependency on old SDK crypto altogether?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually not that far :). Just a few places still using old EC, Sha256 and MerkleProof classes. We can gradually get rid of it and use a shared interface, just have to wait for apollo upgrade before dropping old lib.

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)
Expand All @@ -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(
Expand Down Expand Up @@ -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(
Expand All @@ -235,7 +252,6 @@ lazy val D_Castor = new {
D.zioMock,
D.zioTestSbt,
D.zioTestMagnolia,
prismIdentity,
)

// Project Dependencies
Expand All @@ -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,
Expand All @@ -276,7 +285,7 @@ lazy val D_Pollux = new {
D.zioMock,
D.munit,
D.munitZio,
prismCrypto,
D.prismCrypto,
// shared,
logback,
slf4jApi,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 ###
Expand Down Expand Up @@ -711,6 +720,7 @@ lazy val castorCore = project
libraryDependencies ++= D_Castor.coreDependencies
)
.dependsOn(shared, prismNodeClient)
.dependsOn(sharedCrypto % "compile->compile;test->test")

// #####################
// ##### pollux ######
Expand Down Expand Up @@ -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"))
Expand All @@ -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"),
Expand Down Expand Up @@ -880,6 +896,7 @@ releaseProcess := Seq[ReleaseStep](

lazy val aggregatedProjects: Seq[ProjectReference] = Seq(
shared,
sharedCrypto,
sharedTest,
models,
protocolConnection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -40,25 +44,31 @@ 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(
id = "master-0",
purpose = InternalKeyPurpose.Master,
publicKeyData = PublicKeyData.ECCompressedKeyData(
crv = EllipticCurve.SECP256K1,
data = Base64UrlString.fromByteArray(masterKeyPair.getPublicKey.getEncodedCompressed)
data = Base64UrlString.fromByteArray(masterKeyPair.publicKey.getEncodedCompressed)
)
),
PublicKey(
id = "key-0",
purpose = verificationRelationship,
publicKeyData = PublicKeyData.ECCompressedKeyData(
crv = EllipticCurve.SECP256K1,
data = Base64UrlString.fromByteArray(keyPair.getPublicKey.getEncodedCompressed)
data = Base64UrlString.fromByteArray(keyPair.publicKey.getEncodedCompressed)
)
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading
Loading