• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hyperledger / identus-cloud-agent / 8998019047

08 May 2024 07:31AM UTC coverage: 47.171% (-0.7%) from 47.829%
8998019047

Pull #1021

patlo-iog
chore: pr cleanup
Pull Request #1021: feat: oidc4vc credential configuration and metadata endpoints [WIP]

2 of 253 new or added lines in 12 files covered. (0.79%)

186 existing lines in 51 files now uncovered.

7388 of 15662 relevant lines covered (47.17%)

0.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.19
/castor/src/main/scala/org/hyperledger/identus/castor/core/model/did/PrismDID.scala
1
package org.hyperledger.identus.castor.core.model.did
2

3
import org.hyperledger.identus.castor.core.model.ProtoModelHelper
4
import org.hyperledger.identus.shared.crypto.Sha256Hash
5
import io.iohk.atala.prism.protos.node_models
6
import io.iohk.atala.prism.protos.node_models.AtalaOperation.Operation
7
import org.hyperledger.identus.shared.models.Base64UrlString
8
import org.hyperledger.identus.shared.models.HexString
9
import scala.util.Try
10
import scala.util.matching.Regex
11

12
/** Represents a [Did] used in PRISM with prism-specific method and keys as [PrismDid]
13
  */
14
sealed trait PrismDID {
15
  override def toString: String = did.toString
1✔
16

17
  final def did: DID = DID(PrismDID.PRISM_METHOD, suffix)
1✔
18

19
  final def asCanonical: CanonicalPrismDID = CanonicalPrismDID(stateHash)
1✔
20

21
  def stateHash: HexString
22

23
  def suffix: DIDMethodSpecificId
24

25
}
26

27
object PrismDID extends ProtoModelHelper {
28
  val PRISM_METHOD: DIDMethod = DIDMethod.fromStringUnsafe("prism")
1✔
29
  val CANONICAL_SUFFIX_REGEX: Regex = "^([0-9a-f]{64}$)".r
1✔
30
  val LONG_FORM_SUFFIX_REGEX: Regex = "^([0-9a-f]{64}):([A-Za-z0-9_-]+$)".r
1✔
31

32
  def buildCanonical(stateHash: Array[Byte]): Either[String, CanonicalPrismDID] =
1✔
33
    Try(Sha256Hash.fromBytes(stateHash)).toEither.left
1✔
UNCOV
34
      .map(_.getMessage)
×
35
      .map(_ => CanonicalPrismDID(HexString.fromByteArray(stateHash)))
1✔
36

37
  def buildCanonicalFromSuffix(suffix: String): Either[String, CanonicalPrismDID] =
1✔
38
    HexString
39
      .fromString(suffix)
1✔
40
      .toEither
1✔
41
      .left
1✔
42
      .map(e => s"unable to parse suffix as hex string: ${e.getMessage}")
×
43
      .flatMap(suffix => buildCanonical(suffix.toByteArray))
1✔
44

45
  def buildLongFormFromOperation(createOperation: PrismDIDOperation.Create): LongFormPrismDID =
1✔
46
    buildLongFormFromAtalaOperation(
1✔
47
      createOperation.toAtalaOperation
1✔
48
    ).toOption.get // This cannot fail because we know the operation is a CreateDid
1✔
49

50
  def buildLongFormFromAtalaOperation(atalaOperation: node_models.AtalaOperation): Either[String, LongFormPrismDID] =
1✔
51
    atalaOperation.operation match {
52
      case _: Operation.CreateDid => Right(LongFormPrismDID(atalaOperation))
1✔
53
      case operation =>
1✔
54
        Left(s"Provided initial state of long form Prism DID is ${operation.value}, CreateDid Atala operation expected")
1✔
55
    }
56

57
  def fromString(s: String): Either[String, PrismDID] = {
1✔
58
    DID
59
      .fromString(s)
1✔
60
      .flatMap { did =>
1✔
61
        if (did.method == PRISM_METHOD) Right(did)
1✔
62
        else Left(s"Expected DID to have method $PRISM_METHOD, but got \"${did.method.toString}\" instead")
1✔
63
      }
64
      .flatMap { did =>
1✔
65
        val canonicalMatchGroups = CANONICAL_SUFFIX_REGEX.findAllMatchIn(did.methodSpecificId.toString).toList
1✔
66
        val longFormMatchGroups = LONG_FORM_SUFFIX_REGEX.findAllMatchIn(did.methodSpecificId.toString).toList
1✔
67

68
        (canonicalMatchGroups, longFormMatchGroups) match {
69
          case (Nil, longFormPattern :: Nil) =>
1✔
70
            for {
1✔
71
              stateHash <- HexString
72
                .fromString(longFormPattern.group(1))
1✔
73
                .toEither
1✔
74
                .left
1✔
75
                .map(_ => "Invalid long form Prism DID state hash")
1✔
76
              atalaOperation <- Base64UrlString
1✔
77
                .fromString(longFormPattern.group(2))
1✔
78
                .flatMap { encodedStateBase64 =>
1✔
79
                  Try(node_models.AtalaOperation.parseFrom(encodedStateBase64.toByteArray))
1✔
80
                }
81
                .toEither
1✔
82
                .left
1✔
83
                .map(_ => "Invalid long form Prism DID encoded state")
1✔
84
              longFormDID <- buildLongFormFromAtalaOperation(atalaOperation)
1✔
85
              _ <- Either.cond(
1✔
86
                stateHash == longFormDID.stateHash,
87
                (),
88
                "Canonical suffix does not match the computed state"
89
              )
90
            } yield longFormDID
1✔
91
          case (canonicalPattern :: Nil, Nil) =>
1✔
92
            HexString
93
              .fromString(canonicalPattern.group(1))
1✔
94
              .toEither
1✔
95
              .left
1✔
96
              .map(_ => "Invalid canonical form Prism DID")
1✔
97
              .map(stateHash => CanonicalPrismDID(stateHash))
1✔
98
          case _ => Left("Provided DID is not a valid PRISM DID")
×
99
        }
100
      }
101
  }
102
}
103

104
final case class CanonicalPrismDID private[did] (stateHash: HexString) extends PrismDID {
105
  override val suffix: DIDMethodSpecificId = DIDMethodSpecificId.fromStringUnsafe(stateHash.toString)
1✔
106
}
107

108
final case class LongFormPrismDID private[did] (atalaOperation: node_models.AtalaOperation) extends PrismDID {
109

110
  override val stateHash: HexString = {
111
    val encodedState = atalaOperation.toByteArray
1✔
112
    HexString.fromByteArray(Sha256Hash.compute(encodedState).bytes.toArray)
1✔
113
  }
114

115
  override val suffix: DIDMethodSpecificId = {
116
    val encodedState = Base64UrlString.fromByteArray(atalaOperation.toByteArray).toStringNoPadding
1✔
117
    DIDMethodSpecificId.fromStringUnsafe(s"${stateHash.toString}:${encodedState}")
1✔
118
  }
119

120
  def createOperation: Either[String, PrismDIDOperation.Create] = {
1✔
121
    import ProtoModelHelper.*
122
    atalaOperation.operation match {
123
      case Operation.CreateDid(op) => op.toDomain
1✔
124
      case operation =>
×
125
        Left(s"Provided initial state of long form Prism DID is ${operation.value}, CreateDid Atala operation expected")
×
126
    }
127
  }
128

129
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc