Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into docs/connectionless-p…
Browse files Browse the repository at this point in the history
…roof

Signed-off-by: mixmix <[email protected]>
  • Loading branch information
mixmix committed Nov 21, 2024
2 parents b5efc5f + 8781d3d commit c200931
Show file tree
Hide file tree
Showing 46 changed files with 716 additions and 414 deletions.
3 changes: 2 additions & 1 deletion .mega-linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ DISABLE_LINTERS:
- PYTHON_MYPY
- PYTHON_PYRIGHT
- PYTHON_RUFF
- TYPESCRIPT_STANDARD

DISABLE_ERRORS_LINTERS:
- KOTLIN_KTLINT
Expand Down Expand Up @@ -65,5 +66,5 @@ YAML_PRETTIER_FILTER_REGEX_EXCLUDE: "infrastructure/charts/agent/*|cloud-agent/s
YAML_V8R_FILTER_REGEX_EXCLUDE: "infrastructure/charts/agent/*"
JAVASCRIPT_STANDARD_FILTER_REGEX_EXCLUDE:
"tests/performance-tests/agent-performance-tests-k6/src/k6chaijs.js\
|tests/didcomm-tests/docker/initdb.js"
|tests/performance-tests/agent-performance-tests-k6/src/common/ProofsService.ts|tests/didcomm-tests/docker/initdb.js"
BASH_SHELLCHECK_FILTER_REGEX_EXCLUDE: "infrastructure/*"
3 changes: 3 additions & 0 deletions cloud-agent/service/server/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
<logger name="io.getquill" level="WARN">
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.apache.kafka.clients" level="WARN">
<appender-ref ref="STDOUT" />
</logger>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import org.hyperledger.identus.mercury.model.*
import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation
import org.hyperledger.identus.mercury.protocol.presentproof.*
import org.hyperledger.identus.mercury.protocol.reportproblem.v2.{ProblemCode, ReportProblem}
import org.hyperledger.identus.pollux.core.model.*
import org.hyperledger.identus.pollux.core.model.{presentation, *}
import org.hyperledger.identus.pollux.core.model.error.{CredentialServiceError, PresentationError}
import org.hyperledger.identus.pollux.core.model.error.PresentationError.*
import org.hyperledger.identus.pollux.core.model.presentation.Options
import org.hyperledger.identus.pollux.core.service.{CredentialService, PresentationService}
import org.hyperledger.identus.pollux.core.service.serdes.AnoncredCredentialProofsV1
import org.hyperledger.identus.pollux.sdjwt.{HolderPrivateKey, IssuerPublicKey, PresentationCompact, SDJWT}
import org.hyperledger.identus.pollux.vc.jwt.{DidResolver as JwtDidResolver, Issuer as JwtIssuer, JWT, JwtPresentation}
import org.hyperledger.identus.pollux.vc.jwt.CredentialSchemaAndTrustedIssuersConstraint
import org.hyperledger.identus.resolvers.DIDResolver
import org.hyperledger.identus.shared.http.*
import org.hyperledger.identus.shared.messaging
Expand All @@ -37,7 +38,7 @@ import org.hyperledger.identus.shared.utils.aspects.CustomMetricsAspect
import org.hyperledger.identus.shared.utils.DurationOps.toMetricsSeconds
import zio.*
import zio.metrics.*
import zio.prelude.Validation
import zio.prelude.{Validation, ZValidation}
import zio.prelude.ZValidation.{Failure as ZFailure, *}

