From 838a5a659909c60b19280a07f53e4d25426aa43c Mon Sep 17 00:00:00 2001 From: Tobias Looker Date: Tue, 12 Feb 2019 21:49:28 -0800 Subject: [PATCH 1/5] Initial commit of update to did doc conventions Signed-off-by: Tobias Looker --- text/0023-diddoc-conventions/README.md | 223 +++++++++++++------------ 1 file changed, 115 insertions(+), 108 deletions(-) diff --git a/text/0023-diddoc-conventions/README.md b/text/0023-diddoc-conventions/README.md index 6120e0225..99a57d5a2 100644 --- a/text/0023-diddoc-conventions/README.md +++ b/text/0023-diddoc-conventions/README.md @@ -1,7 +1,6 @@ - # 0023: DID Doc Conventions - Name: diddoc-conventions -- Author: Stephen Curran (swcurran@gmail.com) +- Author: Stephen Curran (swcurran@gmail.com), Tobias Looker (tobias.looker@spark.co.nz) - Start Date: 2018-08-14 - PR: - Jira Issue: @@ -9,20 +8,12 @@ ## Summary [summary]: #summary -This is one of a series of HIPEs that together enable interoperability across implementations of Hyperledger Indy Agents, and ideally in the future, Agents rooted in other self-sovereign identity ecosystems. In this HIPE the use of the DIDDoc is considered and conventions defined that if followed will aid in accomplishing the interoperability goal. - -In order to send a message from one Identity to another, the sending Identity must know something about the Receiver's domain - the Receiver's configuration of Agents. This HIPE outlines some aspects of how a domain MUST populate a DIDDoc it shares with other entities either on a Public Ledger or via a microledger. In both cases, the other identity resolving and viewing the DIDDoc must be able to use the information in the DIDDoc to communicate with the owning Identity. - -There are a series of related HIPEs that combine with this HIPE to address the interoperability of Agents, including in particular, Agent Messages, DIDDoc Conventions, and Cross Domain Messaging. Those HIPEs should be considered together in understanding Agent-to-Agent interoperability. The goal of these related HIPEs is to define the rules that domains MUST follow to enable the delivery of Agent Messages from a Sending Agent to a Receiver Agent in a secure and privacy-preserving manner. +This is one of a series of HIPEs that together enable interoperability across implementations of Hyperledger Indy Agents and ideally in the future, agents rooted in other self-sovereign identity ecosystems. ## Motivation [motivation]: #motivation -The purpose of this HIPE and its related HIPEs is to define a layered Messaging protocol such that we can ignore the transport of messages as we discuss the much richer Agent Messaging types and interactions. That is, we can assume that there is no need to include in an Agent message anything about how to route the message to the Receiver - it just magically happens. Alice (via her Agent) sends a message to Bob, and (because of implementations based on this series of HIPEs) we can ignore how the actual message got to Bob's Agent. - -Put another way - these HIPEs are about envelopes. They define a way to put a message - any message - into an envelope, put it into an outbound mailbox and have it magically appear in the Receiver's inbound mailbox in a secure and privacy-preserving manner. Once we have that, we can focus on letters and not how letters are sent. - -In particular, this HIPE is about addresses - information in the DIDDoc that lets a sending Identity communicate with another Identity. +In this HIPE the use of the DIDDocs and in particular some associated conventions are defined that enable standardised communication between with indy agents. ## Tutorial [tutorial]: #tutorial @@ -34,7 +25,7 @@ These are vital design goals for this HIPE: 1. **Sender Encapsulation**: We SHOULD minimize what the Receiver has to know about the domain (routing tree or agent infrastructure) of the Sender in order for them to communicate. 2. **Receiver Encapsulation**: We SHOULD minimize what the Sender has to know about the domain (routing tree or agent infrastructure) of the Receiver in order for them to communicate. 3. **Independent Keys**: Private signing keys SHOULD NOT be shared between agents; each agent SHOULD be separately identifiable for accounting and authorization/revocation purposes. -4. ***Prevent correlation based on DIDDoc Contents**: The information in the set of DIDDocs owned by an Identity SHOULD NOT be so precise as to represent a fingerprint for that Identity suitable for correlation. +4. **Prevent correlation based on DIDDoc Contents**: The information in the set of DIDDocs owned by an Identity SHOULD NOT be so precise as to represent a fingerprint for that Identity suitable for correlation. ### Assumptions @@ -47,16 +38,13 @@ The following terms are used in this HIPE with the following meanings: - [Sovereign] Domain - a set of Agents collaborating on behalf of an Identity - It's assumed that the Agents of a Domain were developed by a single vendor and so may use implementation-specific mechanisms for tracking extra information one another. - An example of two Domains is provided in the image below. -- Domain Endpoint - a shared physical endpoint for messages into domains - - Shared by many identities (e.g. https://endpoint.agentsRus.com) - - Agency - the handler for messages sent to the Domain Endpoint. -- Routing Agent - the single identity-controlled entry point for a Domain per relationship - - A message delivered to a Domain Endpoint is **always** passed directly to the Routing Agent for a Domain -- Sender Agent - the Agent that creates an Agent Message for the Receiver that is in another Domain. +- Mediators and Relays - defined in the [Mediators and Relays](https://github.com/hyperledger/indy-hipe/pull/85) +- Domain Endpoint - a physical endpoint for messages into domains + - Sender Agent - the Agent that creates an Agent Message for the Receiver that is in another Domain. - Receiver Agent - the Agent that ultimately receives and can decrypt and process the Agent Message from the Sender. - DID - reference to the literal Decentralized ID text - e.g. did:sov:1234abcd -- DID#keyname - reference to the DID appended with "#" and a specific key from the DIDDoc +- DID#keyname - a DID key reference which leverages the [DID fragments syntax](https://w3c-ccg.github.io/did-spec/#fragments). - e.g. did:sov:1234abcd#1 references key "1" of the "did:sov:1234abcd" DIDDoc. - **Note**: The #keyname is NOT the actual Public Key - it's a reference to an entry in the DIDDoc that contains the Public Key. @@ -64,16 +52,63 @@ The following terms are used in this HIPE with the following meanings: The term "DIDDoc" is used in this HIPE as it is defined in the [DID Specification](https://w3c-ccg.github.io/did-spec/#did-documents): -- a collection of public keys and endpoints, -- controlled by an identity, -- associated with a DID, and -- used for a relationship. +- a collection of public keys and service endpoints +- controlled by an identity +- associated with a DID + +A DIDDoc defines how its controlling entity can be messaged by other agents for a given relationship. + +A DID can be resolved to get its corresponding DIDDoc by any agent that needs access to the DIDDoc. This is true whether talking about a public DID published on a Public Ledger, or a non-public DID that is only shared between participants in a relationship. In the case of a non-public DID, it's the (implementation specific) domain's responsibility to ensure that the DIDDoc associated with the DID is available (resolvable) to all Agents requiring it. -A DID can be resolved to get its corresponding DIDDoc by any Agent that needs access to the DIDDoc. This is true whether talking about a DID on the Public Ledger, or a DID persisted to a microledger. In the case of a microledger, it's the (implementation specific) domain's responsibility to ensure such resolution is available to all Agents requiring it. +### DIDDoc Service Conventions + +In order to be able to communicate with an Indy agent using DID infrastructure, the underlying conventions that host this communication must be standardised in the DIDDoc. + +Within the [DID Specification](https://w3c-ccg.github.io/did-spec/#did-documents) lies a section called [Service Endpoints](https://w3c-ccg.github.io/did-spec/#service-endpoints), this section of the DIDDoc is reserved for `any type of service the entity wishes to advertise, including decentralized identity management services for further discovery, authentication, authorization, or interaction`. + +This HIPE introduces the specification of a new DID service endpoint type called `IndyAgent`, which takes the following form. + +```json +{ + "service": [{ + "id": "did:example:123456789abcdefghi;indy-agent", + "type": "IndyAgent", + "priority" : 0, + "recipientKeys" : [ "did:example:123456789abcdefghi#1" ], + "mediatorKeys" : [ "did:example:123456789abcdefghi#1" ], + "serviceEndpoint": "https://agent.example.com/" + }] +} +``` + +- id : Required by the [Service Endpoints Spec](https://w3c-ccg.github.io/did-spec/#service-endpoints). +- type : Required by the [Service Endpoints Spec](https://w3c-ccg.github.io/did-spec/#service-endpoints). +- priority : This represents the priority of the service endpoint, used for distinction when multiple `IndyAgent` service endpoints are present in a single DIDDoc. +- recipientKeys : This is an array of did key references used to denote the default recipients of an endpoint. +- mediatorKeys: This is an array of did key references used to denote the mediators in between the sender and recipients +- serviceEndpoint : Required by the [Service Endpoints Spec](https://w3c-ccg.github.io/did-spec/#service-endpoints). + +#### Message Preperation Conventions + +1. Resolve the relevant `IndyAgent` service of the DIDDoc. +2. Take the raw message the sender would like to send and pack it for the recipient keys listed in the service definition. +3. If the `routingKeys` array is empty then go to step 5. Otherwise for each key: + 1. Pack the message from the previous step with the key of the current entry in the `routingKeys` array. + 2. Prepare a `forward_to_key` message for the current entry in the `routingKeys` array, where the message is the `pack()`'d message from the previous step. +4. Resolve the service endpoint: + 5. If it is a valid endpoint URI, send the resulting message in accordance with the URI's protocol. + 6. If the service endpoint resolves to another service endpoint (i.e like the below example with agents-r-us), resolve this service endpoint and repeat this process from the beginning. + +> Notes +> For step 1. there are two main situations that an agent will be in prior to preparing a new message. + >1. The agent is responding to a message that has just been recieved and has the context of the sender key of the previous message. + >2. The agent is creating a new message to a connection and will use the default `IndyAgent` service convention for preperation of a message. +> With case 1. A targeted lookup of the `IndyAgent` service definition could be done to find a service definition that features the sender key as a recipient key which would ensure that the response was delivered back to the sender. +> With case 2. The default `IndyAgent` service description would be used by resolving the lowest priority service definition from the connections DID doc* ### Example: Domain and DIDDoc -The following is an example of an arbitrary pair of domains that will be helpful in defining the requirements in this HIPE. +The following is an example of an arbitrary pair of domains that will be helpful in providing context to conventions defined above. ![Example Domains: Alice and Bob](domains.jpg) @@ -81,109 +116,83 @@ In the diagram above: - Alice has - 1 Edge Agent - "1" - - 1 Routing Agent - "2" + - 1 Cloud Agent - "2" - 1 Domain Endpoint - "8" - Bob has - - 3 Edge Agents - "4", "5" and "6" - - "6" is an Edge Agent in the cloud, "4" and "5" are physical devices. - - 1 Routing Agent - "3" + - 2 Edge Agents - "4", "5" + - 2 Cloud Agents - "3", "6" - 1 Domain Endpoint - "9" #### Bob's DIDDoc for his Relationship with Alice -Bob’s domain has 3 devices he uses for processing messages - two phones (4 and 5) and a cloud-based agent (6). However, in Bob's relationship with Alice, he ONLY uses one phone (4) and the cloud-based agent (6). Thus the key for device 5 is left out of the DIDDoc (see below). - -Note that the key for the Routing Agent (3) is called "routing". This is an example of the kind of convention needed to allow the Sender's agents to know the keys for Agents with a designated role in the receiving domain. +Bob’s domain has 3 devices he uses for processing messages - two phones (4 and 5) and a cloud-based agent (6). As well, Bob has one agent that he uses as a mediator (3) that can hold messages for the two phones when they are offline. However, in Bob's relationship with Alice, he ONLY uses one phone (4) and the cloud-based agent (6). Thus the key for device 5 is left out of the DIDDoc (see below). For further privacy preservation, Bob also elects to use a shared domain endpoint (agents-r-us), giving him an extra layer of isolation from correlation. This is represented by the `serviceEndpoint` in the service definition not directly resolving to a endpoint URI rather resolving to another `IndyAgent` service description which is owned and controlled by the endpoint owner (agents-r-us). ```json { "@context": "https://w3id.org/did/v1", - "id": "did:sov:1234abcd", + "id": "did:example:1234abcd", "publicKey": [ - {"id": "routing", "type": "RsaVerificationKey2018", "owner": "did:sov:1234abcd","publicKeyPem": "-----BEGIN PUBLIC X…"}, - {"id": "4", "type": "RsaVerificationKey2018", "owner": "did:sov:1234abcd","publicKeyPem": "-----BEGIN PUBLIC 9…"}, - {"id": "6", "type": "RsaVerificationKey2018", "owner": "did:sov:1234abcd","publicKeyPem": "-----BEGIN PUBLIC A…"} + {"id": "3", "type": "RsaVerificationKey2018", "owner": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC X…"}, + {"id": "4", "type": "RsaVerificationKey2018", "owner": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC 9…"}, + {"id": "6", "type": "RsaVerificationKey2018", "owner": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC A…"} ], "authentication": [ - {"type": "RsaSignatureAuthentication2018", "publicKey": "did:sov:1234abcd#4"} + {"type": "RsaSignatureAuthentication2018", "publicKey": "did:example:1234abcd#4"} ], "service": [ - {"type": "Agency", "serviceEndpoint": "did:sov:fghi8377464" } - // or "serviceEndpoint": "https://example.com/endpoint/8377464" and add the #domain key (above) + { + "id": "did:example:123456789abcdefghi;indy-agent", + "type": "IndyAgent", + "priority" : 0, + "recipientKeys" : [ "did:example:1234abcd#4" ], + "mediatorKeys" : [ "did:example:1234abcd#3" ], + "serviceEndpoint" : "did:example:xd45fr567794lrzti67;indy-agent" + } ] } ``` -### Cross Domain Messaging Interoperability - -A key goal for interoperability is that we want other domains to know just enough about the configuration of a domain to which they are delivering a message, but no more. The Cross Domain Messaging HIPE (*reference to be added*), outlines the details of sending the message. Briefly: - -- The Sender creates the message (m[1]) to be processed by the Receiver. -- The Sender encrypts m[1] into a `Forward` message (m[2]) addressed to the Receiver, providing in the `to` the DID#keyname of the Receiver (e.g. did#1) -- The Sender encrypts m[2] into a `Forward` message (m[3]) implicitly addressed to the Receiver's Routing Agent, providing in the `to` the DID of the Receiver (e.g. did). - - "implicit" in that the Receiver's shared Domain Endpoint handler MUST be implemented to proxy any message to "did" to the Routing Agent -- An Agent of the Sender sends m[3] as a Wire Message to the shared Domain Endpoint of the Receiver. - -### Necessary DIDDoc Information - -To accomplish the Cross Domain Messaging sequence listed in the previous section, the Sending Agent MUST be able to elicit from the DIDDoc: - -- the public key and endpoint of the shared Domain Endpoint for the Receiver -- the public key of the Receiver's Routing Agent -- the public key and the "address" (e.g. #keyname fragment) of the Receiver. - -In addition, a holder of a DIDDoc replica MUST also be able to determine from the DIDDoc the public key needed to update the DIDDoc for the DID. A holder of a DIDDoc replica could be the Public Ledger for a publicly resolvable DID or the manager of a microledger on which the state of the DIDDoc is persisted. - -We'll consider how that information is known for each. - -#### The *Shared* Domain Endpoint +Agents r Us DIDDoc -In the model we've defined for interoperability, the Domain Endpoint for the Receiver is assumed to be a shared endpoint that handles incoming messages for many Identities and for each, many DIDs. This definition works for the expected common case, where Domain Endpoints are Agencies operated by Cloud Vendors, but can also work in the degenerate case of an Identity (person or enterprise) hosting its own Agents. The expected case is preferred as it is seen as more privacy preserving, as Identities can "hide in the crowd". There are so many almost identical messages coming to the physical endpoint for so many different Identities that it is extremely difficult to associate an individual message to a specific Identity. This is not possible if each Identity has it's own physical endpoint. - -As such, in the expected case, the Domain Endpoint is owned and controlled by a different Identity (the Agency) from the Receiver. That in turn suggests that the Domain Endpoint should not be just a pair of values (public key and physical endpoint) in many pairwise DIDDocs, but rather a separate DID controlled by the Agency. Since a DID is a URI, the Domain Endpoint DID can be put into the pairwise DIDDoc of the Receiver as a `service_endpoint`. Since the Domain Endpoint is a well-known address (e.g. https://endpoint.AgentsRUs.com), the DID should be public and resolvable on a public ledger. - -This approach allows the Agency to rotate the keys for the endpoint when necessary without requiring updates be made to the DIDDocs created by the users of the Agency. If the DIDDocs of every Agency user contain the actual endpoint and public key of the Domain Endpoint, every DIDDoc created in the Agency would have to be updated when the Domain Endpoint public key is rotated (or the endpoint is changed). - -By referencing a DID as the endpoint, the DIDDocs of DIDs owned by users of the Agency would only need to be updated when changing the Domain Endpoint for a relationship - such as when changing Agencies. Such events are likely to be far rarer than rotating the key of the Domain Endpoint. - -This approach requires that Agents know that when an endpoint in a DIDDoc is a DID, they MUST resolve that DID to retrieve the actual endpoint and public key. - -#### The Routing Agent - -For the Routing Agent, we don't need a physical address of the endpoint of the agent in a DIDDoc since no cross domain messages will ever be directly addressed to the Routing Agent. Further, any Agents within the domain that need to send messages to the Routing Agent (including the shared Domain Endpoint) will know the physical address of the Routing Agent. All we need is for the Sender to know the public key of the Routing Agent. - -As such, **all** DIDDocs to be used for receiving Agent Messages MUST have an identifiable key that is the Routing Agent. By convention, this HIPE defines that the name of the Routing Agent key in the DIDDoc MUST be "`routing`". The JSON snippet for that key will look like this: - -``` +```json { - "id": "routing", - "type": "RsaVerificationKey2018", - "owner": "did:sov:1234abcd", - "publicKeyPem": "-----BEGIN PUBLIC X…" -},... + "@context": "https://w3id.org/did/v1", + "id": "did:example:xd45fr567794lrzti67", + "publicKey": [ + {"id": "1", "type": "RsaVerificationKey2018", "owner": "did:example:xd45fr567794lrzti67","publicKeyPem": "-----BEGIN PUBLIC X…"}, + ], + "authentication": [ + {"type": "RsaSignatureAuthentication2018", "publicKey": "did:example:xd45fr567794lrzti67#1"} + ], + "service": [ + { + "id": "did:example:xd45fr567794lrzti67;indy-agent", + "type": "IndyAgent", + "priority" : 0, + "recipientKeys" : [ "did:example:xd45fr567794lrzti67#1" ], + "mediatorKeys" : [ ], + "serviceEndpoint" : "http://agents-r-us.com" + } + ] +} ``` -##### Routing Agent Public Keys - -To prevent correlation, the Routing Agent SHOULD generate a new public key for each DID that is to be used for receiving Agent Messages. - -#### Agent Message Receiver - -Based on the previous two sections, a Sending Domain knows how deliver a `Forward` message addressed to the Receiver's Routing Agent to the shared Domain Endpoint using a Wire Message. The Routing Agent can decrypt the message addressed to it, and then determine where to deliver the message contained within it (also a `Forward`) intended for the Receiver. That message can be addressed to any #keyname in the DIDDoc, including the `#routing` that is controlled by the Routing Agent. - -How the Sender determines to which #keyname (and hence Agent/device) in the DIDDoc to send the message is a topic for a separate HIPE. In many cases, a Sender will simply be replying to a message sent from a specific #keyname address, and so the same #keyname would be used. However, when the Sender is initiating a conversation, it is not as obvious to whom the message should be sent. Other scenarios like changing the Agent handling a conversation mid-stream will also need to be addressed. - -#### DIDDoc Update Authorization - -The ability to update a DIDDoc requires the Identity owner prove control of the DID. A public key in the DIDDoc is used to prove ownership to support updating the DIDDoc. The choice of Agent(s) within a domain that are empowered to send DIDDoc updates is an implementation-specific tactic. For example, an implementation might require Agents within the Domain send their updates to an empowered Agent to aggregate the changes and replicate those changes to the published copies of the DIDDoc on a public ledger or a microledger. - -It is not clear in the DID Spec or in this HIPE (yet) what keys empower an Agent to make updates to the manifestation of the DIDDoc. +#### Message Preperation Example -#### Degenerate Cases +Alices agent goes to prepare a message `desired_msg` for Bob agent. -As discussed above, the DIDDoc for a domain MUST look as if there are at least four Agents in the domain, and there could be many more. However, what if there are only 2 or even 1 Agent in a domain? +> Stephen: Which of Bob's agents? I think that should be a parameter going into this - e.g. Agent #4. -The HIPE requirement in those degenerate cases is that the DIDDoc still contain the same data (one endpoint, one `routing` key, one authentication key and at least one Receiver key). The domain implementation then handles the case of "Agents with multiple roles". The DIDDoc SHOULD have the Agents use different keys for different purposes to mask the simplified Agent structure. +1. Alices agent resolves the above DID doc Bobs agent has shared with her and resolves the `IndyAgent` service definition. +2. Alices agent then packs the desired message she wishes to trasmit with the keys noted in the `recipientKeys` array. + `pack(wallet,desired_msg,[did-resolve(did:example:1234abcd#4)],sender_verkey)` +3. Because the the `routingKeys` array is not empty, the message is then wrapped inside a forward to keys message where the subject is the contents of the `recipientKeys` array resolved to raw key values. +4. The resulting message from the previous step is then packed for the first and only key in the `routingKeys` array. + `pack(wallet,wrapped_message,[did-resolve(did:example:1234abcd#3)],sender_verkey)` +5. Resolution of the service endpoint leads to resolving another `IndyAgent` service definition, this time owned and controlled by `agents-r-us`. +6. Because in the `agents-r-us` service definition there is a recipient key. The newly packed message is then wrapped in another forward to key message where the subject is first and only key in the `routingKeys` array. +7. This wrapped message is then packed in a message for the keys noted in the `recipientKeys` array of the `agents-r-us` `IndyAgent` service defintion. +8. Finally as the endpoint listed in the serviceEndpoint field for the `agents-r-us` `IndyAgent` service definition is a valid endpoint URI, the message is tramitted in accordance with the URI's protocol. ## Reference [reference]: #reference @@ -206,11 +215,9 @@ N/A The following remain unresolved: -- The use of "routing" for the key name of the Routing Agent seems arbitrary. Is there a good reason to use that name vs. any other? - - Since all DIDDocs should have a "routing" key, it does not expose anything about the domain so it would appear to be as good as any other name. -- If "DID as endpoint" convention is NOT used, the endpoint and key for the shared Domain Endpoint must be explicitly placed into the Receiver's DIDDoc, and a clear convention is needed for determining which key is for the Domain Endpoint. -- If there are multiple endpoints in the DIDDoc, the Sender must know which endpoint is for the shared Domain Endpoint. Should a convention like that for the "routing" key be used? -- It may be appropriate to have a convention in the DIDDoc to designate which keys (and potentially, endpoints) are used for different roles in the Domain. For example: +- The name of the service definition `IndyAgent` is perhaps in appropriate considering the impending hyperledger project reshuffle. +- The convention for packing the message for the required routes is dependent on the array order of key references, which could be viewed as a weak/brittle convention. +- It may be appropriate to have a convention in the DIDDoc to designate which keys (and potentially, endpoints) are used for different roles beyond receivers and mediators in the Domain. For example: - A defined list of roles. - A convention for determining the roles associated with a key. - As noted in the DIDDoc Update Authorization section (above) for example, it is not clear in the DID Spec or in this HIPE (yet) what keys empower an Agent to make updates to the manifestation of the DIDDoc. \ No newline at end of file From 1d31c50567502c539ed450a534c453b6b2267d7d Mon Sep 17 00:00:00 2001 From: Tobias Looker Date: Wed, 13 Feb 2019 09:30:59 -0800 Subject: [PATCH 2/5] Minor updates Signed-off-by: Tobias Looker --- text/0023-diddoc-conventions/README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/text/0023-diddoc-conventions/README.md b/text/0023-diddoc-conventions/README.md index 99a57d5a2..63e8b2282 100644 --- a/text/0023-diddoc-conventions/README.md +++ b/text/0023-diddoc-conventions/README.md @@ -88,21 +88,21 @@ This HIPE introduces the specification of a new DID service endpoint type called - mediatorKeys: This is an array of did key references used to denote the mediators in between the sender and recipients - serviceEndpoint : Required by the [Service Endpoints Spec](https://w3c-ccg.github.io/did-spec/#service-endpoints). -#### Message Preperation Conventions +#### Message Preparation Conventions 1. Resolve the relevant `IndyAgent` service of the DIDDoc. 2. Take the raw message the sender would like to send and pack it for the recipient keys listed in the service definition. -3. If the `routingKeys` array is empty then go to step 5. Otherwise for each key: - 1. Pack the message from the previous step with the key of the current entry in the `routingKeys` array. - 2. Prepare a `forward_to_key` message for the current entry in the `routingKeys` array, where the message is the `pack()`'d message from the previous step. +3. If the `mediatorKeys` array is empty then go to step 5. Otherwise for each key: + 1. Pack the message from the previous step with the key of the current entry in the `mediatorKeys` array. + 2. Prepare a `forward_to_key` message for the current entry in the `mediatorKeys` array, where the message is the `pack()`'d message from the previous step. 4. Resolve the service endpoint: 5. If it is a valid endpoint URI, send the resulting message in accordance with the URI's protocol. 6. If the service endpoint resolves to another service endpoint (i.e like the below example with agents-r-us), resolve this service endpoint and repeat this process from the beginning. > Notes > For step 1. there are two main situations that an agent will be in prior to preparing a new message. - >1. The agent is responding to a message that has just been recieved and has the context of the sender key of the previous message. - >2. The agent is creating a new message to a connection and will use the default `IndyAgent` service convention for preperation of a message. + >1. The agent is responding to a message that has just been received and has the context of the sender key of the previous message. + >2. The agent is creating a new message to a connection and will use the default `IndyAgent` service convention for preparation of a message. > With case 1. A targeted lookup of the `IndyAgent` service definition could be done to find a service definition that features the sender key as a recipient key which would ensure that the response was delivered back to the sender. > With case 2. The default `IndyAgent` service description would be used by resolving the lowest priority service definition from the connections DID doc* @@ -177,20 +177,18 @@ Agents r Us DIDDoc } ``` -#### Message Preperation Example +#### Message Preparation Example Alices agent goes to prepare a message `desired_msg` for Bob agent. -> Stephen: Which of Bob's agents? I think that should be a parameter going into this - e.g. Agent #4. - 1. Alices agent resolves the above DID doc Bobs agent has shared with her and resolves the `IndyAgent` service definition. 2. Alices agent then packs the desired message she wishes to trasmit with the keys noted in the `recipientKeys` array. `pack(wallet,desired_msg,[did-resolve(did:example:1234abcd#4)],sender_verkey)` -3. Because the the `routingKeys` array is not empty, the message is then wrapped inside a forward to keys message where the subject is the contents of the `recipientKeys` array resolved to raw key values. -4. The resulting message from the previous step is then packed for the first and only key in the `routingKeys` array. +3. Because the the `mediatorKeys` array is not empty, the message is then wrapped inside a forward to keys message where the subject is the contents of the `recipientKeys` array resolved to raw key values. +4. The resulting message from the previous step is then packed for the first and only key in the `mediatorKeys` array. `pack(wallet,wrapped_message,[did-resolve(did:example:1234abcd#3)],sender_verkey)` 5. Resolution of the service endpoint leads to resolving another `IndyAgent` service definition, this time owned and controlled by `agents-r-us`. -6. Because in the `agents-r-us` service definition there is a recipient key. The newly packed message is then wrapped in another forward to key message where the subject is first and only key in the `routingKeys` array. +6. Because in the `agents-r-us` service definition there is a recipient key. The newly packed message is then wrapped in another forward to key message where the subject is first and only key in the `mediatorKeys` array. 7. This wrapped message is then packed in a message for the keys noted in the `recipientKeys` array of the `agents-r-us` `IndyAgent` service defintion. 8. Finally as the endpoint listed in the serviceEndpoint field for the `agents-r-us` `IndyAgent` service definition is a valid endpoint URI, the message is tramitted in accordance with the URI's protocol. From 5bb995cb4e0c9584596638ce310b4661dfc9878d Mon Sep 17 00:00:00 2001 From: Tobias Looker Date: Tue, 26 Feb 2019 08:47:42 +1300 Subject: [PATCH 3/5] PR Updates Signed-off-by: Tobias Looker --- text/0023-diddoc-conventions/README.md | 55 +++++++++++++------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/text/0023-diddoc-conventions/README.md b/text/0023-diddoc-conventions/README.md index 63e8b2282..599211c30 100644 --- a/text/0023-diddoc-conventions/README.md +++ b/text/0023-diddoc-conventions/README.md @@ -8,12 +8,12 @@ ## Summary [summary]: #summary -This is one of a series of HIPEs that together enable interoperability across implementations of Hyperledger Indy Agents and ideally in the future, agents rooted in other self-sovereign identity ecosystems. +This is one of a series of HIPEs that together enable interoperability across implementations of DID based identity agents and ideally in the future, agents rooted in other self-sovereign identity ecosystems. ## Motivation [motivation]: #motivation -In this HIPE the use of the DIDDocs and in particular some associated conventions are defined that enable standardised communication between with indy agents. +In this HIPE the use of the DIDDocs and in particular some associated conventions are defined that enable standardised communication between with DID based identity agents. ## Tutorial [tutorial]: #tutorial @@ -62,20 +62,20 @@ A DID can be resolved to get its corresponding DIDDoc by any agent that needs ac ### DIDDoc Service Conventions -In order to be able to communicate with an Indy agent using DID infrastructure, the underlying conventions that host this communication must be standardised in the DIDDoc. +In order to be able to communicate with an DID based identity agent using DID infrastructure, the underlying conventions that host this communication must be standardised in the DIDDoc. Within the [DID Specification](https://w3c-ccg.github.io/did-spec/#did-documents) lies a section called [Service Endpoints](https://w3c-ccg.github.io/did-spec/#service-endpoints), this section of the DIDDoc is reserved for `any type of service the entity wishes to advertise, including decentralized identity management services for further discovery, authentication, authorization, or interaction`. -This HIPE introduces the specification of a new DID service endpoint type called `IndyAgent`, which takes the following form. +This HIPE introduces the specification of a new DID service endpoint type called `DidMessaging`, which takes the following form. ```json { "service": [{ "id": "did:example:123456789abcdefghi;indy-agent", - "type": "IndyAgent", + "type": "DidMessaging", "priority" : 0, "recipientKeys" : [ "did:example:123456789abcdefghi#1" ], - "mediatorKeys" : [ "did:example:123456789abcdefghi#1" ], + "routingKeys" : [ "did:example:123456789abcdefghi#1" ], "serviceEndpoint": "https://agent.example.com/" }] } @@ -83,18 +83,18 @@ This HIPE introduces the specification of a new DID service endpoint type called - id : Required by the [Service Endpoints Spec](https://w3c-ccg.github.io/did-spec/#service-endpoints). - type : Required by the [Service Endpoints Spec](https://w3c-ccg.github.io/did-spec/#service-endpoints). -- priority : This represents the priority of the service endpoint, used for distinction when multiple `IndyAgent` service endpoints are present in a single DIDDoc. +- priority : This represents the priority of the service endpoint, used for distinction when multiple `DidMessaging` service endpoints are present in a single DIDDoc. - recipientKeys : This is an array of did key references used to denote the default recipients of an endpoint. -- mediatorKeys: This is an array of did key references used to denote the mediators in between the sender and recipients +- routingKeys: This is an array, ordered from most srcward to most destward, of did key references used to denote the individual hops in between the sender and recipients - serviceEndpoint : Required by the [Service Endpoints Spec](https://w3c-ccg.github.io/did-spec/#service-endpoints). #### Message Preparation Conventions -1. Resolve the relevant `IndyAgent` service of the DIDDoc. +1. Resolve the relevant `DidMessaging` service of the DIDDoc. 2. Take the raw message the sender would like to send and pack it for the recipient keys listed in the service definition. -3. If the `mediatorKeys` array is empty then go to step 5. Otherwise for each key: - 1. Pack the message from the previous step with the key of the current entry in the `mediatorKeys` array. - 2. Prepare a `forward_to_key` message for the current entry in the `mediatorKeys` array, where the message is the `pack()`'d message from the previous step. +3. If the `routingKeys` array is empty then go to step 5. Otherwise for each key: + 1. Pack the message from the previous step with the key of the current entry in the `routingKeys` array. + 2. Prepare a `forward_to_key` message for the current entry in the `routingKeys` array, where the message is the `pack()`'d message from the previous step. 4. Resolve the service endpoint: 5. If it is a valid endpoint URI, send the resulting message in accordance with the URI's protocol. 6. If the service endpoint resolves to another service endpoint (i.e like the below example with agents-r-us), resolve this service endpoint and repeat this process from the beginning. @@ -102,9 +102,9 @@ This HIPE introduces the specification of a new DID service endpoint type called > Notes > For step 1. there are two main situations that an agent will be in prior to preparing a new message. >1. The agent is responding to a message that has just been received and has the context of the sender key of the previous message. - >2. The agent is creating a new message to a connection and will use the default `IndyAgent` service convention for preparation of a message. -> With case 1. A targeted lookup of the `IndyAgent` service definition could be done to find a service definition that features the sender key as a recipient key which would ensure that the response was delivered back to the sender. -> With case 2. The default `IndyAgent` service description would be used by resolving the lowest priority service definition from the connections DID doc* + >2. The agent is creating a new message to a connection and will use the default `DidMessaging` service convention for preparation of a message. +> With case 1. A targeted lookup of the `DidMessaging` service definition could be done to find a service definition that features the sender key as a recipient key which would ensure that the response was delivered back to the sender. +> With case 2. The default `DidMessaging` service description would be used by resolving the lowest priority service definition from the connections DID doc* ### Example: Domain and DIDDoc @@ -125,7 +125,7 @@ In the diagram above: #### Bob's DIDDoc for his Relationship with Alice -Bob’s domain has 3 devices he uses for processing messages - two phones (4 and 5) and a cloud-based agent (6). As well, Bob has one agent that he uses as a mediator (3) that can hold messages for the two phones when they are offline. However, in Bob's relationship with Alice, he ONLY uses one phone (4) and the cloud-based agent (6). Thus the key for device 5 is left out of the DIDDoc (see below). For further privacy preservation, Bob also elects to use a shared domain endpoint (agents-r-us), giving him an extra layer of isolation from correlation. This is represented by the `serviceEndpoint` in the service definition not directly resolving to a endpoint URI rather resolving to another `IndyAgent` service description which is owned and controlled by the endpoint owner (agents-r-us). +Bob’s domain has 3 devices he uses for processing messages - two phones (4 and 5) and a cloud-based agent (6). As well, Bob has one agent that he uses as a mediator (3) that can hold messages for the two phones when they are offline. However, in Bob's relationship with Alice, he ONLY uses one phone (4) and the cloud-based agent (6). Thus the key for device 5 is left out of the DIDDoc (see below). For further privacy preservation, Bob also elects to use a shared domain endpoint (agents-r-us), giving him an extra layer of isolation from correlation. This is represented by the `serviceEndpoint` in the service definition not directly resolving to a endpoint URI rather resolving to another `DidMessaging` service description which is owned and controlled by the endpoint owner (agents-r-us). ```json { @@ -142,10 +142,10 @@ Bob’s domain has 3 devices he uses for processing messages - two phones (4 and "service": [ { "id": "did:example:123456789abcdefghi;indy-agent", - "type": "IndyAgent", + "type": "DidMessaging", "priority" : 0, "recipientKeys" : [ "did:example:1234abcd#4" ], - "mediatorKeys" : [ "did:example:1234abcd#3" ], + "routingKeys" : [ "did:example:1234abcd#3" ], "serviceEndpoint" : "did:example:xd45fr567794lrzti67;indy-agent" } ] @@ -167,10 +167,10 @@ Agents r Us DIDDoc "service": [ { "id": "did:example:xd45fr567794lrzti67;indy-agent", - "type": "IndyAgent", + "type": "DidMessaging", "priority" : 0, "recipientKeys" : [ "did:example:xd45fr567794lrzti67#1" ], - "mediatorKeys" : [ ], + "routingKeys" : [ ], "serviceEndpoint" : "http://agents-r-us.com" } ] @@ -181,16 +181,16 @@ Agents r Us DIDDoc Alices agent goes to prepare a message `desired_msg` for Bob agent. -1. Alices agent resolves the above DID doc Bobs agent has shared with her and resolves the `IndyAgent` service definition. +1. Alices agent resolves the above DID doc Bobs agent has shared with her and resolves the `DidMessaging` service definition. 2. Alices agent then packs the desired message she wishes to trasmit with the keys noted in the `recipientKeys` array. `pack(wallet,desired_msg,[did-resolve(did:example:1234abcd#4)],sender_verkey)` -3. Because the the `mediatorKeys` array is not empty, the message is then wrapped inside a forward to keys message where the subject is the contents of the `recipientKeys` array resolved to raw key values. -4. The resulting message from the previous step is then packed for the first and only key in the `mediatorKeys` array. +3. Because the the `routingKeys` array is not empty, the message is then wrapped inside a forward to keys message where the subject is the contents of the `recipientKeys` array resolved to raw key values. +4. The resulting message from the previous step is then packed for the first and only key in the `routingKeys` array. `pack(wallet,wrapped_message,[did-resolve(did:example:1234abcd#3)],sender_verkey)` -5. Resolution of the service endpoint leads to resolving another `IndyAgent` service definition, this time owned and controlled by `agents-r-us`. -6. Because in the `agents-r-us` service definition there is a recipient key. The newly packed message is then wrapped in another forward to key message where the subject is first and only key in the `mediatorKeys` array. -7. This wrapped message is then packed in a message for the keys noted in the `recipientKeys` array of the `agents-r-us` `IndyAgent` service defintion. -8. Finally as the endpoint listed in the serviceEndpoint field for the `agents-r-us` `IndyAgent` service definition is a valid endpoint URI, the message is tramitted in accordance with the URI's protocol. +5. Resolution of the service endpoint leads to resolving another `DidMessaging` service definition, this time owned and controlled by `agents-r-us`. +6. Because in the `agents-r-us` service definition there is a recipient key. The newly packed message is then wrapped in another forward to key message where the subject is first and only key in the `routingKeys` array. +7. This wrapped message is then packed in a message for the keys noted in the `recipientKeys` array of the `agents-r-us` `DidMessaging` service defintion. +8. Finally as the endpoint listed in the serviceEndpoint field for the `agents-r-us` `DidMessaging` service definition is a valid endpoint URI, the message is tramitted in accordance with the URI's protocol. ## Reference [reference]: #reference @@ -213,7 +213,6 @@ N/A The following remain unresolved: -- The name of the service definition `IndyAgent` is perhaps in appropriate considering the impending hyperledger project reshuffle. - The convention for packing the message for the required routes is dependent on the array order of key references, which could be viewed as a weak/brittle convention. - It may be appropriate to have a convention in the DIDDoc to designate which keys (and potentially, endpoints) are used for different roles beyond receivers and mediators in the Domain. For example: - A defined list of roles. From b41fa4d3f631816b90417b49674abac30b1b6779 Mon Sep 17 00:00:00 2001 From: Tobias Looker Date: Tue, 26 Feb 2019 08:52:22 +1300 Subject: [PATCH 4/5] Further PR Updates Signed-off-by: Tobias Looker --- text/0023-diddoc-conventions/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0023-diddoc-conventions/README.md b/text/0023-diddoc-conventions/README.md index 599211c30..452a10ca2 100644 --- a/text/0023-diddoc-conventions/README.md +++ b/text/0023-diddoc-conventions/README.md @@ -132,9 +132,9 @@ Bob’s domain has 3 devices he uses for processing messages - two phones (4 and "@context": "https://w3id.org/did/v1", "id": "did:example:1234abcd", "publicKey": [ - {"id": "3", "type": "RsaVerificationKey2018", "owner": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC X…"}, - {"id": "4", "type": "RsaVerificationKey2018", "owner": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC 9…"}, - {"id": "6", "type": "RsaVerificationKey2018", "owner": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC A…"} + {"id": "3", "type": "RsaVerificationKey2018", "controller": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC X…"}, + {"id": "4", "type": "RsaVerificationKey2018", "controller": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC 9…"}, + {"id": "6", "type": "RsaVerificationKey2018", "controller": "did:example:1234abcd","publicKeyPem": "-----BEGIN PUBLIC A…"} ], "authentication": [ {"type": "RsaSignatureAuthentication2018", "publicKey": "did:example:1234abcd#4"} @@ -159,7 +159,7 @@ Agents r Us DIDDoc "@context": "https://w3id.org/did/v1", "id": "did:example:xd45fr567794lrzti67", "publicKey": [ - {"id": "1", "type": "RsaVerificationKey2018", "owner": "did:example:xd45fr567794lrzti67","publicKeyPem": "-----BEGIN PUBLIC X…"}, + {"id": "1", "type": "RsaVerificationKey2018", "controller": "did:example:xd45fr567794lrzti67","publicKeyPem": "-----BEGIN PUBLIC X…"}, ], "authentication": [ {"type": "RsaSignatureAuthentication2018", "publicKey": "did:example:xd45fr567794lrzti67#1"} From f5726a3cf1c8bdd601a7ea29ffb4a9ad33969f89 Mon Sep 17 00:00:00 2001 From: Tobias Looker Date: Tue, 26 Feb 2019 09:20:44 +1300 Subject: [PATCH 5/5] Further PR Updates Signed-off-by: Tobias Looker --- text/0023-diddoc-conventions/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0023-diddoc-conventions/README.md b/text/0023-diddoc-conventions/README.md index 452a10ca2..82d9b02a2 100644 --- a/text/0023-diddoc-conventions/README.md +++ b/text/0023-diddoc-conventions/README.md @@ -71,7 +71,7 @@ This HIPE introduces the specification of a new DID service endpoint type called ```json { "service": [{ - "id": "did:example:123456789abcdefghi;indy-agent", + "id": "did:example:123456789abcdefghi;did-messaging", "type": "DidMessaging", "priority" : 0, "recipientKeys" : [ "did:example:123456789abcdefghi#1" ], @@ -141,12 +141,12 @@ Bob’s domain has 3 devices he uses for processing messages - two phones (4 and ], "service": [ { - "id": "did:example:123456789abcdefghi;indy-agent", + "id": "did:example:123456789abcdefghi;did-messaging", "type": "DidMessaging", "priority" : 0, "recipientKeys" : [ "did:example:1234abcd#4" ], "routingKeys" : [ "did:example:1234abcd#3" ], - "serviceEndpoint" : "did:example:xd45fr567794lrzti67;indy-agent" + "serviceEndpoint" : "did:example:xd45fr567794lrzti67;did-messaging" } ] } @@ -166,7 +166,7 @@ Agents r Us DIDDoc ], "service": [ { - "id": "did:example:xd45fr567794lrzti67;indy-agent", + "id": "did:example:xd45fr567794lrzti67;did-messaging", "type": "DidMessaging", "priority" : 0, "recipientKeys" : [ "did:example:xd45fr567794lrzti67#1" ],