-
Notifications
You must be signed in to change notification settings - Fork 23
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
feat(castor): implement translation of Node DidData to W3C DidDocument #182
Changes from all commits
b1895c0
b8d6717
7af4a07
afb2d35
76a44c0
225a5b8
9824316
78b807b
aef9376
952ca09
1e334db
c6684ff
e345f75
31e1ba1
a07587e
9a2fe98
f3f2989
9389157
941105c
a87416a
22966d5
9c0d10e
c578b0e
044cbdb
10d336b
691c235
26d2737
b568865
e14f7ae
6392be1
308ff0a
9982c82
eaa6059
40b0ea8
7c4d6a3
ba188f5
b46a4eb
c45678b
d64aa61
eb425e3
35a2afa
da94370
b6cd43b
7bb833c
d88e966
297fc79
6981e0f
6364844
5ae2695
b704393
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,17 @@ | ||
package io.iohk.atala.castor.core.model.did | ||
|
||
import io.iohk.atala.castor.core.model.did.w3c.DIDDocumentRepr | ||
|
||
import scala.collection.immutable.ArraySeq | ||
|
||
final case class DIDData( | ||
id: CanonicalPrismDID, | ||
publicKeys: Seq[PublicKey], | ||
services: Seq[Service], | ||
internalKeys: Seq[InternalPublicKey] | ||
) | ||
|
||
final case class DIDMetadata( | ||
lastOperationHash: ArraySeq[Byte], | ||
deactivated: Boolean | ||
) |
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package io.iohk.atala.castor.core.model.did.w3c | ||
|
||
import io.iohk.atala.castor.core.model.did.{DID, DIDUrl} | ||
|
||
/** A projection of DIDDocument data model to W3C compliant DID representation */ | ||
final case class DIDDocumentRepr( | ||
id: String, | ||
controller: String, | ||
verificationMethod: Seq[PublicKeyRepr], | ||
authentication: Seq[PublicKeyRepr], | ||
assertionMethod: Seq[PublicKeyRepr], | ||
keyAgreement: Seq[PublicKeyRepr], | ||
capabilityInvocation: Seq[PublicKeyRepr], | ||
service: Seq[ServiceRepr] | ||
) | ||
|
||
final case class PublicKeyRepr( | ||
id: String, | ||
`type`: "EcdsaSecp256k1VerificationKey2019", | ||
controller: String, | ||
publicKeyJwk: PublicKeyJwk | ||
) | ||
|
||
final case class ServiceRepr( | ||
id: String, | ||
`type`: String, | ||
serviceEndpoint: String | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @patlo-iog, just one comment regarding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @rodolfomiranda . It will be trivial to extend these types in scala 3 so if we ever need to project some document where it provides a set of URIs then we can add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'm falling in love with Scala :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LOL |
||
) | ||
|
||
final case class PublicKeyJwk(kty: "EC", crv: String, x: String, y: String) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.iohk.atala.castor.core.model.did.w3c | ||
|
||
import java.time.Instant | ||
|
||
// errors are based on https://www.w3.org/TR/did-spec-registries/#error | ||
enum DIDResolutionErrorRepr(val value: String) { | ||
case InvalidDID extends DIDResolutionErrorRepr("invalidDid") | ||
case InvalidDIDUrl extends DIDResolutionErrorRepr("invalidDidUrl") | ||
case NotFound extends DIDResolutionErrorRepr("notFound") | ||
case RepresentationNotSupported extends DIDResolutionErrorRepr("representationNotSupported") | ||
case InternalError extends DIDResolutionErrorRepr("internalError") | ||
case InvalidPublicKeyLength extends DIDResolutionErrorRepr("invalidPublicKeyLength") | ||
case InvalidPublicKeyType extends DIDResolutionErrorRepr("invalidPublicKeyType") | ||
case UnsupportedPublicKeyType extends DIDResolutionErrorRepr("unsupportedPublicKeyType") | ||
} | ||
|
||
final case class DIDDocumentMetadataRepr(deactivated: Boolean) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package io.iohk.atala.castor.core.model.did.w3c | ||
|
||
import io.iohk.atala.castor.core.model.did.{ | ||
CanonicalPrismDID, | ||
DIDData, | ||
DIDMetadata, | ||
PublicKey, | ||
PublicKeyData, | ||
Service, | ||
VerificationRelationship | ||
} | ||
|
||
object W3CModelHelper extends W3CModelHelper | ||
|
||
private[castor] trait W3CModelHelper { | ||
|
||
extension (didMetadata: DIDMetadata) { | ||
def toW3C: DIDDocumentMetadataRepr = DIDDocumentMetadataRepr(deactivated = didMetadata.deactivated) | ||
} | ||
|
||
extension (didData: DIDData) { | ||
def toW3C: DIDDocumentRepr = { | ||
val keyWithPurpose = didData.publicKeys.map(k => k.purpose -> k.toW3C(didData.id)) | ||
DIDDocumentRepr( | ||
id = didData.id.toString, | ||
controller = didData.id.toString, | ||
verificationMethod = Nil, | ||
authentication = keyWithPurpose.collect { case (VerificationRelationship.Authentication, k) => k }, | ||
assertionMethod = keyWithPurpose.collect { case (VerificationRelationship.AssertionMethod, k) => k }, | ||
keyAgreement = keyWithPurpose.collect { case (VerificationRelationship.KeyAgreement, k) => k }, | ||
capabilityInvocation = keyWithPurpose.collect { case (VerificationRelationship.CapabilityInvocation, k) => k }, | ||
service = didData.services.map(_.toW3C) | ||
) | ||
} | ||
} | ||
|
||
extension (service: Service) { | ||
def toW3C: ServiceRepr = ServiceRepr( | ||
id = service.id, | ||
`type` = service.`type`.name, | ||
serviceEndpoint = service.serviceEndpoint.toString | ||
) | ||
} | ||
|
||
extension (publicKey: PublicKey) { | ||
def toW3C(controller: CanonicalPrismDID): PublicKeyRepr = PublicKeyRepr( | ||
id = publicKey.id, | ||
`type` = "EcdsaSecp256k1VerificationKey2019", | ||
controller = controller.toString, | ||
publicKeyJwk = publicKey.publicKeyData match { | ||
case PublicKeyData.ECKeyData(crv, x, y) => | ||
PublicKeyJwk( | ||
kty = "EC", | ||
crv = crv.name, | ||
x = x.toStringNoPadding, | ||
y = y.toStringNoPadding | ||
) | ||
} | ||
) | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wow :), how does it works, this type in double quotes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new in scala 3 :). Enforce that
type
must not only be string, but string of valueEcdsaSecp256k1VerificationKey2019