Basic Example
Parse a DID Document
val documentString = """{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:example:123456789abcdefghi",
"keyAgreement": [
"did:example:123456789abcdefghi#keys-1",
{
"id": "did:example:123#zC9ByQ8aJs8vrNXyDhPHHNNMSHPcaSgNpjjsBYpMMjsTdS",
"type": "X25519KeyAgreementKey2019",
"controller": "did:example:123",
"publicKeyMultibase": "z9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE"
}
]
}"""
documentString.fromJson[DIDDocument]
// res0: Either[String, DIDDocument] = Right(
// value = DIDDocumentClass(
// id = "did:example:123456789abcdefghi",
// alsoKnownAs = None,
// verificationMethod = None,
// authentication = None,
// assertionMethod = None,
// keyAgreement = Some(
// value = Set(
// VerificationMethodReferenced(
// value = "did:example:123456789abcdefghi#keys-1"
// ),
// VerificationMethodEmbeddedMultibase(
// id = "did:example:123#zC9ByQ8aJs8vrNXyDhPHHNNMSHPcaSgNpjjsBYpMMjsTdS",
// controller = "did:example:123",
// type = "X25519KeyAgreementKey2019",
// expires = None,
// revoked = None,
// publicKeyMultibase = "z9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE",
// secretKeyMultibase = None
// )
// )
// ),
// capabilityInvocation = None,
// capabilityDelegation = None,
// service = None
// )
// )
NOTE the return type is of type Either[String, DIDDocument]
<br> Since the documentString
is a valid json and which is also a valid DID Document.
The value is Right
of that class that implemente trait DIDDocument
.
<br> If the documentString
was a invalid json or did not represented a DID Document.
The return value would have been Left, containing the information why failed to parse.
"not a json".fromJson[DIDDocument]
// res1: Either[String, DIDDocument] = Left(value = "(expected '{' got 'n')")
"""{"some_json": "but_not_a_valid_document"}""".fromJson[DIDDocument]
// res2: Either[String, DIDDocument] = Left(value = ".id(missing)")
Another Important Point is that there is no failed here everywhere on this library! We work with values. (Any error/exception will be considered a bug and reports are appreciated)
This this allowed us to this allowed us to build programs build (ZIO) programs. That can are executed at any point in time.
Make DID Peer identities
import fmgp.crypto.*
import fmgp.did.method.peer.*
val alice = DIDPeer2.makeAgent(
Seq(
OKPPrivateKey( // keyAgreement
kty = KTY.OKP,
crv = Curve.X25519,
d = "Z6D8LduZgZ6LnrOHPrMTS6uU2u5Btsrk1SGs4fn8M7c",
x = "Sr4SkIskjN_VdKTn0zkjYbhGTWArdUNE4j_DmUpnQGw",
),
OKPPrivateKey( // keyAuthentication
kty = KTY.OKP,
crv = Curve.Ed25519,
d = "INXCnxFEl0atLIIQYruHzGd5sUivMRyQOzu87qVerug",
x = "MBjnXZxkMcoQVVL21hahWAw43RuAG-i64ipbeKKqwoA",
)
),
Seq(DIDPeerServiceEncoded.fromEndpoint("https://alice.did.fmgp.app/"))
)
// alice: AgentDIDPeer = fmgp.did.method.peer.DIDPeer2$$anon$4@19fe49d3
alice.id.asDIDSubject
// res3: DIDSubject = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0"
alice.id.document.toJsonPretty
// res4: String = """{
// "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
// "authentication" : [
// {
// "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0#key-2",
// "controller" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
// "type" : "JsonWebKey2020",
// "publicKeyJwk" : {
// "kty" : "OKP",
// "crv" : "Ed25519",
// "x" : "MBjnXZxkMcoQVVL21hahWAw43RuAG-i64ipbeKKqwoA"
// }
// }
// ],
// "keyAgreement" : [
// {
// "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0#key-1",
// "controller" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
// "type" : "JsonWebKey2020",
// "publicKeyJwk" : {
// "kty" : "OKP",
// "crv" : "X25519",
// "x" : "Sr4SkIskjN_VdKTn0zkjYbhGTWArdUNE4j_DmUpnQGw"
// }
// }
// ],
// "service" : [
// {
// "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0#service",
// "type" : "DIDCommMessaging",
// "serviceEndpoint" : {
// "uri" : "https://alice.did.fmgp.app/",
// "accept" : [
// "didcomm/v2"
// ]
// }
// }
// ...
Resolve did:peer identities
import fmgp.did.method.peer.*
val program1 = DidPeerResolver.didDocument(DIDPeer(alice.id.asDIDSubject))
// program1: ZIO[Any, Nothing, DIDDocument] = Sync(
// trace = "fmgp.did.method.peer.DidPeerResolver.genesisDocument(DidPeerResolver.scala:33)",
// eval = fmgp.did.method.peer.DidPeerResolver$$$Lambda$24278/0x0000000805fa9c40@...
Unsafe.unsafe { implicit unsafe => // Run side effect
Runtime.default.unsafe
.run(program1)
.getOrThrowFiberFailure()
}
// res5: DIDDocument = DIDDocumentClass(
// id = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
// ...
Trust Ping example
import fmgp.did.comm.protocol.trustping2.* // For the protocol
val ping = TrustPingWithRequestedResponse(
from = alice.id,
to = TO("did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ")
)
// ping: TrustPingWithRequestedResponse = TrustPingWithRequestedResponse(
// id = "406b2752-6736-4146-a9a3-797c3295d82b",
// from = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
// to = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ"
// )
ping.toPlaintextMessage.toJsonPretty
// res6: String = """{
// "id" : "406b2752-6736-4146-a9a3-797c3295d82b",
// "type" : "https://didcomm.org/trust-ping/2.0/ping",
// "to" : [
// "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ"
// ],
// "from" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
// "body" : {
// "response_requested" : true
// }
// }"""
Encrypt
import Operations.*
val program2 = for {
msg <- authEncrypt(ping.toPlaintextMessage).provideSomeLayer(ZLayer.succeed(alice))
_ <- Console.printLine(msg.toJsonPretty)
} yield ()
Unsafe.unsafe { implicit unsafe => // Run side effect
Runtime.default.unsafe
.run(program2.provide(Operations.layerOperations ++ DidPeerResolver.layer))
.getOrThrowFiberFailure()
}
// {
// "ciphertext" : "3qTpp9SnlDGKRB-zzNOX6Qw6PBUx3ajZJihgyMQirEUOB9yp4E-oaUsJUQoR1Dc7ihBeEIGmyMXpTCp98-da1t5PWK7tiMn5eR-nvqJ7YIim4_PY0fhj3u-c25Ex41egTdDHNmwyTG21bBwl4EgJggvymcQEK9qx3d9JSgD83Kd6Br07aYeiwFONO9ZzEc1a-3wjiUK1isz5QLNn1FRW3BXda-jiwnyo1U4mpsnwxxXKjvmNTWE906NyUtbqS-A1HTy-10jFtQW_UiT89Ipms_ld0FAp6q9RPDrWvLw7Wf6xRayEiEqe95C3As9fXGsRZDyjUrfj6F1dzZBH739WN4WUFv5i0GRIv-Bezd21nB1MVvM2VLWfFttpDsjDK_sSFJcy3757DqLsAAu3qyBv9LedYpMhoOpm4Q53G3cHjsjYwJoNSa-NtpUm--hhTWGDdH0SSgpxS495_wUDqfT_rbduKaSgLiZWQBqQxzXnDcu6VjscVlbc2789tMmNEnXZLVgFKsaEz3g9oBJcawNwxTSQ9bljtA-pxcQFBaUkx6GknKlR9pAi2IiL9W7FxYS3G4vUpjduuWa33IxMF83uw8gdIZXf3JoAEDTUJiMh9ImeSd0uU-t4XTs5gROBIu-rpmus4XbVIKoreGvCgC_jnctk21S9_rh2VyHQzfovCAhxREptRUqQ8gDVg8Si2hOy1jGkyIODDwfPjv8B-rs4ZYKDkN3skdSi7Czz5fO0f-3cHinAMiBFxEBthvjkB9St",
// "protected" : "eyJlcGsiOnsia3R5IjoiT0tQIiwiY3J2IjoiWDI1NTE5IiwieCI6ImFYVUc0YUNEZkwyUHFoWkQyODhNaXhMX245a3BYTnRLaUIzaEZ3QjNGamsifSwiYXB2IjoiZXVXaDJHcEc0WUl3OVlXVFAyX1ZLUWhUVHRCN2VhR25CZk85OV9NZjhuZyIsInNraWQiOiJkaWQ6cGVlcjoyLkV6NkxTZ2h3U0U0Mzd3bkRFMXB0M1g2aFZEVVF6U2pzSHppbnBYM1hGdk1qUkFtN3kuVno2TWtoaDFlNUNFWVlxNkpCVWNUWjZDcDJyYW5DV1JydjdZYXgzTGU0TjU5UjZkZC5TZXlKMElqb2laRzBpTENKeklqcDdJblZ5YVNJNkltaDBkSEJ6T2k4dllXeHBZMlV1Wkdsa0xtWnRaM0F1WVhCd0x5SXNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAja2V5LTEiLCJhcHUiOiJaR2xrT25CbFpYSTZNaTVGZWpaTVUyZG9kMU5GTkRNM2QyNUVSVEZ3ZEROWU5taFdSRlZSZWxOcWMwaDZhVzV3V0ROWVJuWk5hbEpCYlRkNUxsWjZOazFyYUdneFpUVkRSVmxaY1RaS1FsVmpWRm8yUTNBeWNtRnVRMWRTY25ZM1dXRjRNMHhsTkU0MU9WSTJaR1F1VTJWNVNqQkphbTlwV2tjd2FVeERTbnBKYW5BM1NXNVdlV0ZUU1RaSmJXZ3daRWhDZWs5cE9IWlpWM2h3V1RKVmRWcEhiR3RNYlZwMFdqTkJkVmxZUW5kTWVVbHpTVzFGYVU5c2MybGFSMnhyV1RJNWRHSlRPVEpOYVVwa1psZ3dJMnRsZVMweCIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiRUNESC0xUFUrQTI1NktXIn0",
// "recipients" : [
// {
// "encrypted_key" : "XBe0HCCIjMUub9Ae29j324MEkLimUxbkW_6k_vDFu8PNMNZ-p1Om5bJN7AUKDLKxrGSeLREyNl0yGakZIMSuShlIm5Iu-eoI",
// "header" : {
// "kid" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ#key-1"
// }
// }
// ],
// "tag" : "P0l-yOpKlYi35m3f-iSvQ-uxRSlS8aDFywlN19T8XqM",
// "iv" : "rEFUoBTx3hD1T3YKe5AxcQ"
// }