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

input-output-hk / atala-prism-building-blocks / 5477316800

06 Jul 2023 03:26PM UTC coverage: 27.118% (-0.8%) from 27.945%
5477316800

Pull #584

FabioPinheiro
feat: update anoncreds demo after the new getJson methods
Pull Request #584: feat: update anoncreds demo after the new getJson methods

2455 of 9053 relevant lines covered (27.12%)

0.27 hits per line

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

52.38
/castor/lib/core/src/main/scala/io/iohk/atala/castor/core/model/did/PrismDID.scala
1
package io.iohk.atala.castor.core.model.did
2

3
import io.iohk.atala.castor.core.model.ProtoModelHelper
4
import io.iohk.atala.prism.crypto.{Sha256, Sha256Digest}
5
import io.iohk.atala.prism.protos.node_models
6
import io.iohk.atala.prism.protos.node_models.AtalaOperation.Operation
7
import io.iohk.atala.shared.models.Base64UrlString
8
import io.iohk.atala.shared.models.HexString
9

10
import scala.util.Try
11
import scala.util.matching.Regex
12

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

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

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

22
  def stateHash: HexString
23

24
  def suffix: DIDMethodSpecificId
25

26
}
27

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

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

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

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

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

1✔
58
  def fromString(s: String): Either[String, PrismDID] = {
59
    // Only reuse code in Did.fromString not PrismDid.fromString from 1.4 SDK
60
    // because of uncertainty around keeping prism-identity up-to-date
61
    // as the protobuf definition evolves
×
62
    Try(io.iohk.atala.prism.identity.Did.Companion.fromString(s)).toEither.left
×
63
      .map(_.getMessage)
×
64
      .flatMap { did =>
×
65
        if (did.getMethod.toString == PRISM_METHOD.value) Right(did)
×
66
        else Left(s"Expected DID to have method ${PRISM_METHOD.value}, but got \"${did.getMethod.toString}\" instead")
67
      }
1✔
68
      .flatMap { (did: io.iohk.atala.prism.identity.Did) =>
1✔
69
        val canonicalMatchGroups = CANONICAL_SUFFIX_REGEX.findAllMatchIn(did.getMethodSpecificId.toString).toList
1✔
70
        val longFormMatchGroups = LONG_FORM_SUFFIX_REGEX.findAllMatchIn(did.getMethodSpecificId.toString).toList
71

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

108
final case class CanonicalPrismDID private[did] (stateHash: HexString) extends PrismDID {
1✔
109
  override val suffix: DIDMethodSpecificId = DIDMethodSpecificId.fromString(stateHash.toString).get
110
}
111

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

114
  override val stateHash: HexString = {
1✔
115
    val encodedState = atalaOperation.toByteArray
1✔
116
    HexString.fromByteArray(Sha256.compute(encodedState).getValue)
117
  }
118

119
  override val suffix: DIDMethodSpecificId = {
1✔
120
    val encodedState = Base64UrlString.fromByteArray(atalaOperation.toByteArray).toStringNoPadding
1✔
121
    DIDMethodSpecificId.fromString(s"${stateHash.toString}:${encodedState}").get
122
  }
123

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

133
}
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