import java.time.{Instant, ZoneId}
Expand Down Expand Up @@ -947,7 +948,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {

object Verifier {

def handleRequestPending(id: DidCommID, record: RequestPresentation): ZIO[
def handleRequestPending(id: DidCommID, requestPresentation: RequestPresentation): ZIO[
JwtDidResolver & COMMON_RESOURCES & MESSAGING_RESOURCES,
Failure,
Unit
Expand Down Expand Up @@ -978,17 +979,20 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {

val verifierReqPendingToSentFlow = for {
_ <- ZIO.log(s"PresentationRecord: RequestPending (Send Message)")
walletAccessContext <- buildWalletAccessContextLayer(
record.from.getOrElse(throw new RuntimeException("from is None is not possible"))
)
walletAccessContext <- ZIO
.fromOption(requestPresentation.from)
.mapError(_ => RequestPresentationMissingField(id.value, "sender"))
.flatMap(buildWalletAccessContextLayer)

result <- for {
didOps <- ZIO.service[DidOps]
didCommAgent <- buildDIDCommAgent(
record.from.getOrElse(throw new RuntimeException("from is None is not possible"))
).provideSomeLayer(ZLayer.succeed(walletAccessContext))
didCommAgent <- ZIO
.fromOption(requestPresentation.from)
.mapError(_ => RequestPresentationMissingField(id.value, "sender"))
.flatMap(buildDIDCommAgent(_).provideSomeLayer(ZLayer.succeed(walletAccessContext)))
resp <-
MessagingService
.send(record.makeMessage)
.send(requestPresentation.makeMessage)
.provideSomeLayer(didCommAgent)
@@ Metric
.gauge("present_proof_flow_verifier_send_presentation_request_msg_ms_gauge")
Expand Down Expand Up @@ -1069,6 +1073,16 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
}
}

private def buildReportProblem(presentation: Presentation, error: String): ReportProblem = {
ReportProblem.build(
fromDID = presentation.to,
toDID = presentation.from,
pthid = presentation.thid.getOrElse(presentation.id),
code = ProblemCode("e.p.presentation-verification-failed"),
comment = Some(error)
)
}

private def handleJWT(
id: DidCommID,
requestPresentation: RequestPresentation,
Expand All @@ -1085,7 +1099,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
_ <- checkInvitationExpiry(id, invitation).provideSomeLayer(ZLayer.succeed(walletAccessContext))
result <- for {
didResolverService <- ZIO.service[JwtDidResolver]
credentialsClaimsValidationResult <- presentation.attachments.head.data match {
claimsValidationResult <- presentation.attachments.head.data match {
case Base64(data) =>
val base64Decoded = new String(java.util.Base64.getUrlDecoder.decode(data))
val maybePresentationOptions: Either[PresentationError, Option[Options]] =
Expand All @@ -1103,36 +1117,55 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
)
)
.getOrElse(Right(None))
val schemaIdAndTrustedIssuers = requestPresentation.body.proof_types.map { proofType =>
CredentialSchemaAndTrustedIssuersConstraint(
proofType.schema,
proofType.trustIssuers.map(_.map(_.value))
)
}

val presentationClaimsValidationResult = for {
_ <- ZIO.fromEither(maybePresentationOptions.map {
validationResult: Validation[String, Unit] <- ZIO.fromEither(maybePresentationOptions.map {
case Some(options) =>
JwtPresentation.validatePresentation(
JWT(base64Decoded),
options.domain,
options.challenge
)
case _ => Validation.unit
JwtPresentation
.validatePresentation(
JWT(base64Decoded),
Some(options.domain),
Some(options.challenge),
schemaIdAndTrustedIssuers
)
case _ =>
JwtPresentation
.validatePresentation(
JWT(base64Decoded),
None,
None,
schemaIdAndTrustedIssuers
)
})

verificationConfig <- ZIO.service[AppConfig].map(_.agent.verification)
_ <- ZIO.log(s"VerificationConfig: ${verificationConfig}")

// https://www.w3.org/TR/vc-data-model/#proofs-signatures-0
// A proof is typically attached to a verifiable presentation for authentication purposes
// and to a verifiable credential as a method of assertion.
uriResolver <- ZIO.service[UriResolver]
result <- JwtPresentation
result: Validation[String, Unit] <- JwtPresentation
.verify(
JWT(base64Decoded),
verificationConfig.toPresentationVerificationOptions()
)(didResolverService, uriResolver)(clock)
.mapError(error => PresentationError.PresentationVerificationError(error.mkString))
} yield result

} yield Seq(validationResult, result)
presentationClaimsValidationResult

case any => ZIO.fail(PresentationReceivedError("Only Base64 Supported"))
}
credentialsClaimsValidationResult = ZValidation
.validateAll(claimsValidationResult)
.map(_ => ())
_ <- credentialsClaimsValidationResult match
case l @ ZFailure(_, _) => ZIO.logError(s"CredentialsClaimsValidationResult: $l")
case l @ Success(_, _) => ZIO.logInfo(s"CredentialsClaimsValidationResult: $l")
Expand All @@ -1151,19 +1184,13 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
_ <- service
.markPresentationVerificationFailed(id)
.provideSomeLayer(ZLayer.succeed(walletAccessContext)) @@ presReceivedToProcessedAspect
didCommAgent <- buildDIDCommAgent(presentation.from).provideSomeLayer(
didCommAgent <- buildDIDCommAgent(presentation.to).provideSomeLayer(
ZLayer.succeed(walletAccessContext)
)
reportproblem = ReportProblem.build(
fromDID = presentation.to,
toDID = presentation.from,
pthid = presentation.thid.getOrElse(presentation.id),
code = ProblemCode("e.p.presentation-verification-failed"),
comment = Some(error.mkString)
)
reportProblem = buildReportProblem(presentation, error.mkString)
_ <-
MessagingService
.send(reportproblem.toMessage)
.send(reportProblem.toMessage)
.provideSomeLayer(didCommAgent)
_ <- ZIO.log(s"CredentialsClaimsValidationResult: $error")
} yield ()
Expand Down Expand Up @@ -1219,19 +1246,13 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
_ <- service
.markPresentationVerificationFailed(id)
.provideSomeLayer(ZLayer.succeed(walletAccessContext)) @@ presReceivedToProcessedAspect
didCommAgent <- buildDIDCommAgent(presentation.from).provideSomeLayer(
didCommAgent <- buildDIDCommAgent(presentation.to).provideSomeLayer(
ZLayer.succeed(walletAccessContext)
)
reportproblem = ReportProblem.build(
fromDID = presentation.to,
toDID = presentation.from,
pthid = presentation.thid.getOrElse(presentation.id),
code = ProblemCode("e.p.presentation-verification-failed"),
comment = Some(invalid.toString)
)
reportProblem = buildReportProblem(presentation, invalid.toString)
resp <-
MessagingService
.send(reportproblem.toMessage)
.send(reportProblem.toMessage)
.provideSomeLayer(didCommAgent)
_ <- ZIO.log(s"CredentialsClaimsValidationResult: ${invalid.toString}")
} yield ()
Expand Down Expand Up @@ -1263,19 +1284,13 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
.provideSomeLayer(ZLayer.succeed(walletAccessContext)) @@ presReceivedToProcessedAspect)
.flatMapError(e =>
for {
didCommAgent <- buildDIDCommAgent(presentation.from).provideSomeLayer(
didCommAgent <- buildDIDCommAgent(presentation.to).provideSomeLayer(
ZLayer.succeed(walletAccessContext)
)
reportproblem = ReportProblem.build(
fromDID = presentation.to,
toDID = presentation.from,
pthid = presentation.thid.getOrElse(presentation.id),
code = ProblemCode("e.p.presentation-verification-failed"),
comment = Some(e.toString)
)
reportProblem = buildReportProblem(presentation, e.toString)
_ <-
MessagingService
.send(reportproblem.toMessage)
.send(reportProblem.toMessage)
.provideSomeLayer(didCommAgent)
_ <- ZIO.log(s"CredentialsClaimsValidationResult: ${e.toString}")
} yield ()
Expand All @@ -1286,12 +1301,4 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
}
}
}

// val syncDIDPublicationStateFromDlt: ZIO[WalletAccessContext & ManagedDIDService, GetManagedDIDError, Unit] =
// for {
// managedDidService <- ZIO.service[ManagedDIDService]
// _ <- managedDidService.syncManagedDIDState
// _ <- managedDidService.syncUnconfirmedUpdateOperations
// } yield ()

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ object ReportProblem {
given Encoder[ReportProblem] = deriveEncoder[ReportProblem]
given Decoder[ReportProblem] = deriveDecoder[ReportProblem]

def readFromMessage(message: Message): ReportProblem =
def fromMessage(message: Message): ReportProblem =
val body = message.body.asJson.as[ReportProblem.Body].toOption.get // TODO get
ReportProblem(
id = message.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ object PresentationError {
msg
)

final case class PresentationValidationError(msg: String)
extends PresentationError(
StatusCode.BadRequest,
msg
)

final case class PresentationReceivedError(msg: String)
extends PresentationError(
StatusCode.InternalServerError,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.hyperledger.identus.pollux.core.repository.{CredentialRepository, Cre
import org.hyperledger.identus.pollux.prex.{ClaimFormat, Jwt, PresentationDefinition}
import org.hyperledger.identus.pollux.sdjwt.*
import org.hyperledger.identus.pollux.vc.jwt.{Issuer as JwtIssuer, *}
import org.hyperledger.identus.pollux.vc.jwt.PresentationPayload.Implicits.*
import org.hyperledger.identus.shared.crypto.{Ed25519KeyPair, Secp256k1KeyPair}
import org.hyperledger.identus.shared.http.UriResolver
import org.hyperledger.identus.shared.messaging.{Producer, WalletIdAndRecordId}
Expand Down Expand Up @@ -1505,7 +1506,7 @@ class CredentialServiceImpl(
ZIO.fail(CredentialRequestValidationFailed(s"JWT presentation verification failed: $error"))

jwtPresentation <- ZIO
.fromTry(JwtPresentation.decodeJwt(jwt))
.fromTry(JwtPresentation.decodeJwt[JwtPresentationPayload](jwt))
.mapError(t => CredentialRequestValidationFailed(s"JWT presentation decoding failed: ${t.getMessage}"))
} yield jwtPresentation
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.hyperledger.identus.pollux.prex.PresentationSubmissionError.{
JsonPathNotFound,
SubmissionNotSatisfyInputDescriptors
}
import org.hyperledger.identus.pollux.vc.jwt.{JWT, JwtCredential, JwtPresentation}
import org.hyperledger.identus.pollux.vc.jwt.{JWT, JwtCredential, JwtPresentation, JwtPresentationPayload}
import org.hyperledger.identus.pollux.vc.jwt.CredentialPayload.Implicits.*
import org.hyperledger.identus.pollux.vc.jwt.PresentationPayload.Implicits.*
import org.hyperledger.identus.shared.json.{JsonInterop, JsonPath, JsonPathError, JsonSchemaValidatorImpl}
Expand Down Expand Up @@ -220,7 +220,7 @@ object PresentationSubmissionVerification {
.map(JWT(_))
.mapError(_ => InvalidDataTypeForClaimFormat(format, path, "string"))
payload <- ZIO
.fromTry(JwtPresentation.decodeJwt(jwt))
.fromTry(JwtPresentation.decodeJwt[JwtPresentationPayload](jwt))
.mapError(e => ClaimDecodeFailure(format, path, e.getMessage()))
_ <- formatVerification(jwt)
.mapError(errors => ClaimFormatVerificationFailure(format, path, errors.mkString))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hyperledger.identus.pollux.vc.jwt

case class CredentialSchemaAndTrustedIssuersConstraint(
schemaId: String,
trustedIssuers: Option[Seq[String]]
)
Loading

0 comments on commit c200931

Please sign in to comment.