├── .DS_Store ├── .gitignore ├── README.md ├── agents └── README.md ├── did-format.png ├── did.md ├── dkms ├── 01-edge-agent-start.puml ├── 02-provision-new-agent.puml ├── 03-first-edge-agent.puml ├── 04-update-agent-policy-registry.puml ├── 05-add-cloud-agent.puml ├── 06-add-new-edge-agent.puml ├── 07-add-connection-public-did.puml ├── 08-add-connection-private-did-provisioned.puml ├── 09-add-connection-private-did-unprovisioned.puml ├── 10-rotate-did-key.puml ├── 11-revoke-did.puml ├── 12-revoke-edge-agent.puml ├── 13-recovery-setup.puml ├── 14-add-recovery-buddy.puml ├── 15-recovery-update.puml ├── 16-offline-recovery.puml ├── 17-social-recovery.puml ├── C_1.png ├── DKMS Design and Architecture V3.md ├── README.md ├── aap_0.png ├── aap_1.png ├── aap_10.png ├── aap_11.png ├── aap_12.png ├── aap_13.png ├── aap_14.png ├── aap_15.png ├── aap_18.png ├── aap_19.png ├── aap_2.png ├── aap_20.png ├── aap_21.png ├── aap_22.png ├── aap_23.png ├── aap_24.png ├── aap_25.png ├── aap_26.png ├── aap_27.png ├── aap_28.png ├── aap_3.png ├── aap_4.png ├── aap_5.png ├── aap_6.png ├── aap_7.png ├── aap_8.png ├── aap_9.png ├── agency-migration.puml ├── agent-authz-policy-ledger-interactions.md ├── agent_authorization_policy.md ├── burn-identity-with-agents.puml ├── failure-modes.puml ├── image_0.png ├── image_1.png ├── image_10.png ├── image_11.png ├── image_12.png ├── image_13.png ├── image_14.png ├── image_15.png ├── image_16.png ├── image_17.png ├── image_18.png ├── image_19.png ├── image_2.png ├── image_20.png ├── image_21.png ├── image_22.png ├── image_23.png ├── image_24.png ├── image_25.png ├── image_26.png ├── image_3.png ├── image_4.png ├── image_5.png ├── image_6.png ├── image_7.png ├── image_8.png ├── image_9.png ├── mathcal_a.png ├── overview.puml ├── proof.png ├── recover-agent-policy-registry.puml ├── recover-connection.puml ├── revoke-edge-agent-success.puml ├── revoke-rogue-edge-agent.puml ├── shamir_secret.md ├── trustee_protocols.md └── zpok.png ├── janus ├── Janus_coin.png ├── README.md ├── janus.svg ├── layers.png ├── love-letter-flow.png ├── love-letters-1-640.png ├── love-letters-1.png ├── love-letters.md ├── message-inventory.md ├── message-layers.md ├── message-packaging.md ├── message-routing.md ├── message-transport.md ├── repudiation.md ├── sealed-envelope.jpg ├── security-context.md └── whisper-secret.jpg ├── jigsaw.png ├── ledger └── README.md ├── patterns ├── abstract-negotiation-seq.puml ├── negotiation-seq.puml ├── negotiation-state.puml └── protocol-patterns.md ├── privacy_by_design_granular_requirements.png ├── relationship-state-machine.md ├── self_sovereign_privacy_by_design_v1.md ├── sovereign_privacy_by_design_distilled.md ├── superseded.png ├── themis ├── README.md ├── cred-def.md ├── cred-offer.md ├── cred-request.md ├── credential.md ├── motivation.md ├── non-public-objects.md ├── proof-request-expression-language.md ├── proof-request.md ├── proof.md ├── public-objects.md ├── schema.md ├── themis.jpg ├── unlocking_seq.puml └── zklang.md └── todos.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | .project 4 | /*/.project 5 | 6 | ## Core latex/pdflatex auxiliary files: 7 | *.aux 8 | *.lof 9 | *.log 10 | *.lot 11 | *.fls 12 | *.out 13 | *.toc 14 | *.fmt 15 | *.fot 16 | *.cb 17 | *.cb2 18 | *.blg 19 | *.bbl 20 | 21 | ## Build tool auxiliary files: 22 | *.fdb_latexmk 23 | *.synctex 24 | *.synctex(busy) 25 | *.synctex.gz 26 | *.synctex.gz(busy) 27 | *.pdfsync 28 | 29 | ## generated zklang pdf files 30 | zklang/*.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![superseded](superseded.png) 2 | 3 | 4 | # The Sovrin Protocol 5 | 6 | The Sovrin Protocol is a set of standards, patterns, and tools that facilitate 7 | trusted interactions. People, institutions, and things can use this 8 | protocol to interact with one another in many different ways--but 9 | always as peers, in patterns that are easy, powerful, secure, and private. 10 | 11 | The protocol adapts to many different circumstances. it can be used on the 12 | internet, over sneakernet, or even with snail mail. 13 | 14 | The protocol is rooted in principles of Self-Sovereign Identity (SSI). Instead of 15 | having powerful institutions grant marginalized people identities based 16 | on siloed data, SSI puts identity owners in charge. They create their 17 | own identity, manage keys, and share personal data however they want, 18 | without constraints or approval from others. Nobody can take their identity 19 | away. 20 | 21 | ## Safe and Empowered Digital Interactions 22 | 23 | Alice wants to interact with many different parties. 24 | 25 | She wants to interact with minimal reliance on third parties. She wants to control her interactions such that another party cannot interfere with her interactions. 26 | 27 | Alice's digital interactions should be safe. Safe from prying eyes. Safe from services that track her without her knowledge and consent. Safe from unwanted correlation. Compromised third parties should not be able to impersonate her, or impersonate others to her. She should be safe from apps that exploit their positions of trust. Safe from disclosing more information about herself than is needed. 28 | 29 | Alice's digital interactions should be easy. Being secure should not be harder than not being secure. She shouldn't have to make a decision to be private; she should be private by default. She should have good information about the intent of interactions. Her apps should help her make good decisions about what to share and who to trust. 30 | 31 | Alice should be able to establish trust with another party with minimal reliance on third parties and minimal exchange of personal information. She should be able to make informed decisions about who is trustworthy. She should be able to share her reputation and attributes across contexts without revealing private information. Alice should have strong assurances in her digital interactions without the need for exchanging secrets and personal information. 32 | 33 | Alice's digital interactions should be essentially free, regardless of her circumstances and regardless of where she lives in the world. The cost of interactions should not be an inhibitor to interaction. Alice should not feel compelled to give up privacy in exchange for the ability to interact digitally, or compelled to exchange her personal information for services. 34 | 35 | For a more detailed discussion on these principles, see [Self-Sovereign Privacy By Design - V1](self_sovereign_privacy_by_design_v1.md). 36 | 37 | ## Three Dimensions of Self Sovereign Identity 38 | 39 | There are three orthogonal dimensions to Alice's digital identity: (1) her _**relationships**_, (2) her _**attributes**_, and (3) her _**agents**_. Separating these three dimensions allows for a clear understanding of how they interact. Conflating them confuses the proper role of actors and systems and weakens security. 40 | 41 | 42 | ### Relationships 43 | 44 | In Sovrin, identifiers are not shared across contexts. This helps protect privacy by limiting unwanted or cross-context correlation. Identifiers can be thought of as correlation handles. Correlation handles, like identifiers, are very useful within a context. Because identifiers are not shared across contexts, Alice uses a different identifier for every relationship she has. Because each relationship, or "pairing," has a different identifier, you can say that Sovrin uses pairwise identifiers. 45 | 46 | Sovrin's identifiers are DIDs. DID stands for Decentralized Identifier. (For more information, see the DID specification here: https://w3c-ccg.github.io/did-spec/). 47 | 48 | Sovrin supports groups. It can be said that a pair is just another group, a group of two. There are cases where an identifier is well known, as in the case of a public corporation. The corporation can have one or more "public" DIDs. This holds true to the constraint that identifiers are not shared across contexts, because the context of these DIDs is a public one. This is an exceptional case. Even though a person is free to create a public DID, it's important not to attach to that DID a reputation that must be carried into other contexts. 49 | 50 | 51 | ### Attributes 52 | 53 | In Sovrin, a person has two types of attributes. The first type is assertions about oneself, like "my name is Alice," or, "my favorite color is yellow." The second are asserted by others. For example, a driver license with my address on it. Essentially, this is an assertion made by the State of California that I live at this address. 54 | 55 | The party asserting some attributes about another is called an **Issuer**. When Alice holds a driver license, she can share that with Bob and Bob can examine it. If Bob believes that that driver license is authentic, and Bob trusts the State of California in its address verification processes, Bob can rely on the fact that Alice lives at 123 Oak Street. 56 | 57 | A **Credential** is a generic term to refer to a collection of attributes. A driver license is a credential. A credential allows Alice to prove to Bob that another party asserts some attributes about Alice. 58 | 59 | 60 | ### Agents 61 | 62 | In the physical world, we can speak with our mouths, sign documents with our hands, hear with our ears. In the digital world, we have software and hardware that we use to accomplish the digital equivalent. These bits of running code that operate on our behalf are called, Agents. 63 | 64 | My mobile phone can run an agent. My notebook computer can run an agent. I can ask a service provider to host an agent in the cloud. 65 | 66 | The important thing to note is an agent is owned by one person or entity. Even if I have an agent hosted by a service provider, it's still my agent. 67 | 68 | Some agents have endpoints. These agents can serve as simple message proxies or perform more sophisticated actions. 69 | 70 | There are two types of agents: Edge Agents, and Cloud Agents. 71 | 72 | 73 | 74 | Agents hold keys which are authorized for certain types of activity. This allows the Agent owner to assign low privileges to lower trust Cloud Agents, and higher privileges to higher trust Edge Agents. Some privileges may require multiple keys held by different agents, including agents of trusted associates, to perform certain types of activities. For example, perhaps a funds transfer of greater than $10,000 USD would require two of four keys (phone, tablet, notebook, and Alice's partner, Bob). 75 | 76 | Reference diagrams found here: [DIDs, Credentials and Agents slides](https://docs.google.com/presentation/d/1oz1uB7y4J6GuqlmzyRmqrAwNiQQaWXs1LuHfFayAnwI) 77 | 78 | 79 | 80 | ## The Intersections of Dimensions 81 | 82 | 83 | ### The Relationship-Attribute Plane 84 | 85 | Because Relationships and Attributes are orthogonal, an Issuer does not issue credentials to a particular DID. Remember DIDs are contextual to a relationship, and Credentials should be usable in different relationships without sharing correlation handles across relationships or contexts. 86 | 87 | Sovrin Credentials allow for an individual to dynamically generate proofs from one or more credentials as needed for any relationship, without correlation handles. This is not to say that cross-context correlation can't be done with shared attributes, but the control is in a person's hands, and the protocol does not leak correlation handles. 88 | 89 | 90 | ### The Relationship-Agent Plane 91 | 92 | Because a person or entity has multiple relationships (represented by a pair of DIDs), an agent must support multiple DIDs. 93 | 94 | Not every agent needs to be used in every relationship. The Relationship-Agent plane is represented by a "Relationship State Machine," which is implemented with a replicated microledger. Agents are authorized within the microledger so the other party (or parties) in the relationship know how to regard each agent (identified by public key). For example, a cloud agent may _not_ be authorized to sign on behalf of a person, but may be authorized to communicate GPS coordinates or be a message relay. 95 | 96 | 97 | 98 | Note, an agent does not have its own DID. DIDs are orthogonal to Agents. Agents can be identified by a local name, or by the public key used in a particular relationship. 99 | 100 | Each DID/Agent combination requires a separate key. An endpoint must be unique per relationship, so an agent must support multiple endpoints. 101 | 102 | Agents are authorized for certain types of activity _for each relationship_. This allows the Agent owner to use different agents in different contexts. 103 | 104 | 105 | ### The Agent-Attribute Plane 106 | 107 | The keys Agents have are stored in their own wallets. Wallets can hold credentials (verifiable collections of attributes). 108 | 109 | Agents have special keys that allow them to be able to generate proofs about credentials they hold. The Agent Authorization Policy is a combination of a ledger smart contract and a cryptographic accumulator that allows for proving in zero knowledge that a device is an authorized device. This allows a person or organization to have a sophisticated recovery policy and to be able to revoke a compromised agent. 110 | 111 | A person may selectively copy credentials to different agents, effectively limiting which credentials are provable from which agents. 112 | 113 | For more details about how these dimensions work together, see [How DIDs, Keys, Credentials, and Agents Work Together in Sovrin](https://docs.google.com/document/d/1hnQPEdfmAG-DnXGrDXowjc5J571pK7Ub4bWkUlzrH1Y). 114 | 115 | ## General Requirements 116 | 117 | In order to achieve the conceptual model, we need the following: 118 | 1. A Secure and private way to connect to and communicate with peers 119 | 1. A privacy-respecting ability to assert things about others and prove assertions about oneself 120 | 1. Control all her things (e.g., agent provisioning, authorization, revocation) 121 | 1. Privacy respecting value transfer that is compliant with regulation 122 | 1. Semantic Interoperability 123 | 124 | 125 | ### Secure peer-to-peer communications 126 | In order for Alice to interact securely with others, she'll need a transport-agnostic protocol that encrypts all information and ensures authentication at every level. It should allow for multi-hop communications without needing to trust intermediaries or share more information than is minimally necessary to accomplish the task. [Janus](janus/README.md) is the working name for a protocol that meets these requirements. Janus uses pairwise [DIDs](did.md) as mentioned above. 127 | 128 | Alice also needs a way to bootstrap trust and ensure she's still interacting with who she thinks she is. The Sovrin network acts as a public registry for DIDs, public keys, and endpoints. 129 | 130 | ### Privacy-respecting issuing and proving 131 | 132 | Alice needs a way to receive credentials from issuers. She also needs a way to prove that she holds a credential from a certain issuer with certain attributes or characteristics. She needs to do this in a way that doesn't share any more information than she intends. And her sharing of attributes should not result in disclosing correlation handles. [Themis](themis/README.md) is the working name for a protocol that accomplishes these requirements. 133 | 134 | The Sovrin network acts as a public registry for Credential Definitions, Schema definitions, and Issuer public keys. Issuer public keys are used to verify proofs from credentials issued. 135 | 136 | An issuer of a credential should also be able to revoke that credential. Alice should be able to prove she posesses a credential that is not revoked, without strongly identifying _which_ credential she holds. Privacy-respecting Revocation is a key to any credentialing system. 137 | 138 | The Sovrin network also acts as a public registry for Credential revocation. 139 | 140 | ### Control 141 | Alice needs to be able to exercise control over her keys and agents without interference and without permission from a third party. * [DIDs and DID Documents](did.md) provide much of that functionality. The [Relationship State Machine](relationship-state-machine.md) is a concept that allows for pairwise relationships to be established securely without an initial write to Sovrin. Microledgers are an implementation of the the Relationship State Machine concept. 142 | 143 | With Sovrin, reliance on a centralized third party is removed by design. This moves key management to the edge. It increases the responsibility of applications to properly manage keys and recovery. The [Decentralized Key Management (DKMS)](dkms/README.md) protocol outlines ways in which Alice can significantly reduce reliance on centralized third parties, while still being able to interact safely and securely. 144 | 145 | Alice needs a way to provision new agents, and revoke them remotely if they are lost or compromised, and do this without communicating with them. Agent Authorization Policies, outlined in the DKMS documents, help to ensure only trusted devices are able to prove certain things on behalf of Alice. The Sovrin network is used to store a sophisticated agent provisioning policy along with a mechanism for proving in a privacy-respecting way that the agent used is authorized. 146 | 147 | 148 | ### Privacy-respecting value transfer 149 | Alice needs to be able to send payment in interactions with others. For example, paying a fee for a Driver License. She needs a privacy respecting way to pay for transactions on the Sovrin ledger. Issuers need a way to recover some of the costs of issuing. Holders can pay Issuers, as in the case of Alice paying a fee for her driver license. Relying parties can also pay Issuers, as in the case of credit reporting agencies. All this should be done in a privacy respecting way. 150 | 151 | 152 | 153 | ### Semantic interoperability 154 | Issuers and Relying Parties should not need to have strong agreements in place, or build expensive integrations. Sovrin [Schemas](themis/schema.md) are published on the Sovrin ledger by Sovrin users. Anyone can publish a schema. 155 | 156 | Because they are public, others can see what kinds of attributes are being issued in credentials. Relying parties can adjust to those schemas, or suggest improvements to the Issuers. 157 | 158 | Issuers can see what other issuers in their ecosystem are publishing and what relying parties are accepting. They can adjust to make it easier for relying parties to accept proofs of their credentials. 159 | 160 | We believe there will be a natural and organic convergence around the most useful schemas. 161 | 162 | 163 | 164 | 171 | 172 | 173 | 174 | 175 | 176 | 185 | 186 | -------------------------------------------------------------------------------- /agents/README.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Agents 3 | Agents are dedicated to supporting one *Owner* (person or organization), which is perpendicular to modern web infrastructure and horizontal architectures in general. An agent is aligned to one and only one Owner, and everything it does is in direct support of that one Owner. 4 | 5 | Agents come in two basic flavors: (1) Edge Agents and (2) Cloud Agents. 6 | 7 | ## Edge Agents 8 | An owner's Edge Agents, also known as Local Agents, are Sovrin-aware code (perhaps in the form of an SDK) running on a device in direct control of the owner. Devices include mobile phones, tablets, PCs, and servers controlled by enterprises. 9 | 10 | ## Cloud Agents 11 | An owner's Cloud Agents are any of its agents running on hardware physically controlled by another party. -------------------------------------------------------------------------------- /did-format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/did-format.png -------------------------------------------------------------------------------- /did.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # DID 3 | 4 | A decentralized identifier is a new type of globally unique identifier which are fully under the control of the DID subject with cryptographically verifiable ownership. DID’s resolve to DID Documents in similar ways as uniform resource names (URNs) except they do not 5 | require a central registration authority, identity provider, or certificate authority. 6 | 7 | ## DID Format 8 | DIDs follow the same basic pattern as the URN specification. The key difference is that with DIDs the namespace component identifies a DID method, and a DID method specification specifies the format of the method specific identifier: 9 | ![sov_did](did-format.png "Sovrin DID Format") 10 | 11 | The Sovrin DID method namestring is sov. The identifier is the base58 encoding of a 128-bit number using the BitCoin/IPFS alphabet. For example, a Sovrin DID can generated by base58-encoding the first half of an Ed25519 verification key. 12 | 13 | ## DID Document 14 | DID infrastructure can be thought of as a global key-value database in which the database is all DID-compatible blockchains, distributed ledgers, or decentralized networks. In this virtual database, the key is a DID, and the value is a DID document. The purpose of the DID document is to describe the public keys and service endpoints necessary to bootstrap cryptographically-verifiable interactions with the identified entity. 15 | A DID and DID document are created, resolved, and managed on a system using a specific DID Method. DID methods define how DIDs work within a specific environment. All DID method specs must define the format and generation of the method-specific identifier. 16 | 17 | ## The Sovrin DID Method Spec 18 | DIDs written to the Sovrin ledger will follow the requirements defined in the [Sovrin DID method spec](https://github.com/sovrin-foundation/sovrin/blob/master/spec/did-method-spec-template.html). 19 | 20 | ## Public (Global) DIDs on Sovrin 21 | Public (Global) DIDs are created and updated in Sovrin using a [NYM](https://github.com/hyperledger/indy-node/blob/24a86c5ebf86a2aed26f12c3db0dfc6667137d11/docs/transactions.md#nym) transaction. 22 | [Code reference](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L43) to NYM transaction. 23 | -------------------------------------------------------------------------------- /dkms/01-edge-agent-start.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 200 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Edge\nAgent" as ag 20 | al -> ag: installs software and starts it 21 | 22 | ag -> al: New or existing identity wallet? 23 | alt new 24 | al -> ag: new 25 | note over al, ag #77ccff 26 | include First Edge Agent diagram 27 | end note 28 | else existing 29 | al -> ag: existing 30 | ag -> al: Add a new device or recover a lost wallet? 31 | alt add 32 | al -> ag: add 33 | note over al, ag #77ccff 34 | include Add New Edge Agent diagram 35 | end note 36 | else recover 37 | al -> ag: recover 38 | 39 | ag -> al: How would you like to recover? 40 | 41 | alt 42 | al -> ag: offline 43 | note over al, ag #77ccff 44 | include Offline Recovery diagram 45 | end note 46 | else 47 | al -> ag: social 48 | note over al, ag #77ccff 49 | include Social Recovery diagram 50 | end note 51 | end 52 | end 53 | end 54 | 55 | 56 | @enduml 57 | -------------------------------------------------------------------------------- /dkms/02-provision-new-agent.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | participant "Agent" as ea 19 | participant "Secure Element" as se 20 | participant "Wallet" as w 21 | 22 | ea -> ea: create secure element credential 23 | note right 24 | This can be a PIN or a 25 | biometric that can be used 26 | to securely access keys stored in 27 | the secure element. Multiple 28 | factors may be used as desired. 29 | end note 30 | 31 | ea -> se: request the agent policy keypair 32 | se -> se: create agent policy keys 33 | note right 34 | create Ap1-pk and Ap1-sk and 35 | encrypt with SE credential 36 | end note 37 | 38 | ea -> se: request agent-to-agent communication keypair 39 | se -> se: create agent-to-agent keys 40 | note right 41 | create AA1-vk and AA1-sk and 42 | encrypt with SE credential. 43 | These keys allow this agent to talk to other 44 | agents within Alice's domain. 45 | end note 46 | 47 | ea -> ea: create agent-to-agent ID AA1-ID 48 | ea -> w: store AA1-ID 49 | ea -> se: request for new wallet encryption key 50 | se -> se: create wallet encryption key 51 | note right 52 | create AW1-k and encrypt 53 | with SE credential 54 | end note 55 | 56 | se -> ea: AW1-k 57 | 58 | ea -> w: encrypt wallet with AW1-k 59 | 60 | @enduml 61 | -------------------------------------------------------------------------------- /dkms/03-first-edge-agent.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 200 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor "Alice" as a 19 | participant "Edge\nAgent" as ea 20 | participant Wallet as w 21 | 22 | note over a, w #f0f0e0 23 | Referenced from Edge Agent Start diagram. 24 | 25 | Wallet encrypted with key from secure element. 26 | end note 27 | 28 | == initial setup == 29 | note over a, w #77ccff 30 | include Provision New Agent diagram 31 | end note 32 | 33 | == create link secret and policy registry == 34 | 35 | ea -> ea: create link secret (ALS) 36 | ea -> w: store ALS 37 | 38 | ea -> ea: generate policy registry address **//P//** 39 | ea -> w: store **//P//** 40 | 41 | note over a, w #77ccff 42 | include Update Agent Policy Registry diagram 43 | (with all authorizations) 44 | end note 45 | 46 | == create cloud agent == 47 | 48 | note over a, w #77ccff 49 | include Add Cloud Agent diagram 50 | end note 51 | 52 | @enduml 53 | -------------------------------------------------------------------------------- /dkms/04-update-agent-policy-registry.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | participant "Agent" as ag 19 | participant "Ledger" as le 20 | ag -> le: update Ap1-pk to policy registry at **//P//**\n\ 21 | with authorizations and policy updates 22 | note right 23 | Authorizations include 24 | PROVE,REVOKE_PROVE,PROVISION_PROVE,ADMIN 25 | end note 26 | le --> le: add Ap1-pk to prover registry 27 | le -> ag: result 28 | 29 | @enduml 30 | -------------------------------------------------------------------------------- /dkms/05-add-cloud-agent.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Edge\nAgent" as ea 20 | box "Agency" 21 | participant "Agency\nAgent" as ai 22 | participant "Provisioning\nExtension" as ape 23 | participant "Routing\nExtension" as are 24 | end box 25 | 26 | note over al, are #f0f0e0 27 | Precondition: Alice's agency is chosen by the edge agent software. 28 | Alice can change the default agency later. 29 | Alice has setup her initial edge agent (see First Edge Agent). 30 | end note 31 | 32 | == create cloud agent Part 1 == 33 | 34 | ea -[#blue]> ai: register for cloud agent 35 | note right 36 | The Agency Agent initiates new cloud agents. 37 | end note 38 | 39 | ai -[#blue]> ea: request for consent 40 | ea -> al: request for consent 41 | note right 42 | Consent required may vary by legal jurisdiction and agency 43 | end note 44 | al -> ea: consent 45 | ea -> al: request for authorizations be granted to cloud agent 46 | note right 47 | As a general rule, cloud agents will have a subset of 48 | the authorizations granted to edge agents. 49 | end note 50 | al -> ea: selected authorizations 51 | ea -[#blue]> ai: consent, authorizations\nAA1-ID, AA1-vk 52 | 53 | newpage 54 | 55 | == create cloud agent Part 2 == 56 | 57 | ai -> ape: provision cloud agent for Alice 58 | note over al, are #77ccff 59 | include Provision New Agent diagram 60 | end note 61 | 62 | ai -> are: create agent endpoint for Alice 63 | 64 | ai -[#blue]> ea: AA2-ID, AA2-vk\nAp2-pk, endpoint 65 | ea -> ea: Store AA2-ID, AA2-vk, endpoint in wallet 66 | note over al, are #77ccff 67 | include Update Agent Policy Registry diagram 68 | end note 69 | 70 | @enduml 71 | -------------------------------------------------------------------------------- /dkms/06-add-new-edge-agent.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Edge\nAgent 2" as a2 20 | participant "Edge\nAgent 1" as a1 21 | 22 | note over al, a1 #f0f0e0 23 | Assumptions: Alice has chosen **existing | add new device** from options in Edge Agent Start. 24 | Edge Agent 2 has been provisioned as described in the Provision New Agent diagram. 25 | end note 26 | 27 | == add new edge agent == 28 | 29 | al -> a2: add 30 | a2 -> al: instructions for adding Agent 2 and selecting authorizations 31 | note right 32 | Multiple methods can be used for 33 | adding and authorizing a new agent 34 | end note 35 | 36 | al -> a1: add agent\n\ 37 | with selected authorizations 38 | note right 39 | This may work in either direction 40 | between the two agents 41 | end note 42 | a1 -> a1: display provisioning code for adding agent 2 43 | note left 44 | QR code, barcode, or passcode entered into agent 2 45 | end note 46 | a1 -> al: show code 47 | al -> a2: scan code from agent 1 48 | 49 | a2 -[#blue]> a1: add request, sends Ap2-pk, AA2-vk 50 | a1 -> a1: store AA2-vk in wallet 51 | a1 -> al: confirm agent 2 52 | al -> a1: yes 53 | note over a1, a2 54 | Agent 1 adds keys and authorizations for agent 2 to policy registry 55 | end note 56 | note over al, a1 #77ccff 57 | include Update Agent Policy Registry diagram 58 | end note 59 | a1 -[#blue]> a2: ALS, token data, claims 60 | note right 61 | sync data to agent 2 62 | end note 63 | a2 -> a2: store data in wallet 64 | 65 | @enduml 66 | -------------------------------------------------------------------------------- /dkms/07-add-connection-public-did.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | actor Alice as al 18 | participant "Alice's\nEdge Agent" as aea 19 | participant "Alice's\nCloud Agent" as aca 20 | participant "Org's\nCloud Agent" as oca 21 | participant "Org's\nEdge Agent" as org 22 | 23 | note over al, org #f0f0e0 24 | Private entity Alice creates a relationship with public entity Org. 25 | Preconditions: Org has a well known DID O0 registered on a public ledger 26 | and Alice's Edge Agent has this DID. 27 | end note 28 | 29 | == Connect with Public Organization Part 1 == 30 | 31 | al -> aea: add connection to Org 32 | aea -> aea: create DID, keys, and microledger (AODID, AO1-vk, AO1-sk) 33 | aea -[#blue]> aca: request cloud agent DID verification key for AODID 34 | aca->aca: create keys (AO2-vk,AO2-sk) 35 | aca-[#blue]>aea: AO2-vk 36 | aea->aea: add cloud agent DID verification key AO2-vk to microledger 37 | 38 | newpage 39 | 40 | == Connect with Public Organization Part 2 == 41 | 42 | par2 43 | aea -[#blue]> aca: connection invitation\n\ 44 | AODID, AO1-vk 45 | else 46 | aca-[#blue]>oca: \n\n\n 47 | else 48 | oca-[#blue]>org: \n\n\n 49 | 50 | org->org: create DID, keys, and microledger (OADID, OA1, OAml) 51 | org-[#blue]>oca: request agent DID verification key for OADID 52 | 53 | oca->oca: create DID keypair (OA2) 54 | oca-[#blue]>org: OA2-vk 55 | org->org: add cloud agent DID verification key OA2-vk to microledger 56 | 57 | par2 58 | org-[#blue]>oca: success with microledger deltas 59 | else 60 | oca-[#blue]>aca: \n\n success 61 | else 62 | aca-[#blue]>aea: \n\n 63 | else 64 | aea->al: \n\n 65 | 66 | @enduml 67 | -------------------------------------------------------------------------------- /dkms/08-add-connection-private-did-provisioned.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice\nEdge Agent" as aea 20 | participant "Alice\nCloud Agent" as aca 21 | participant "Bob\nCloud Agent" as bca 22 | participant "Bob\nEdge Agent" as bea 23 | actor Bob as bob 24 | 25 | note over al, bob #f0f0e0 26 | Alice and Bob know each other and want to connect. 27 | Alice and Bob both already have agents. 28 | Alice knows Bob's invitation address (at his cloud agent). 29 | end note 30 | 31 | == add connection to private DID (provisioned) Part 1 == 32 | 33 | al -> aea: add connection to Bob 34 | aea -> aea: create DID, keypair, and microledger (ABDID, AB1, ABml) 35 | aea -[#blue]> aca: request agent DID verification key for ABDID 36 | aca -> aca: create keypair and endpoint for connection with Bob (AB2) 37 | 38 | note right 39 | This registration will be revoked 40 | if the invitation expires. 41 | end note 42 | 43 | aca -[#blue]> aea: AB2-vk 44 | 45 | aea->aea: add cloud agent DID verification key AB2-vk and endpoint to microledger 46 | aea->aea: create complete connection invitation 47 | note right 48 | this includes the microledger ABml 49 | end note 50 | 51 | newpage 52 | 53 | == add connection to private DID (provisioned) Part 2 == 54 | 55 | par2 56 | aea -[#blue]> aca: connection invitation 57 | else 58 | aca -[#blue]> bca: \n 59 | else 60 | bca -[#blue]> bea: \n 61 | bea -> bob: display connection invitation 62 | 63 | bob -> bea: accept connection invitation 64 | bea -> bea: create DID, keypair, and microledger (BADID, BA1, BAml) 65 | bea -[#blue]> bca: request agent DID verification key for BAml 66 | bca -> bca: create keypair BA2 67 | bca -[#blue]> bea: endpoint and BA2-vk 68 | bea->bea: add cloud agent DID verification key and endpoint BA2-vk to microledger 69 | 70 | par2 71 | bea-[#blue]>bca: success and microledger deltas 72 | else 73 | bca-[#blue]>aca: \n\nsuccess 74 | else 75 | aca-[#blue]>aea: \n\n 76 | else 77 | aea->al: \n\n 78 | 79 | @enduml 80 | -------------------------------------------------------------------------------- /dkms/09-add-connection-private-did-unprovisioned.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice\nEdge Agent" as aea 20 | participant "Alice\nCloud Agent" as aca 21 | participant "Bob\nCloud Agent" as bca 22 | participant "Bob\nEdge Agent" as bea 23 | actor Bob as bob 24 | 25 | note over al, bob #f0f0e0 26 | Alice and Bob know each other and want to connect. 27 | Alice has an agent but Bob does not. 28 | end note 29 | 30 | == add connection to private DID (unprovisioned) Part 1 == 31 | 32 | al -> aea: add connection to Bob 33 | aea -> aea: create DID, keypair, and microledger (ABDID, AB1, ABml) 34 | aea -[#blue]> aca: request agent DID verification key for ABDID 35 | aca -> aca: create keypair and endpoint for connection with Bob (AB2) 36 | 37 | note right 38 | This registration will be revoked 39 | if the invitation expires. 40 | end note 41 | 42 | aca -[#blue]> aea: AB2-vk 43 | 44 | aea->aea: add cloud agent DID verification key AB2-vk and endpoint to microledger 45 | aea->aea: create complete connection invitation 46 | note right 47 | this includes the microledger ABml 48 | end note 49 | 50 | newpage 51 | 52 | == add connection to private DID (unprovisioned) Part 2 == 53 | 54 | note over al, bob 55 | Send SMS, email, QR code etc. containing connection invitation and a helper URL. 56 | end note 57 | 58 | aea --> bob: connection invitation 59 | 60 | note over bea, bob 61 | Download edge agent from helper URL. 62 | end note 63 | 64 | note over al, bob #77ccff 65 | include First Edge Agent diagram. 66 | end note 67 | 68 | note over bea 69 | Edge agent gets gets connection inviation from helper URL. 70 | end note 71 | 72 | bea -> bob: display connection invitation 73 | bob -> bea: accept connection invitation 74 | bea -> bea: create DID, keypair, and microledger (BADID, BA1, BAml) 75 | bea -[#blue]> bca: request agent DID verification key for BAml 76 | bca -> bca: create keypair BA2 77 | bca -[#blue]> bea: endpoint and BA2-vk 78 | bea->bea: add cloud agent DID verification key and endpoint BA2-vk to microledger 79 | 80 | par2 81 | bea-[#blue]>bca: success and microledger deltas 82 | else 83 | bca-[#blue]>aca: \n\nsuccess 84 | else 85 | aca-[#blue]>aea: \n\n 86 | else 87 | aea->al: \n\n 88 | 89 | @enduml 90 | -------------------------------------------------------------------------------- /dkms/10-rotate-did-key.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor "Alice" as al 19 | participant "Alice's\nEdge Agent 1" as aea1 20 | participant "Alice's\nCloud Agent" as aca 21 | participant "Alice's\nEdge Agent 2" as aea2 22 | participant "Bob's\nCloud Agent" as bca 23 | participant "Bob's\nEdge Agent" as bea 24 | 25 | note over al, bea #f0f0e0 26 | Alice rotates keys for her relationship with Bob, and propagates those changes to Bob's agents. 27 | end note 28 | 29 | == rotate DID keys Part 1 == 30 | 31 | alt 32 | note over aca 33 | Agent recovery triggers a DID key change event 34 | end note 35 | else 36 | note over aca 37 | DID key expiration triggers a DID key change event 38 | end note 39 | end 40 | 41 | aea1 -> aea1: generate keys (AB1) 42 | opt if changing keys for cloud agent as well... 43 | aea1 -[#blue]> aca: key change request for ABDID 44 | aca -> aca: create new keypair (AB2) 45 | aea1 <-[#blue] aca: AB2-vk 46 | end 47 | 48 | 49 | opt if policy in microledger dictates multisig for keychange... 50 | par2 51 | aea1 -> aea1: generate a one time passcode 52 | aea1 -[#blue]> aca: request for signature over key change event 53 | else 54 | aca -[#blue]>aea2: \n\n\n\n\n\n\n 55 | end 56 | aea2 -> al: [Warning] 57 | note over aca, aea2 58 | "Another device is attempting to change the keys you use in your relationship with Bob. 59 | If you approve this change, please enter the passcode from the other device." 60 | end note 61 | 62 | al -> aea2: passcode 63 | 64 | aea2 -> aea2: verify passcode matches 65 | par2 66 | aea2 -[#blue]> aca: signed key change event 67 | else 68 | aca -[#blue]> aea1: \n 69 | end 70 | 71 | end 72 | 73 | newpage 74 | 75 | == rotate DID keys Part 2 == 76 | 77 | aea1 -> aea1: write key change events to microledger (ABml) along with signatures 78 | par2 79 | aea1 -[#blue]> aca: ABml deltas 80 | else 81 | aca -[#blue]> bca: 82 | else 83 | bca -[#blue]> bea: 84 | bea -> bea: verifies and updates local copy of ABml with new events 85 | 86 | par2 87 | bca <-[#blue] bea: ack 88 | else 89 | aca <-[#blue] bca: 90 | else 91 | aea1 <-[#blue] aca: 92 | 93 | opt 94 | bca <-[#blue] bea: ABml deltas 95 | note left 96 | Any of Bob's agents that 97 | he uses with Alice need to 98 | know about the key changes 99 | as well. 100 | end note 101 | bca -> bca: verifies and updates local copy of ABml with new events 102 | end 103 | 104 | 105 | @enduml 106 | -------------------------------------------------------------------------------- /dkms/11-revoke-did.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor "Alice" as al 19 | participant "Alice's\nEdge Agent" as aea 20 | participant "Alice's\nCloud Agent" as aca 21 | participant "Bob's\nCloud Agent" as bca 22 | participant "Bob's\nEdge Agent" as bea 23 | 24 | note over al, bea #f0f0e0 25 | Alice is ending her relationship with Bob. 26 | end note 27 | 28 | al -> aea: delete Bob from connections 29 | 30 | aea -> aea: add DISABLE event to microledger ABml, signed by AB1-sk 31 | 32 | aea -[#blue]> aca: ABml deltas 33 | 34 | aca -> aca: applies deltas to local ABml 35 | 36 | aea <-[#blue] aca: ack 37 | 38 | opt if Alice chooses to notify Bob... 39 | par2 40 | aea -[#blue]> aca: ABml deltas 41 | else 42 | aca -[#blue]> bca: \n 43 | else 44 | bca -[#blue]> bea: \n 45 | end 46 | 47 | bea -> bea: applies deltas to local ABml 48 | note left 49 | Propagation of the microledger is a 50 | general solution for messages related 51 | to the connection state. Bob knows 52 | his relationship with Alice is disabled. 53 | end note 54 | 55 | par2 56 | bea -[#blue]> bca: ack 57 | else 58 | bca -[#blue]> aca: 59 | else 60 | aca -[#blue]> aea: 61 | end 62 | 63 | end 64 | 65 | aea -> al: success 66 | 67 | 68 | 69 | @enduml 70 | -------------------------------------------------------------------------------- /dkms/12-revoke-edge-agent.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Edge\nAgent 2" as ea 20 | participant "Ledger" as le 21 | 22 | note over al, le #f0f0e0 23 | Alice wishes to revoke edge agent 1. 24 | Alice has previously provisioned edge agent 2. 25 | end note 26 | 27 | == Revoking Agent 1 == 28 | 29 | al -> ea: revoke agent 1 30 | ea -> le: remove agent 1 policy keys 31 | le -> le: update agent policy registry 32 | ea -> ea: remove agent 1 DID keys 33 | 34 | note over al, le #77ccff 35 | include Rotate DID Key diagram 36 | end note 37 | 38 | ea -> al: success 39 | 40 | @enduml 41 | -------------------------------------------------------------------------------- /dkms/13-recovery-setup.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice's\nEdge Agent" as aea 20 | participant "Alice's\nCloud Agent" as aca 21 | participant "Recovery Buddy\nCloud Agent" as rb1 22 | 23 | note over aca #f0f0e0 24 | Assumptions: Cloud agent automatically stores encrypted backup of Alice's edge wallets 25 | end note 26 | 27 | == recovery setup == 28 | 29 | aea -> al: select options for recovery? 30 | note right 31 | Edge agent recommends Alice sets up a recovery policy 32 | end note 33 | al -> aea: yes 34 | aea -> al: options 35 | note right 36 | Offers offline and social recovery options 37 | end note 38 | al -> aea: choice 39 | aea -> aea: create backup encryption/decryption keypair AR 40 | note right 41 | The backup is encrypted using public key 42 | encryption. The public key is stored in the 43 | wallet and used for encryption. The private key 44 | is used for decryption and is sharded and distributed. 45 | end note 46 | 47 | aea -> aea: encrypt backup 48 | note right 49 | Will continue as background process 50 | end note 51 | aea -[#blue]> aca: encrypted backup 52 | alt chooses recovery buddies (minimum of 3) 53 | note over al, rb1 #77ccff 54 | Each recovery buddy completes Add Recovery Buddy diagram 55 | end note 56 | group Each recovery buddy 57 | aea -[#blue]> aca: recovery data share 58 | note right 59 | Includes backup encryption key ARsk, 60 | claim link secret ALS, and recovery endpoint 61 | end note 62 | aca -[#blue]> rb1: forward share 63 | rb1 -> rb1: store share 64 | par2 65 | rb1 -[#blue]> aca: \nack 66 | else 67 | aca -[#blue]> aea: \n 68 | end 69 | end 70 | else chooses paper wallet backup 71 | aea -> aea: create paper wallet with recovery data 72 | note right 73 | Includes same recovery data as above 74 | end note 75 | aea -> al: display paper wallet 76 | al -> al: save paper wallet 77 | end 78 | 79 | @enduml 80 | -------------------------------------------------------------------------------- /dkms/14-add-recovery-buddy.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | participant "Alice's\nEdge Agent" as aea 19 | participant "Alice's\nCloud Agent" as aca 20 | participant "Recovery Buddy\nCloud Agent" as rca 21 | participant "Recovery Buddy\nEdge Agent" as rea 22 | actor "Recovery\nBuddy" as rb1 23 | 24 | == add recovery buddy == 25 | 26 | aea -[#blue]> aca: create recovery buddy invitation 27 | aca -> aca: assign recovery endpoint 28 | note right 29 | This is a unique URL known only to Alice's cloud agent; 30 | it will be used only for a specific recovery invitation 31 | end note 32 | aca -[#blue]> aea: return recovery buddy invitation 33 | aea -> aea: create recovery data share 34 | note right 35 | This is a share of the recovery data - see **Recovery Setup** 36 | end note 37 | 38 | alt connection exists 39 | par2 40 | aea -[#blue]> aca: recovery buddy invitation 41 | else 42 | aca -[#blue]> rca: \nforward 43 | else 44 | rca -[#blue]> rea: \n 45 | end 46 | rea -> rb1: notify pending recovery buddy invitation 47 | else connection does not exist 48 | aea --> rb1: recovery buddy invitation 49 | note right 50 | Out of band 51 | end note 52 | note over aea, rb1 #f0f0e0 53 | Some time later 54 | end note 55 | alt If Buddy doesn't have software installed 56 | note over aea, rb1 #77ccff 57 | include Add Connection to Private DID (Unprovisioned) diagram 58 | end note 59 | else If Buddy does not already have a connection with Alice 60 | note over aea, rb1 #77ccff 61 | include Add Connection to Private DID (Provisioned) diagram 62 | end note 63 | end 64 | end 65 | rb1 -> rea: accepts recovery buddy invitation 66 | par2 67 | rea -[#blue]> rca: accept recovery buddy invitation 68 | else 69 | rca -[#blue]> aca: \n\nforward 70 | else 71 | aca -[#blue]> aea: \n\n 72 | end 73 | 74 | @enduml 75 | -------------------------------------------------------------------------------- /dkms/15-recovery-update.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice's\nEdge Agent" as aea 20 | participant "Alice's\nCloud Agent" as aca 21 | participant "Recovery Buddy\nCloud Agent" as rca 22 | participant "Recovery Buddy\nEdge Agent" as rea 23 | actor "Recovery\nBuddy" as rb1 24 | 25 | note over al, rb1 #f0f0e0 26 | Assumptions: Recovery Setup diagram has happened 27 | end note 28 | 29 | == recovery update == 30 | 31 | al -> aea: update recovery options 32 | opt Add more recovery buddies 33 | al -> aea: select another recovery buddy 34 | 35 | aea -> aea: create new backup keypair 36 | 37 | note over al, rb1 #77ccff 38 | include Add Recovery Buddy diagram (for each recovery buddy) 39 | end note 40 | 41 | par2 42 | aea -[#blue]> aca: PREPARE msg for share 43 | else 44 | aca -[#blue]> rca: \nforward 45 | else 46 | rca -[#blue]> rea: \n 47 | end 48 | 49 | rea -> rea: store new share with pending status 50 | 51 | par2 52 | rea -[#blue]> rca: \nack 53 | else 54 | rca -[#blue]> aca: \n 55 | else 56 | aca -[#blue]> aea:\n 57 | end 58 | 59 | aea -> aea: wait for enough responses 60 | 61 | par2 62 | aea -[#blue]> aca: COMMIT msg for new share 63 | else 64 | aca -[#blue]> rca: \nforward 65 | else 66 | rca -[#blue]> rea: \n 67 | end 68 | 69 | rea -> rea: delete old share; replace with new share 70 | 71 | par2 72 | rea -[#blue]> rca: \nack 73 | else 74 | rca -[#blue]> aca: \n 75 | else 76 | aca -[#blue]> aea: \n 77 | end 78 | 79 | aea -> al: success 80 | 81 | else Adding or changing to offline recovery 82 | al -> aea: select paper wallet backup 83 | aea -> aea: create paper wallet 84 | note right 85 | Includes private recovery key ARsk 86 | link secret ALS, and agency's DID for Alice 87 | end note 88 | aea -> al: display paper wallet 89 | al -> al: save paper wallet 90 | 91 | end 92 | 93 | @enduml 94 | -------------------------------------------------------------------------------- /dkms/16-offline-recovery.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice\nEdge Agent" as aea 20 | participant "Alice\nCloud Agent" as aca 21 | participant "Ledger" as led 22 | 23 | note over aca #f0f0e0 24 | Assumptions: Cloud agent automatically stores encrypted backup of Alice's edge wallets 25 | end note 26 | 27 | note over al, led #77ccff 28 | include Provision New Agent diagram 29 | end note 30 | == offline recovery process == 31 | 32 | aea -> al: please scan paper wallet 33 | al -> aea: scan paper wallet 34 | aea -> aea: extract recovery endpoint 35 | aea -[#blue]> aca: request encrypted backup 36 | 37 | aca -[#blue]> aea: encrypted backup 38 | aea -> aea: decrypt and restore backup data 39 | aea -> aea: replace old agent keys with new agent keys 40 | 41 | note over al, led #77ccff 42 | include Update Agent Policy Registry diagram 43 | end note 44 | note over al, led #77ccff 45 | include Rotate DID Key diagram 46 | end note 47 | 48 | @enduml 49 | -------------------------------------------------------------------------------- /dkms/17-social-recovery.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice\nEdge Agent" as aea 20 | participant "Alice\nCloud Agent" as aca 21 | participant "Recovery Connection\nCloud Agent" as rca 22 | participant "Recovery Connection\nEdge Agent" as rea 23 | actor "Recovery\nConnection" as rb 24 | 25 | note over al, rb #f0f0e0 26 | Assumptions: Alice has lost her edge agent(s) and needs to recover using her recovery buddies. 27 | Alice has performed all steps in the Provision New Agent and Add Cloud Agent diagrams. 28 | end note 29 | 30 | == social recovery process Part 1 == 31 | 32 | al -> aea: initiate recovery 33 | 34 | aea -> aea: prepare recovery request 35 | 36 | al <- aea: prompt to establish connections 37 | 38 | loop for each recovery connection... 39 | 40 | al --> rb: conversation 41 | 42 | note over al,rb 43 | Alice convinces recovery connection to accept her temporary connection request 44 | end note 45 | 46 | rb -> rea: create recovery connection 47 | 48 | note left 49 | This is how Alice becomes reconnected to her cloud agent— 50 | her recovery connection knows how to identify her connection, 51 | her connection knows the location of Alice's recovery share, 52 | and the recovery share knows Alice's recovery endpoint 53 | end note 54 | 55 | rea -> rb: identify connection to recover 56 | 57 | rb -> rea: choose Alice 58 | 59 | par2 60 | rea -[#blue]> rca: recovery request 61 | else 62 | rca -[#blue]> aca: \n 63 | else 64 | aca -[#blue]> aea: \n 65 | else 66 | aea -> al: \naccept request 67 | end 68 | 69 | note over al, rb #77ccff 70 | include Add Connection to Private DID (Provisioned) diagram 71 | end note 72 | 73 | aea -> al: recovery challenge 74 | 75 | al -> aea: challenge response 76 | 77 | note right 78 | A challenge comes as part of a recovery connection 79 | end note 80 | 81 | par2 82 | aea -[#blue]> aca: forward response 83 | else 84 | aca -[#blue]> rca: \n 85 | else 86 | rca -[#blue]> rea: \n 87 | else 88 | rea -> rb: \n 89 | end 90 | 91 | rb -> rb: verify Alice 92 | note left 93 | This is the most powerful feature of social recovery: Alice's recovery connections 94 | can verify that it is really her attempting to recover and know there is no 95 | man in the middle. 96 | end note 97 | rea -> rea: decrypt recovery share 98 | note left 99 | The recovery share was encrypted with the Recovery Connection's private key 100 | end note 101 | rea -> rea: extract recovery endpoint 102 | rea -> rea: encrypt recovery share 103 | note left 104 | Re-encrypted with the public key of Alice's new edge agent 105 | end note 106 | 107 | par2 108 | rea -[#blue]> rca: recovery share 109 | else 110 | rca -[#blue]> aca: 111 | else 112 | aca -[#blue]> aea: 113 | end 114 | 115 | end 116 | 117 | newpage 118 | 119 | == social recovery process Part 2 == 120 | 121 | aea -> aea: decrypt and assemble shares 122 | aea -[#blue]> aca: request encrypted backup 123 | 124 | aca -[#blue]> aea: encrypted backup 125 | aea -> aea: decrypt and read backup data 126 | aea -> aea: replace old agent keys with new agent keys 127 | 128 | note over al, rb #77ccff 129 | include Update Agent Policy Registry diagram 130 | include Rotate DID Key diagram 131 | end note 132 | 133 | @enduml 134 | -------------------------------------------------------------------------------- /dkms/C_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/C_1.png -------------------------------------------------------------------------------- /dkms/DKMS Design and Architecture V3.md: -------------------------------------------------------------------------------- 1 | #The DKMS Design and Architecture document has been moved to [the DKMS directory at Hyperledger Indy](http:bit.ly/dkmsv3). 2 | -------------------------------------------------------------------------------- /dkms/README.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Decentralized Key Management 3 | 4 | ### Introduction 5 | A decentralized key management system (DKMS) is an approach to cryptographic key 6 | management where there is no central authority. DKMS leverages the security, 7 | immutability, availability, and resiliency properties of distributed ledgers 8 | to provide highly scalable key distribution, verification, and recovery. 9 | 10 | ### Key Types 11 | DKMS uses the following key types: 12 | 1. **Master keys**: Keys that are not cryptographically protected. They are distributed manually or 13 | initially installed and protected by procedural controls and physical or electronic isolation. 14 | 2. **Key encrypting keys**: Symmetric or public keys used for key transport or storage of other keys. 15 | 3. **Data keys**: Used to provide cryptographic operations on user data (e.g., encryption, authentication). 16 | 17 | The keys at one level are used to protect items at a lower level. Consequently, special measures 18 | are used to protect master keys, including severely limiting access and use, hardware protection, 19 | and providing access to the key only under shared control. 20 | 21 | ### Key Loss 22 | Key loss means the owner no longer controls the key and it can assume there is no further risk of compromise. For example devices unable to function due to water, electricity, breaking, fire, hardware failure, acts of God, etc. 23 | ### Compromise 24 | Key compromise means that private keys and/or master keys have become or can become known either passively or actively. 25 | 26 | ### Recovery 27 | In decentralized identity management, recovery is important since identity owners have no “higher authority” 28 | to turn to for recovery. 29 | 1. Offline recovery uses physical media or removable digital media to store recovery keys. 30 | 2. Social recovery employs entities trusted by the identity owner called "trustees" who store recovery data on an identity owners behalf—typically 31 | in the trustees own agent(s). 32 | 33 | These methods are not exclusive and should be combined with key rotation and revocation for proper security. 34 | 35 | 1. [Design and architecture](DKMS%20Design%20and%20Architecture%20V3.md) 36 | 2. **Public Registry for Agent Authorization Policy**. An identity owner create a policy on the ledger that defines its agents and their authorizations. 37 | Agents while acting on the behalf of the identity owner need to prove that they are authorised. [More details](agent_authorization_policy.md) 38 | -------------------------------------------------------------------------------- /dkms/aap_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_0.png -------------------------------------------------------------------------------- /dkms/aap_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_1.png -------------------------------------------------------------------------------- /dkms/aap_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_10.png -------------------------------------------------------------------------------- /dkms/aap_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_11.png -------------------------------------------------------------------------------- /dkms/aap_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_12.png -------------------------------------------------------------------------------- /dkms/aap_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_13.png -------------------------------------------------------------------------------- /dkms/aap_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_14.png -------------------------------------------------------------------------------- /dkms/aap_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_15.png -------------------------------------------------------------------------------- /dkms/aap_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_18.png -------------------------------------------------------------------------------- /dkms/aap_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_19.png -------------------------------------------------------------------------------- /dkms/aap_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_2.png -------------------------------------------------------------------------------- /dkms/aap_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_20.png -------------------------------------------------------------------------------- /dkms/aap_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_21.png -------------------------------------------------------------------------------- /dkms/aap_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_22.png -------------------------------------------------------------------------------- /dkms/aap_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_23.png -------------------------------------------------------------------------------- /dkms/aap_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_24.png -------------------------------------------------------------------------------- /dkms/aap_25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_25.png -------------------------------------------------------------------------------- /dkms/aap_26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_26.png -------------------------------------------------------------------------------- /dkms/aap_27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_27.png -------------------------------------------------------------------------------- /dkms/aap_28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_28.png -------------------------------------------------------------------------------- /dkms/aap_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_3.png -------------------------------------------------------------------------------- /dkms/aap_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_4.png -------------------------------------------------------------------------------- /dkms/aap_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_5.png -------------------------------------------------------------------------------- /dkms/aap_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_6.png -------------------------------------------------------------------------------- /dkms/aap_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_7.png -------------------------------------------------------------------------------- /dkms/aap_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_8.png -------------------------------------------------------------------------------- /dkms/aap_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/aap_9.png -------------------------------------------------------------------------------- /dkms/agency-migration.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice's\nEdge Agent" as aea 20 | participant "Alice's Old\nCloud Agent" as aoca 21 | participant "Alice's New\nCloud Agent" as anca 22 | 23 | 24 | == == 25 | 26 | al -> aea: change agency 27 | note right 28 | Alice enters the new agency information 29 | and completes Add Cloud Agent 30 | with the new agency 31 | end note 32 | 33 | note over al, bob #77ccff 34 | include Add Cloud Agent diagram 35 | end note 36 | 37 | note over al, bob 38 | When rotating DID keys, the deltas will include 39 | the new agency service endpoint 40 | end note 41 | 42 | note over al, bob #77ccff 43 | include Rotate DID Key diagram 44 | end note 45 | 46 | note over al, bob 47 | Recovery update will need to be updated 48 | to point to the new agency 49 | end note 50 | 51 | note over al, bob #77ccff 52 | include Recovery Update diagram 53 | end note 54 | 55 | 56 | @enduml 57 | -------------------------------------------------------------------------------- /dkms/agent-authz-policy-ledger-interactions.md: -------------------------------------------------------------------------------- 1 | # Agent Authz policy (changes for ledger) 2 | **Objective**: Prove agents are authorized to provide proof of claims and authorize and de-authorize other agents 3 | 4 | ## Assumptions 5 | 1. The ledger maintains a global accumulator that holds commitments sent by the agents. 6 | 1. The gloabal accumulator is maintained by the each node so every node knows the accumulator private key 7 | 1. Agent auth policy txns are stored at the identity ledger. 8 | 1. Each auth policy is uniquely identified by a policy address `I`. 9 | 1. One agent can belong to several authz policies, thus several different `I`'s. 10 | 1. An agent can have several authorizations. Following are the list of authorizations: 11 | - PROVE 12 | - PROVE\_GRANT 13 | - PROVE\_REVOKE 14 | - ADMIN 15 | 16 | ## Transactions 17 | ### AGENT\_AUTHZ 18 | An authz policy is created/updated by an `AGENT_AUTHZ` transaction. A transaction creating a new authz policy: 19 | ``` 20 | { 21 | identifier: 22 | signature: , 23 | req_id: , 24 | operation: { 25 | type: AGENT_AUTHZ, 26 | address: , 27 | verkey: , 28 | authorization: , 29 | commitment: 30 | } 31 | } 32 | ``` 33 | **address**: The policy address, this is a unique identifier of an authz policy. Is a large number (size/range TBD). If the ledger has never seen the provided policy address, it considers the transaction a creation of a new authz policy else it is considered an update of an existing policy identifier by the address. 34 | **verkey**: An ed25519 verkey of the agent to which the `authorization` corresponds. This is optional when a new policy is being created as `identifier` is sufficient. This verkey should be kept different from any DID verkey to avoid coorelation. 35 | **authorization**: A bitset indicating which authorizations are being given to the agent, it is ignored when creating a new policy (the ledger does not know `I`). The various bits indicate different authorizations: 36 | 37 | ``` 38 | 0 None (revoked) 39 | 1 ADMIN (all) 40 | 2 PROVE 41 | 3 PROVE_GRANT 42 | 4 PROVE_REVOKE 43 | 5 "Reserved for future" 44 | 6 "Reserved for future" 45 | 7 ... 46 | ... 47 | ``` 48 | 49 | While creating a new policy, this field's value is ignored and the creator agent has all authorizations. For any subsequent polciy transactions, the ledger checks if the sender (author to be precise, since anyone can send a transaction once a signature has been done) of transaction has the authorization to make the transaction, eg. The author of txn has `PROVE_GRANT` if it is giving a `PROVE` authorization to another agent. 50 | **Future Work**: When we support `m-of-n` authorization, `verkey` would be a map stating the policy and the verkeys 51 | 52 | **commitment**: This is a number (size/range TBD) given by the agent when it is being given a ``PROVE`` authorization. Thus this field is only needed when a policy is being created or an agent is being given the `PROVE` authorization. The ledger upon receiving this commitment checks if the commitment is prime and if it is then it updates the global accumulator with this commitment. Efficient primality testing algorithms like BPSW or ECPP can be used but the exact algorithm is yet to be decided. If the commitment is not prime (in case of creation or update of policy address) then the transaction is rejected. The ledger rejects the transaction if it has already seen the commitment as part of another transaction. 53 | In case of creation of new policy or an agent being given `PROVE` authorization, the ledger responds with the accumulator value after the update with this commitment. 54 | 55 | 56 | ### GET\_AGENT\_AUTHZ 57 | This query is sent by any client to check what the authz policy of any address `I` is 58 | ``` 59 | { 60 | ..., 61 | operation: { 62 | type: GET_AGENT_AUTHZ, 63 | address: , 64 | } 65 | } 66 | ``` 67 | 68 | The ledger replies with all the agents, their associated authorizations and the commitments of the address `I`. 69 | 70 | ### GET\_AGENT\_AUTHZ\_ACCUM 71 | This query is sent by anyone to get the value of the accumulator. 72 | ``` 73 | { 74 | ..., 75 | operation: { 76 | type: GET_AGENT_AUTHZ_ACCUM, 77 | accum_id: 78 | } 79 | } 80 | ``` 81 | The ledger returns the global accumulator with the id. Both accumulators are add only; the client checks that commitment is present in one accumulator AND not present in other accumulator. 82 | 83 | 84 | ## Data structures 85 | ### Ledger 86 | Each authz transaction goes in the identity ledger. 87 | 88 | ### State trie. 89 | The state stores: 90 | 1. Accumulator: The accumulator is stored in the trie at name `` with value as the value of accumulator. 91 | 2. Policies: The state stores one name for each policy, the name is `:`, the value at this name is a hash. The hash is determined deterministically serializing (RLP encoding from ethereum, we already use this) this data structure: 92 | 93 | ``` 94 | [ 95 | [, , [commitment>]], 96 | [, , [commitment>]], 97 | [, , [commitment>]], 98 | ] 99 | ``` 100 | 101 | The hash of above can then be used to lookup (it is not, more on this later) the exact authorization polciy in a separate name-value store. This is done to keep the database backing the state (trie) smaller. 102 | 103 | ### Caches 104 | There is an agent\_authz cache used for optimisations are: 105 | The cache is a name-value store (leveldb) and offers a constant lookup time for lookup by name. 106 | 1. Policy values: The authorization of each agent per policy. The values for the keys are rlp encoding of the list of at most 2 items, `authorization bitset` with each bit respresenting a different auth, `commitment` is optional and relevant only when agent has the `PROVE` authorization. 107 | 108 | ``` 109 | { 110 | : :, 111 | : :, 112 | : :, 113 | : :, 114 | : :, 115 | .... 116 | } 117 | ``` 118 | These names are used by the nodes during processing any transaction. 119 | 120 | 2. Accumulator value: Value of each accumulator is stored corresponding to the special byte indicating the global accumulator. 121 | ``` 122 | { 123 | : , 124 | } 125 | ``` 126 | 127 | During processing of any write transaction, the node updates the ledger, state and caches after the txn is successful but for querying (client as well as its own like validation, etc) it only uses caches since caches are more efficient than state trie. The state trie is only used for state proofs. 128 | 129 | 3. TODO: Maintaining a set of commitments: Each node maintains a set of see commitments and does not allow duplicate commitments. Its kept in key value store with constant lookup time for commitment lookup. 130 | 131 | 132 | ## Code organisation. 133 | These changes would be implemented as a separate plugin. The plugin will not introduce new ledger or state but will introduce the cache described above. The plugin will intrduce a new request handler which will subclass the `DomainRequestHandler`. The plugin's new request handler will introduce 1 `write_type` and 2 `query_types` and methods to handle those. 134 | -------------------------------------------------------------------------------- /dkms/burn-identity-with-agents.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Issuers" as IS 20 | participant "Ledger" as le 21 | 22 | note over al, le #f0f0e0 23 | Assumptions: 24 | end note 25 | 26 | @enduml 27 | -------------------------------------------------------------------------------- /dkms/failure-modes.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam roundcorner 15 3 | skinparam maxmessagesize 100 4 | skinparam state { 5 | ArrowColor grey 6 | BorderColor grey 7 | FontSize 17 8 | } 9 | 10 | state Oblivious { 11 | state "Stolen" as stdk 12 | state "Lurk" as lkdk 13 | state "Lost" as ltdk 14 | state "Misuse" as imdk 15 | } 16 | Oblivious: Mitigation by prevention, reducing impact\nand attacker benefit 17 | 18 | state Cognizant { 19 | state Stolen 20 | state Lurk 21 | state Lost 22 | state Misuse 23 | } 24 | Cognizant: Mitigation by prevention, quick recovery,\nreducing impact and attacker benefit 25 | 26 | 27 | Functional --> Cognizant 28 | Functional --> Oblivious 29 | Oblivious --> stdk 30 | Oblivious --> lkdk 31 | Oblivious --> ltdk 32 | Oblivious --> imdk 33 | Cognizant --> Stolen 34 | Cognizant --> Lurk 35 | Cognizant --> Lost 36 | Cognizant --> Misuse 37 | 38 | stdk --> Stolen 39 | lkdk --> Lurk 40 | ltdk --> Lost 41 | 42 | Lost --> stdk 43 | lkdk -right-> imdk 44 | Lurk -right-> Misuse 45 | 46 | @enduml 47 | -------------------------------------------------------------------------------- /dkms/image_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_0.png -------------------------------------------------------------------------------- /dkms/image_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_1.png -------------------------------------------------------------------------------- /dkms/image_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_10.png -------------------------------------------------------------------------------- /dkms/image_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_11.png -------------------------------------------------------------------------------- /dkms/image_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_12.png -------------------------------------------------------------------------------- /dkms/image_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_13.png -------------------------------------------------------------------------------- /dkms/image_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_14.png -------------------------------------------------------------------------------- /dkms/image_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_15.png -------------------------------------------------------------------------------- /dkms/image_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_16.png -------------------------------------------------------------------------------- /dkms/image_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_17.png -------------------------------------------------------------------------------- /dkms/image_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_18.png -------------------------------------------------------------------------------- /dkms/image_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_19.png -------------------------------------------------------------------------------- /dkms/image_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_2.png -------------------------------------------------------------------------------- /dkms/image_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_20.png -------------------------------------------------------------------------------- /dkms/image_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_21.png -------------------------------------------------------------------------------- /dkms/image_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_22.png -------------------------------------------------------------------------------- /dkms/image_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_23.png -------------------------------------------------------------------------------- /dkms/image_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_24.png -------------------------------------------------------------------------------- /dkms/image_25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_25.png -------------------------------------------------------------------------------- /dkms/image_26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_26.png -------------------------------------------------------------------------------- /dkms/image_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_3.png -------------------------------------------------------------------------------- /dkms/image_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_4.png -------------------------------------------------------------------------------- /dkms/image_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_5.png -------------------------------------------------------------------------------- /dkms/image_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_6.png -------------------------------------------------------------------------------- /dkms/image_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_7.png -------------------------------------------------------------------------------- /dkms/image_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_8.png -------------------------------------------------------------------------------- /dkms/image_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/image_9.png -------------------------------------------------------------------------------- /dkms/mathcal_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/mathcal_a.png -------------------------------------------------------------------------------- /dkms/overview.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam roundcorner 15 3 | skinparam maxmessagesize 100 4 | skinparam state { 5 | ArrowColor grey 6 | BorderColor grey 7 | FontSize 17 8 | } 9 | 10 | state "Identity" as id 11 | state "Link Secret" as cls: Used in all claims 12 | state "Payment Keys" as payks 13 | state "Policy Keys" as polks 14 | state "DID Keys" as didks 15 | state "Claims" as clm { 16 | state "Claim 1" 17 | state "Claim 2" 18 | } 19 | state "Ledger" as le { 20 | state "Identity\nPolicy\nAddress" as ipa 21 | state "Prover\nRegistry\nAccumulator" as ga 22 | state "Token\nAccumulator" as ta 23 | le --> ga: Push\nUpdates 24 | } 25 | 26 | id --> cls 27 | id --> didks 28 | id --> polks 29 | id --> payks 30 | 31 | id --> clm 32 | cls --> clm 33 | polks --> ipa: CRUD for ACL 34 | payks --> ta: Spend 35 | 36 | @enduml 37 | -------------------------------------------------------------------------------- /dkms/proof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/proof.png -------------------------------------------------------------------------------- /dkms/recover-agent-policy-registry.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice's\nEdge Agent" as aea 20 | participant "Alice's\nCloud Agent" as aca 21 | participant "Issuers\nAgent" as aci 22 | participant "Issuer" as iss 23 | participant "Ledger" as le 24 | note over al, le #f0f0e0 25 | Assumptions: Alice no longer has any agent policy 26 | keys to use for control over her agent policy registry 27 | on the ledger. An attacker has compromised the 28 | agent policy registry and locked out Alice. 29 | end note 30 | 31 | == agent recovery == 32 | 33 | note over al, le #f0f0e0 34 | Alice performs agent recovery by completing all steps in 35 | Offline Recovery diagram or Social Recovery diagram 36 | She can't complete the portion to update the agent policy registry 37 | because she is locked out 38 | end note 39 | 40 | == create new agent policy registry == 41 | 42 | aea -> aea: generate policy registry address **//P'//** 43 | aea -> aea: store **//P'//** 44 | 45 | note over al, le #77ccff 46 | include Update Agent Policy Registry diagram 47 | (with all authorizations) 48 | end note 49 | 50 | == revoke claims == 51 | 52 | note over al, le 53 | Alice revokes all her claims that include 54 | the old agent policy address P as 55 | a blinded attribute. Alice also petitions 56 | the Issuers to reuissue her claims. 57 | 58 | How to invalidate claims that are not revocable? 59 | end note 60 | 61 | al -> aea: revoke claim 62 | 63 | aea -[#blue]> aca: \nrevoke claim message 64 | note right 65 | Claim with claim schema S and 66 | claim index Si 67 | end note 68 | 69 | par2 70 | aca -[#blue]>aci: \n\nforward 71 | else 72 | aci -[#blue]>iss:\n\nnotify issuer 73 | end 74 | 75 | iss --> iss: verify alice 76 | note right 77 | Issuer authenticates Alice 78 | using the same methods as before 79 | when Alice was issued the claim 80 | end note 81 | iss -[#blue]> aci: revoke claim 82 | note right 83 | Add claim index Si 84 | to the non-revocation accumulator SO 85 | corresponding to claim schema S. Sign 86 | transaction with Issuer accumulator private key. 87 | end note 88 | aci -[#blue]> le: forward revoke claim 89 | note right 90 | Adds claim index Si to the 91 | non-revocation accumulator corresponding to 92 | claim schema S. 93 | end note 94 | le -> le: update accumulator 95 | le -[#blue]> aci: result 96 | 97 | aci -[#blue]> iss: forward result 98 | 99 | par2 100 | aci -[#blue]> aca: \nack 101 | else 102 | aca -[#blue]> aea: \n 103 | else 104 | aea -> al: \n 105 | end 106 | 107 | == reissue claims == 108 | 109 | note over al, le #77ccff 110 | Alice completes Issue Claim diagram 111 | for each claim with new policy address P 112 | end note 113 | 114 | @enduml 115 | -------------------------------------------------------------------------------- /dkms/recover-connection.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice's\nEdge Agent" as aea 20 | participant "Alice's\nCloud Agent" as aca 21 | participant "Bob's\nCloud Agent" as bca 22 | participant "Bob's\nEdge Agent" as bea 23 | actor Bob as bob 24 | note over al, bob #f0f0e0 25 | Assumptions: Alice no longer has valid any DID 26 | keys to use for her connection with Bob. 27 | An attacker has compromised the connection and locked out Alice. 28 | end note 29 | 30 | == agent recovery == 31 | 32 | note over al, bob #f0f0e0 33 | Alice performs agent recovery by completing all steps in 34 | Offline Recovery diagram or Social Recovery diagram 35 | She can't complete the portion to rotate DID keys 36 | because she is locked out 37 | end note 38 | == reestablish relationship with Bob == 39 | 40 | alt out of band method 41 | al --> bob: compromise notify 42 | note right 43 | Alice contacts Bob out of band to let him 44 | know that her existing connection is not her. 45 | Bob can authenticate Alice using the same methods 46 | as before when Alice and Bob connected 47 | end note 48 | 49 | else decry method 50 | note over al, bob 51 | After recovery, the agent knows it couldn't rotate the DID keys. 52 | The agent uses the key that was previously authorized to perform 53 | the decry method. 54 | end note 55 | par2 56 | aea -[#blue]> aca: add DECRY event to microledger ABml, signed by AB1-sk 57 | else 58 | aca -[#blue]> bca: \n\n\n\n\nforward 59 | else 60 | bca -[#blue]> bea: \n\n\n\n\nforward 61 | else 62 | bea -> bob: \n\n\n\n\nDECRY notify 63 | note right 64 | DECRY means Bob should be use caution with his 65 | connection to Alice because it should no longer be trusted. Bob 66 | should verify that his connection is really to Alice. 67 | end note 68 | end 69 | end 70 | bob --> bob: verify Alice 71 | note right 72 | This can be different based on who Bob is. 73 | If Bob is Alice's brother this could be simple. 74 | If Bob is Alice's bank this would be more complex. 75 | end note 76 | bob -> bob: delete former connection data with Alice 77 | note right 78 | DID, keys and microledger 79 | end note 80 | note over al, bob #77ccff 81 | include Add Connection Private DID Provisioned diagram 82 | (with all authorizations) 83 | end note 84 | 85 | @enduml 86 | -------------------------------------------------------------------------------- /dkms/revoke-edge-agent-success.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | actor "Alice" as al 18 | participant "Edge\nAgent 2" as ea 19 | participant "Ledger" as le 20 | 21 | note over al, le #f0f0e0 22 | Alice's only edge agent 1 becomes 23 | unavailable to her. It's stolen, lost, 24 | malfunctioning, physically gone or it's hacked 25 | and she no longer trusts using that agent. 26 | end note 27 | 28 | == Setup new agent == 29 | note over al, le 30 | Alice follows process in 31 | recover-offline.puml or recover-social.puml. 32 | After that former agent 1 is revoked. 33 | Attacker is halted at that point. 34 | end note 35 | 36 | @enduml 37 | -------------------------------------------------------------------------------- /dkms/revoke-rogue-edge-agent.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam sequenceArrowThickness 2 3 | skinparam roundcorner 15 4 | skinparam maxmessagesize 100 5 | skinparam sequence { 6 | ArrowColor grey 7 | LifeLineBorderColor grey 8 | ParticipantBorderColor grey 9 | boxbordercolor white 10 | ParticipantFontSize 17 11 | actorfontsize 17 12 | boxfontsize 17 13 | boxfontcolor grey 14 | ActorBorderColor grey 15 | Actorbackgroundcolor white 16 | } 17 | 18 | actor Alice as al 19 | participant "Alice\nEdge\nAgent 1" as a1 20 | participant "Alice\nEdge\nAgent 2" as a2 21 | participant "Remote\nAgent" as ca 22 | actor Mallory as ma 23 | participant Ledger as le 24 | 25 | note over al, le #f0f0e0 26 | Mallory has physically stolen edge agent 2 from Alice. 27 | Alice was not using the software when Mallory took it, so 28 | Mallory must use brute force to unlock it. 29 | Alice's key management policy is 2 out of 3 to 30 | provision and revoke. The policy includes these 31 | three agents. 32 | 33 | Remote agent can be any that is trusted by Alice 34 | end note 35 | == Revoking Agent 2 == 36 | 37 | al -> a1: revoke agent 2 38 | a1 -[#blue]> le: policy request 39 | le -[#blue]> a1: policy 40 | note over a1 41 | Edge agent knows it 42 | needs another key 43 | to revoke agent 2 and 44 | remove agent 2 from 45 | changing the policy 46 | end note 47 | 48 | a1 -[#blue]> ca: request signature to revoke\nagent 2 49 | 50 | alt If Alice controls Remote Agent 51 | ca -[#blue]> al: please authenticate 52 | al -[#blue]> ca: authenticate to agent 53 | ca -[#blue]> al: confirm request to revoke 54 | al -[#blue]> ca: confirm 55 | else If Remote Agent is controlled by Third Party Bob 56 | ca --> al: authenticate Alice 57 | note right 58 | This is done out of band 59 | end note 60 | al --> ca: authenticate to Bob 61 | ca -> ca: confirm request to revoke 62 | end 63 | 64 | 65 | ca -[#blue]> a1: signature to remove agent 2 \ 66 | from all policies 67 | note right 68 | The ledger needs to two signatures 69 | to complete the transaction 70 | end note 71 | 72 | a1 -[#blue]> le: signature to remove agent 2 \ 73 | from all policies 74 | le -> le: update policy 75 | note right 76 | Ledger can now complete 77 | the revocation transaction 78 | Agent 2 cannot use claims in proofs 79 | end note 80 | 81 | le -[#blue]> a1: result 82 | 83 | a1 -> a1: remove all agent 2 keys from DIDs 84 | note over al, le #77ccff 85 | include Revoke DID diagram 86 | end note 87 | a1 -[#blue]> ca: remove all agent 2 keys from DIDs 88 | ca -[#blue]> a1: completed 89 | 90 | note over al, le #f0f0e0 91 | Eventually mallory manages to break into agent 2 92 | end note 93 | ma -> a2: revoke agent 1 94 | a2 -[#blue]> le: policy request 95 | le -[#blue]> a2: policy 96 | note over a2 97 | Edge agent sees it 98 | can't revoke agent 1 99 | end note 100 | a2 -> ma: access denied 101 | 102 | note over al, le 103 | Race condition happens if Mallory is able to 104 | revoke Agent 1 before Alice can revoke. 105 | 106 | Policy could be defined to only allow 1 to revoke 2 107 | but not the reverse. This adds complexity. 108 | Another recovery key only used for 109 | this situation could also prevent this. But 110 | Alice could lose the paper wallet or her 111 | recovery buddies could lose it and what then? 112 | end note 113 | 114 | @enduml 115 | -------------------------------------------------------------------------------- /dkms/shamir_secret.md: -------------------------------------------------------------------------------- 1 | # Shmair secret API (indy-crypto and indy-sdk) 2 | **Objective**: `indy-crypto` exposes the low level API for generating and reconstructing secrets. `indy-sdk` uses the underlying `indy-crypto` and exposes an API to shard a JSON message, store the shards and reconstitute the secret. 3 | 4 | ## Indy-crypto 5 | 1. `shard_secret(secret: bytes, m: u8, n: u8, sign_shares: Option) -> Result, IndyCryptoError>`. 6 | Splits the bytes of the secret `secret` in `n` different shares and `m-of-n` shares are required to reconstitute the secret. `sign_shares` if provided, all shards are signed. 7 | 1. `recover_secret(shards: Vec, verify_signatures: Option) -> Result, IndyCryptoError>`. 8 | Recover the secret from the given `shards`. `verify_signatures` if given verifies the signatures. 9 | 10 | ## Indy-sdk 11 | 1. `shard_JSON(msg: String, m: u8, n: u8, sign_shares: Option) -> Result, IndyError>` 12 | Takes the message as a JSON string and serialises it to bytes and passes it to `shard_secret` of `indy-crypto`. The serialisation has to be deterministic, i.e the same JSON should always serialise to same bytes everytime. The resulting `Share` given by `indy-crypto` is converted to JSON before returning. 13 | 1. `shard_JSON_with_wallet_data(wallet_handle: i32, msg: String, wallet_keys:Vec<&str>, m: u8, n: u8, sign_shares: Option) -> Result, IndyError>` 14 | Takes the message as a JSON string, updates the JSON with key-values from wallet given by handle `wallet_handle`, keys present in the vector `wallet_keys` and passes the resulting JSON to `shard_JSON`. 15 | 1. `recover_secret(shards: Vec, verify_signatures: Option) -> Result` 16 | Takes a collection of shards each encoded as JSON, deserialises them into `Share`s and passes them to `recover_secret` from `indy-crypto`. It converts the resulting secret back to JSON before returning it. 17 | 1. `shard_JSON_and_store_shards(wallet_handle: i32, msg: String, m: u8, n: u8, sign_shares: Option) -> Result` 18 | Shards the given JSON using `shard_JSON` and store shards as a JSON array (each shard is an object in itself) in the wallet given by `wallet_handle`. Returns the wallet key used to store the shards. 19 | -------------------------------------------------------------------------------- /dkms/trustee_protocols.md: -------------------------------------------------------------------------------- 1 | # Trustee Setup Protocol 2 | **Objective**: Provide the messages and data formats so an identity owner can choose, update, remove trustees and their delegated capabilities. 3 | 4 | ## Assumptions 5 | 6 | 1. An identity owner selects a connection to become a trustee 7 | 1. Trustees can be granted various capabilities by identity owners 8 | 1. Safeguarding a recovery share. This will be the most common 9 | 1. Revoke an authorized agent on behalf of an identity owner 10 | 1. Provision a new agent on behalf of an identity owner 11 | 1. Be an administrator for managing identity owner agents 12 | 1. Trustees agree to any new specified capabilities before any action is taken 13 | 1. Trustees will safeguard recovery shares. Their app will encrypt the share and not expose it to anyone else 14 | 1. Trustees authenticate out-of-band an identity owner when a recovery event occurs 15 | 1. The Trustees' app should only send a recovery share to an identity owner after they have been authenticated 16 | 1. All messages will use [Message Packaging](https://github.com/evernym/protocol/blob/master/message-packaging.md). 17 | 18 | ## Messages and Structures 19 | Messages are formatted as JSON. All binary encodings use base64url. 20 | All messages include the following fields: 21 | 22 | 1. *version* \: The semantic version of the message data format. 23 | 1. *type* \: The message type. 24 | 25 | ### CAPABILTY\_OFFER 26 | Informs a connection that the identity owner wishes to make them a trustee. The message includes information about what 27 | capabilities the identity owner has chosen to grant a trustee and how long the offer is valid. 28 | This message adds the following fields 29 | 30 | *expires* \: 64-bit unsigned big-endian integer. The number of seconds elapsed between January 1, 1970 UTC and the time the offer will expire if no request message is received. This value is purely informative.\ 31 | *capabilities* \: A list of capabilities that the trustee will be granted. They can include 32 | 33 | 1. RECOVERY\_SHARE: The trustee will be given a recovery share 34 | 1. REVOKE\_AUTHZ: The trustee can revoke agents 35 | 1. PROVISION\_AUTHZ: The trustee can provision new agents 36 | 1. ADMIN\_AUTHZ: The trustee is an administrator of agents 37 | 38 | ``` 39 | { 40 | "version": "0.1", 41 | "type": "CAPABILITY_OFFER", 42 | "capabilities": ["RECOVERY_SHARE", "REVOKE_AUTHZ", "PROVISION_AUTHZ"] 43 | "expires": 1517428815 44 | } 45 | ``` 46 | 47 | ### CAPABILTY\_REQUEST 48 | Sent to an identity owner in response to a TRUSTEE\_OFFER message. The message includes includes information 49 | for which capabilities the trustee has agreed. This message adds the following fields 50 | 51 | *for\_id* \: The nonce sent in the TRUSTEE\_OFFER message.\ 52 | *capabilities* \: A name value object that contains the trustee's response for each privilege.\ 53 | *authorizationKeys* \: The public keys that the trustee will use to verify her actions with the authz policy registry on behalf of the identity owner. 54 | 55 | ``` 56 | { 57 | "version": "0.1", 58 | "type": "CAPABILITY_REQUEST", 59 | "authorizationKeys": ["Rtna123KPuQWEcxzbNMjkb"] 60 | "capabilities": ["RECOVERY_SHARE", "REVOKE_AUTHZ"] 61 | } 62 | ``` 63 | 64 | ### CAPABILITY\_RESPONSE 65 | Sends the identity owner policy address and/or recovery data and metadata to a recovery trustee. A trustee should send a confirmation message that this message was received. 66 | 67 | *address* \: The identity owner's policy address. Only required if the trustee has a key in the authz policy registry.\ 68 | *share* \: The actual recovery share data in the format given in the next section. Only required if the trustee has the RECOVERY\_SHARE privilege. 69 | 70 | ``` 71 | { 72 | "version": "0.1", 73 | "type": "CAPABILITY_RESPONSE", 74 | "address": "b3AFkei98bf3R2s" 75 | "share": { 76 | ... 77 | } 78 | } 79 | ``` 80 | 81 | ### TRUST\_PING 82 | Authenticates a party to the identity owner for out of band communication. 83 | 84 | *challenge* \: A message that a party should respond to so the identity owner can be authenticated. Contains a *question* field for the other party to answer 85 | and a list of *valid\_responses*. 86 | 87 | ``` 88 | { 89 | "version": "0.1", 90 | "type": "TRUST_PING", 91 | "challenge": { 92 | ... 93 | } 94 | } 95 | ``` 96 | 97 | *challenge* will look like the example below but allows for future changes as needed.\ 98 | *question* \: The question for the other party to answer.\ 99 | *valid\_responses* \: A list of valid responses that the party can give in return. 100 | 101 | ``` 102 | { 103 | "question": "Are you on a call with CULedger?", 104 | "valid_responses": ["Yes", "No"] 105 | } 106 | ``` 107 | 108 | ### TRUST\_PONG 109 | The response message for the TRUST\_PING message. 110 | 111 | ``` 112 | "version": "0.1", 113 | "type": "TRUST_PONG", 114 | "answer": { 115 | "answerValue": "Yes" 116 | } 117 | ``` 118 | 119 | ### KEY\_HEARTBEAT\_REQUEST 120 | Future\_Work: Verifies a trustee/agent has and is using the public keys that were given to the identity owner. These keys 121 | 122 | *authorizationKeys* \: Public keys the identity owner knows that belong to the trustee/agent. 123 | 124 | ``` 125 | { 126 | "version": "0.1", 127 | "type": "KEY_HEARTBEAT_REQUEST", 128 | "authorizationKeys": ["Rtna123KPuQWEcxzbNMjkb"] 129 | } 130 | ``` 131 | 132 | ### KEY\_HEARTBEAT\_RESPONSE 133 | Future\_Work: The updated keys sent back from the trustee/agent 134 | 135 | 136 | ### RECOVERY\_SHARE\_RESPONSE 137 | Future\_Work: After an identity owner receives a challenge from a trustee, an application prompts her to complete the challenge. This message contains her response. 138 | 139 | *for\_id* \: The nonce sent in the RECOVERY\_SHARE\_CHALLENGE message.\ 140 | *response* \: The response from the identity owner. 141 | 142 | ``` 143 | { 144 | "version": "0.1", 145 | "type": "RECOVERY_SHARE_RESPONSE", 146 | "response": { 147 | ... 148 | } 149 | } 150 | ``` 151 | 152 | *response* will look like the example below but allows for future changes as needed. 153 | 154 | ``` 155 | { 156 | "pin": "3qA5h7" 157 | } 158 | ``` 159 | 160 | ## Recovery Share Data Structure 161 | Recovery shares are formated in JSON with the following fields: 162 | 163 | 1. *version* \: The semantic version of the recovery share data format. 164 | 1. *source\_did*: The identity owner DID that sent this share to the trustee 165 | 1. *tag* \: A value used to verify that all the shares are for the same secret. The identity owner compares this to every share to make sure they are the same. 166 | 1. *shareValue* \: The share binary value. 167 | 1. *hint* \: Hint data that contains the following fields: 168 | 1. *trustees* \: A list of all the recovery trustee names associated with this share. These names are only significant to the identity owner. Helps to aid in recovery by providing some metadata for the identity owner and the application. 169 | 1. *threshold* \: The minimum number of shares needed to recover the key. Helps to aid in recovery by providing some metadata for the identity owner and the application. 170 | 171 | ``` 172 | { 173 | "version": "0.1", 174 | "source_did": "did:sov:asbdfa32135" 175 | "tag": "ze4152Bsxo90", 176 | "shareValue": "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789" 177 | "hint": { 178 | "theshold": 3, 179 | "trustees": ["Mike L", "Lovesh", "Corin", "Devin", "Drummond"] 180 | } 181 | } 182 | ``` 183 | -------------------------------------------------------------------------------- /dkms/zpok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/dkms/zpok.png -------------------------------------------------------------------------------- /janus/Janus_coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/janus/Janus_coin.png -------------------------------------------------------------------------------- /janus/README.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | 3 | ![Janus](Janus_coin.png) 4 | 5 | # Janus 6 | 7 | Janus is the current codename for a protocol that enables secure 8 | communication between peers. Its name refers to the two-faced figure 9 | from Greek mythology, emphasizing a two-way flow of information. 10 | (This also feels appropriate for the classic crypto communication 11 | stories that feature Alice and Bob.) 12 | 13 | Janus is a subset or subprotocol of the overarching protocol for self-sovereign 14 | identity. It assumes the existence of certain ecosystem features such as 15 | agents and keys, and is thus dependent on a larger context. 16 | 17 | Janus partially overlaps the mandate of other secure communications 18 | protocols like Signal. The implications of this overlap are discussed 19 | elsewhere. 20 | 21 | ## Requirements 22 | 23 | At the highest level, Janus aims to: 24 | 25 | 1. Provide highly secure communication channels, with correct basis for trust. 26 | 2. Provide strong privacy guarantees as demanded by [Self-Sovereign 27 | Privacy by Design](../self_sovereign_privacy_by_design_v1.md). 28 | 3. Facilitate interoperability (be usable from many programming languages, 29 | many blockchain technologies, many vendor stacks, many OSes and 30 | hardware platforms). 31 | 4. Be [transport-agnostic](message-transport.md) (work over http, raw tcp, smtp, snail mail, 32 | carrier pigeon...). 33 | 5. Be [composable](message-packaging.md) and [extensible](message-inventory.md). 34 | 35 | ## Agents and Keys 36 | 37 | People and institutions can't speak raw bytes on a wire; they use software 38 | that works on their behalf. Each independent, key-weilding piece of software 39 | that represents an identity owner is called an agent. 40 | 41 | There are two agent types: 42 | 43 | * Edge. Run on hardware directly controlled by identity owner: mobile 44 | devices, laptops, on-prem servers (where identity owner = institution). 45 | High trust. Manage the most privileged keys. 46 | * Cloud. Run on hardware controlled by someone else: agents as a service. 47 | Trust is somewhat tempered. Manage delegated, limited-use keys. 48 | 49 | Every participant in secure communication has at least one agent. 50 | Each agent needs its own keys. Keys are never copied. (For deep 51 | background on the theory and principles of key management espoused 52 | by Janus, see [this recent research report](https://drive.google.com/open?id=1OEOl5cv69dEidK_Efx8blcYwgyPiaU_c).) 53 | 54 | The distinction between identity owners and their keys and agents, and 55 | the trust differences between technologies in the cloud and at the 56 | edge, imply a [model of the ecosystem that is layered and nuanced](message-layers.md). 57 | 58 | ## Messages 59 | 60 | At its heart, Janus thinks about communication as an asynchronous exchange 61 | of messages over any untrusted, unreliable transport. To whatever transport 62 | is used in a given context, Janus adds features such as security, privacy, 63 | reliability, and synchronous patterns like http's familiar request/response. 64 | This allows Janus to provide value in classic RESTful paradigms as well as: 65 | 66 | * Broadcasts, pub/sub 67 | * Occasionally connected agents 68 | * Fancy routing (store-and-forward, onion, delivery delay) 69 | * Other protocols (e.g., snail mail) 70 | * Semi-trusted agents (progressive/muted auth, limited proxies) 71 | 72 | Janus message exchange can also negotiate an alternate, 73 | non-message-oriented communication mode with trust and security rooted 74 | in Janus's standard guarantees (e.g., video streaming over a channel 75 | built with Janus messages). 76 | 77 | The [inventory of Janus message types](message-inventory.md) is open; anybody can add their own. 78 | 79 | ## Composability and Transformations 80 | 81 | In snail mail, the content of a message and its packaging are orthogonal. 82 | You can send a bill, a photo, or a love letter--or another envelope--in the 83 | same envelope. 84 | 85 | Janus messages are similar. Core messages (what you put inside the 86 | envelope) can be packaged and repackaged per circumstance, with 87 | [_transformations_](message-packaging.md). 88 | 89 | ## Case Studies 90 | 91 | Perhaps the best way to understand Janus is to observe it in action. 92 | See the following: 93 | 94 | * [Love Letters](love-letters.md) -------------------------------------------------------------------------------- /janus/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/janus/layers.png -------------------------------------------------------------------------------- /janus/love-letter-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/janus/love-letter-flow.png -------------------------------------------------------------------------------- /janus/love-letters-1-640.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/janus/love-letters-1-640.png -------------------------------------------------------------------------------- /janus/love-letters-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/janus/love-letters-1.png -------------------------------------------------------------------------------- /janus/love-letters.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Love Letters 3 | 4 | Let us use a familiar circumstance as a case study in secure communication. 5 | Suppose Alice and Bob wish to carry on a private romantic conversation. 6 | We will explore how this interaction unfolds across the edge and cloud 7 | agents owned by Alice and Bob, and how it also involves services in the 8 | low-trust layer of the ecosystem. 9 | 10 | The general flow will be as follows: 11 | 12 | ![how love letters flow](love-letter-flow.png) 13 | 14 | As we have mentioned elsewhere, people can't speak in bytes, or hear them. 15 | They need agents to do that. These agents need to be authorized, which 16 | means they need cryptographic keys. And keys means there must be a secure 17 | way to store secrets, which implies wallets. 18 | 19 | ## Initial State 20 | 21 | The state of agents, keys, wallets, and service that provide the backdrop 22 | for this interaction looks like this: 23 | 24 | 25 | 26 | Here, agents are numbered. Alice has two agents under her control: 1 (on 27 | a mobile phone, in the high trust layer) and 2 (in the cloud, in the 28 | medium trust layer). Bob also has two agents under his 29 | control: 3 (in the cloud) and 4 (on his mobile phone). A dotted line has 30 | been drawn around the _sovereign domains_ controlled by Alice and Bob. 31 | 32 | Not all of these agents are strictly necessary; Alice could use 1 and 33 | Bob could use 4, without any other parties involved. However, cloud 34 | agents add certain convenience (e.g., a stable, permanent http endpoint) 35 | and are likely to play a role most of the time, so we've included them. 36 | 37 | Some other agents are also shown -- 8 and 9. These agents are not 38 | strictly necessary, either, but again, we include them for illustrative 39 | purposes. These would be agents at the _agencies_ that host Alice and 40 | Bob's cloud agents, respectively. Such agents can provide helpful 41 | services for many customers. They are part of the low trust layer, as 42 | far as Alice and Bob ar concerned. 43 | 44 | The cryptographic material in the _identity wallets_ of each of these 45 | agents is listed under the respective number. For example, Alice's edge 46 | agent, 1, has a DID+public verkey+private signing key triple, identified 47 | by did@A:AB (the did for Alice [A] in the Alice~Bob [AB] relationship); 48 | 1.vk@A:AB (the verkey belonging to 1 on Alice's side of the AB 49 | relationship); and 1.sk@A:AB (the signing key belonging to 1 on Alice's 50 | side of the AB relationship). Hopefully the notation is intuitive enough 51 | that you can guess what other pieces of data mean. 52 | 53 | Notice that signing keys only appear in a single place -- 1.sk@A:AB 54 | appears only in 1's wallet; 2.sk@A:AB appears only in 2's wallet; 3's 55 | signing key appears only in 3's wallet; and 4's only in 4's wallet. 56 | However, the public verkey for these entities appears in multiple places. 57 | This is as we would expect; many parties know another party's verkey, 58 | but only one party knows the signing key. 59 | 60 | Notice, also, that Alice and Bob themselves do not hold any keys. This 61 | may feel a bit surprising--but remember, people can't deal with bytes. 62 | That's the job of software agents. (Technically, it is possible for Alice 63 | and Bob to hold keys on pieces of paper, but those keys are inert until 64 | they are given to a piece of software, so we ignore that case when we 65 | say "only agents can hold keys." 66 | 67 | ## Sending a message 68 | 69 | Now, suppose Alice wants to send a message to Bob. On her mobile phone, 70 | she types/texts the original message, "Sweet nothings." We will call 71 | this message _m0_. Her agent, 1, then applies a series of 72 | transformations to her message, controlling how it is encrypted and routed. 73 | The message starts in Alice's high trust layer, passes through her medium 74 | trust layer, is routed through low trust services, and eventually appears in 75 | Bob's high trust context again. We will describe these steps in excruciating 76 | detail, but like TLS in an http world, this all happens magically as far 77 | as Alice and Bob are concerned; to them, it feels like just pressing 78 | *Send* and responding to a notification that 79 | a message has arrived. 80 | 81 | ### Step 1 82 | 83 | Alice wants only Bob to be able to read _m0_. Since Bob reads 84 | messages on his phone, Alice needs to encrypt for Bob's edge agent, 4. She 85 | wants Bob to know who sent this message, so she calls `auth_crypt(` 86 | _m0_`, 4.vk@B:AB, 1.vk@A:AB)`. This transformation 87 | of her message requires the public verification key of the recipient, 88 | plus her private signing key. (In the implementation of this protocol in 89 | indy-sdk, Alice passes two verkeys instead. This is because the signing 90 | key 1.sk@A:AB is known only to her wallet, and is never accessible to the 91 | application layer; it uses the verkey to tell the wallet to look up the 92 | signing key...) This produces a new message, _m1_, 93 | that 4 can decrypt. 4 knows it came from 1, because 1's verkey is 94 | communicated in the packaging in a way that only 4 can read. (For those 95 | interested in hard-core details, the packaging uses libsodium's 96 | Public Key Authenticated Encryption plus libsodium's Sealed Box primitive.) 97 | 98 | ### Step 2 99 | 100 | Now Alice has a problem: how will she get the message to Bob? Bob's edge 101 | agent 4 doesn't have a static IP address, which is a wrinkle. Further, 102 | Alice's own phone is running out of battery. What she'd like to do is 103 | send the message to her own cloud agent, 2, before her battery dies, and give 104 | 2 instructions to get the message to 4. 105 | 106 | Alice's agent 1 packages the message for this routing instruction by calling: 107 | `forward(`_m1_, `did@B:AB)`. This transformation produces a 108 | new message, _m2_, that could be processed correctly by her 109 | cloud agent, 2. 110 | 111 | ### Step 3 112 | 113 | But who should be able to read _m2_? Only 2, of course. Between 114 | Alice's phone and her cloud agent, there may be much untrusted networking 115 | infrastructure. So Alice's agent 1 now encrypts again: 116 | `auth_crypt(`_m2_`, 2.vk@A:AB, 1.vk@B:AB)`. This produces _m3_. 117 | 118 | ### Step 4 119 | 120 | How is 2 going to get _m3_? 121 | 122 | There are many possible answers to this question, but for the current 123 | discussion we will assume that 2 is running at an agency, and that the 124 | agency provides a low-trust message routing service as part of its own 125 | agent, 8. This service is similar to a _mail tranfer agent_ in the world 126 | of SMTP; it maintains an inbox and mindlessly delivers messages according 127 | to the address label in the message packaging. 128 | 129 | Alice's agent 1 now transforms _m3_ into _m4_ by calling: 130 | `forward(`_m3_`, did@A:AB). If she gives this message to 131 | 8, it will know to route it to Alice's agent 2 because it knows that 2 132 | services did@A:AB. 133 | 134 | ### Step 5 135 | 136 | Anybody might snoop on _m4_ while it's in transit between 137 | Alice's phone and 8. Therefore, Alice's agent 1 does one final transformation: 138 | `anon_crypt(`_m4_', 8.vk). This creates _m5_. It does not tell 8 who is asking 139 | to send a message, but it prevents evesdropping. 140 | 141 | ### Step 6 142 | 143 | With all this packaging done, Alice's phone can now send _m5_ 144 | to 8 over any type of insecure channel. When it arrives, 8 calls 145 | `anon_decrypt(`_m5_`)`, and is now looking at _m4_, 146 | which is a plaintext instruction to forward a payload, _m3_, to the agent that 147 | services did@A:AB. 8 looks up this agent and decides that 2 is the proper 148 | recipient, so it forwards _m3_ as requested. It has no idea 149 | what it is forwarding, or who it came from. (You may be wondering about 150 | spam. Spam is not prevented at this layer, but rather at 2, which is 151 | in the medium trust layer. It has policies that govern what to accept 152 | and reject.) 153 | 154 | ### Step 7 155 | 156 | When 2 receives _m3_, it decrypts, noting that the sender 157 | is Alice's agent 1, which it knows to be authorized to act for Alice. 158 | The decryption produces _m2_, which is an instruction to 159 | forward an encrypted payload, _m1_, to the DID by which Bob 160 | is known to Alice. 161 | 162 | ### Step 8 163 | 164 | Alice's cloud agent, 2, now performs a process very similar to the one 165 | that her edge agent, 1, went through. It can't read Alice's plaintext 166 | message, but it knows that Alice wants an encrypted payload delivered to 167 | Bob. 168 | 169 | It looks up the permanent endpoint for Bob on the ledger; the URL 170 | that's returned is the URL of 9 (the mail routing service for Bob at 171 | Bob's agency). Just as 1 built something for 2 via 8, 2 must build something 172 | for 3 via 9. 173 | 174 | 2 begins by calling `auth_crypt(`_m1_`, 3.vk@B:AB, 2.vk@A:AB)`. 175 | This ensures that 3, upon receiving the message, will know it came from 2. 176 | The new message is _m6_. 177 | 178 | ### Step 9 179 | 180 | Now 2 has to account for the routing instruction that 9 needs to see, 181 | to deliver _m6_ to Bob's cloud agent 3. She calls 182 | `forward(`_m6_`, did@B:AB)`. This produces _m7_. 183 | 184 | ### Step 10 185 | 186 | Between 2 and 9, an evesdropper could lurk. 2 wants to guarantee that such 187 | parties can do no harm, so 2 calls `anon_crypt(`_m7_`, 9.vk)`, 188 | producing _m8_. 189 | 190 | ### Step 11 191 | 192 | 2 is now ready to send. It contacts 9 and drops the encrypted payload 193 | _m8_. When 9 sees it, 9 calls 194 | `anon_decrypt(`_m8_`)`, and is now looking at _m7_, 195 | which is a plaintext instruction to forward a payload, _m6_, 196 | to the agent that services did@B:AB. 9 looks up this agent and decides 197 | that 3 is the proper recipient, so it forwards _m6_ as requested. 198 | It has no idea what it is forwarding, or who it came from. 199 | 200 | ### Step 12 201 | 202 | When 3 receives _m6_, it decrypts. This produces _m1_, 203 | an encrypted message that 3 cannot read. However, 3 knows that this 204 | encrypted payload is intended to be read by Bob (since 3's only purpose 205 | in life is to help people communicate with Bob). Thus, 3 concludes that 206 | it must forward the message to 4. The message is already encrypted for 4, 207 | so 3 simply sends it over any convenient method (e.g., mobile push notification). 208 | And Bob gets Alice's message. 209 | 210 | ## Variations 211 | 212 | Many of the steps that we described above have alternate paths that are 213 | equally valid. For example: 214 | 215 | * Alice's agent 1 could have contacted Bob's agent 3 via 9, without ever 216 | using 2 or 8. This would simplify the workflow a fair amount, and would 217 | have the additional privacy advantage of not allowing Alice's cloud agent 218 | to be aware of some of the communication she's doing. It is a valid 219 | choice in Janus. However, such a choice would 220 | make it hard for Alice to give special delivery instructions that 221 | enhance convenience or privacy, such 222 | as "Deliver this next week, when I'm gone backpacking in the Himalayas 223 | and don't have an internet connection" or "Route this message through 224 | a mix network so 9 cannot tell the originating IP address" or "Retry 225 | message delivery for up to 6 weeks" 226 | 227 | * Alice's agent 1 could have done all of the wrapping, not just the first 228 | part that got the message to 2. This style of packaging is called "onion 229 | packaging", since it adds many layers, whereas the style we described 230 | above is called "JIT (just in time) packaging", since it only does one 231 | leg of the route at a time. Both styles have pros and cons, and both 232 | are supported by Janus. Onion packaging is more opaque to intermediate 233 | participants, but also more fragile. 234 | 235 | * Alice's agent 1 could have contacted Bob's agent 4 directly, if 1 and 236 | 4 were connected over bluetooth or some other channel that allowed a 237 | short circuit. This, too, is supported by Janus. 238 | 239 | * Alice could have chosen to use greater privacy by calling `anon_crypt()` 240 | instead of `auth_crypt()` in steps 3 and/or 8. This choices would have 241 | made it impossible for one or both of the cloud agents to recognize 242 | the sender. Janus supports such usage patterns, but either cloud agent 243 | could be configured with a policy that drops messages from anonymous 244 | senders, if Alice and Bob make that choice. 245 | 246 | 247 | -------------------------------------------------------------------------------- /janus/message-inventory.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Message Inventory 3 | 4 | A few message types are well known and trending toward standardization: 5 | 6 | * Connection request 7 | * [Credential offer](../themis/cred-offer.md), [credential request]( 8 | ../themis/cred-request.md), Credential 9 | * Proof offer, [proof request](../themis/proof-request.md), 10 | [Proof](../themis/proof-format.md) 11 | * Trust ping 12 | * Payment 13 | * Agent interface discovery and back-channel security negotiation 14 | * Arbitrary information (analogous to secure chat or s/mime) 15 | * Noise 16 | -------------------------------------------------------------------------------- /janus/message-layers.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # A Layered Ecosystem 3 | 4 | As mentioned in the Janus overview, communication unfolds against a 5 | landscape that is complex. Participants include individual human identity 6 | owners, institutions, and IoT things. These participants may be proxied 7 | by one or more software- or hardware-based agents. Technologies may be 8 | cloud-based or edge-oriented. 9 | 10 | There are many possible ways to describe this picture; each focuses on 11 | some realities but suppresses others as being less relevant to insight. 12 | 13 | Janus chooses to think in terms of layers of trust: 14 | 15 | ![layers of trust](layers.png) 16 | 17 | ## Layers of trust 18 | 19 | The high trust layer is where legal accountability lives. Interactions 20 | in this layer typically require human approval. They take place on 21 | _edge devices_ such as mobile phones, laptops, and on-prem servers 22 | belonging to an enterprise. 23 | 24 | The medium trust layer is embodied in devices and services that are not 25 | under the direct control of their associated identity owners, but that 26 | still carry out explicit instructions from those owners. These components 27 | are still _owned_ in an important sense by a single participant from the 28 | high trust layer, and have a fiduciary responsibility to proxy faithfully. 29 | 30 | The low-trust layer consists of services and devices that provide mass 31 | services. These components may be highly trustworthy, but they contribute 32 | value without needing to represent and proxy in the same way. 33 | 34 | ## Problem sets 35 | 1. Enduser problems 36 | 1. How to implement smart policy that adds value 37 | 1. SPAM 38 | 39 | ## Objectives 40 | 1. Support highly-trusted Edge Agents 41 | 1. Support semi-trusted Cloud Agents 42 | 1. Support low-trust Cloud Services (like an Agency Router) 43 | 1. Agents need to be able to act on my behalf according to some authorization or policy 44 | 45 | 46 | # Messaging Layers (Daniel & Devin) 47 | 1. Comms or Routing Layer 48 | 1. Agent Layer 49 | 1. threads of interactions 50 | 1. 51 | 52 | # Orthogonal principles 53 | 1. Edge, Cloud, Untrusted & 54 | 1. Packaging layers 55 | 56 | 57 | # Example Scenario 58 | Alice sends message to Bob 59 | 60 | # Example Structure 61 | ```json 62 | { 63 | "route_msg": sealed_box({ 64 | 65 | }) 66 | "cloud_msg": {...}, 67 | "edge_msg": { 68 | "header": { 69 | "type": "CRED", 70 | "type_version": "0.1" 71 | }, 72 | "payload": {} 73 | } 74 | ``` 75 | 76 | ```json 77 | } 78 | ``` 79 | 80 | 81 | # Packaging 82 | 1. The message itself 83 | 1. Add header (and possibly sig) for message 84 | 1. Interaction context 85 | 1. Routing: where you want to send something 86 | 87 | 88 | # Future optimization 89 | 1. Encrypting information so that agents can see a subset, and the enduser can see all, without redundancy. 90 | 91 | -------------------------------------------------------------------------------- /janus/message-packaging.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Message Packaging 3 | 4 | Message delivery is complex. The hops in message delivery between two parties might vary according to whether agents are used, how much they are trusted, and how functional edge devices are. Likewise, the way encryption is applied may need dynamic adjustment. 5 | 6 | For this reason, the protocol does not prescribe a single encryption, a single format, a single routing strategy. Instead, it defines some primitives and some standard patterns for how these primitives are combined. By composing these primitives according to circumstances, a wide variety of use cases can be addressed by a sender, with predictable and modest handling effort by the receiver. 7 | 8 | ## Crypto Transformations 9 | 10 | Janus uses elliptic curve cryptography to achieve message availability, 11 | confidentiality, and integrity. It offers three crypto primitives: 12 | 13 | ```anon_crypt(msg, recipient_verkey)``` 14 |
Encrypt only for recipient. Sender is anonymous. Parties can be unknown 15 | to each other. The message is tamper evident.
16 | 17 | ```auth_crypt(msg, recipient_verkey, sender_sigkey)``` 18 |
Encrypt only for recipient. Recipient learns sender’s verkey but can’t 19 | prove to anybody else who the sender is (making the message repudiable). 20 | Parties can be unknown to each other. The message is tamper evident.
21 | 22 | ```sign(msg, sender_sigkey)``` 23 |
Associate a non-repudiable signature with a message.
24 | 25 | ## Other Transformations 26 | 27 | ```Forward(msg)``` 28 |
Specify where and how to send something.
29 | 30 | ```Topicalize(msg)``` 31 |
Give a message a context/thread and a sequence number within that context.
32 | 33 | ```Bundle(msg)``` 34 |
Great multiple messages as a unit.
35 | 36 | ```Type(msg)``` 37 |
Describe message type, format, and version to an observer 38 | or participant in a communication chain.
39 | 40 | # Message Packaging Primitives 41 | 42 | ### Typed Messages 43 | Messages are not self-describing by themselves. They need some metadata to help describe what they are. 44 | 45 | This is done with a `type` object, which has three members. One for the type name, one for the version and one for the format of the message. 46 | 47 | Generally, the version should conform to Semantic Versioning principles and the format should make use of mime-types. 48 | 49 | Example: 50 | ```json 51 | { 52 | "name": "CRED", 53 | "version": "0.1", 54 | "format": "application/msgpack" 55 | } 56 | ``` 57 | 58 | A message can be "typed" in one of two methods. One in which the original message is unchanged, but wrapped in an object, and the other where special `@type` member is added to the message. 59 | 60 | #### Wrapping method 61 | In this method, the original message is wrapped as the `msg` element of a new object, along with a `type` object: 62 | 63 | ```json 64 | { 65 | "type": { }, 66 | "msg": { } 67 | } 68 | ``` 69 | 70 | #### Annotating method 71 | A `@type` member is included in the message object itself, as a peer to the root members of the object. 72 | ```json 73 | { 74 | "@type": {...}, 75 | 76 | } 77 | ``` 78 | 79 | Notice the annotation method uses a prepended `@` to indicate it is an annotation, that is a member that is not part of the original object. 80 | 81 | ### Signed Message 82 | Signing is only done when the use case requires it, for several reasons: 83 | 1. Authentication can be accomplished as part of the Public Key Authenticated Encryption (PKAE). 84 | 2. The Non-Repudiation offered by signing (DSA, ECDSA, EDDSA) is not always desired, as in the interrim steps of a negotiation. Signatures make a message non-repudiable. 85 | 3. Signatures are somewhat more expensive to compute and verify than other ways to authenticate, like PKAE. 86 | 87 | If a signature is required, the original message is encoded as BASE64URL and added to a new object with two other signature fields: 88 | 89 | ```json 90 | { 91 | "signed": "", 92 | "sig": "", 93 | "sig_type": "" 94 | } 95 | ``` 96 | 97 | The `sig_type` tells us how the original message was encoded, what algorithm was used to create the signature, and how the signature is encoded. 98 | 99 | For example, the `ED25519_B64U` signature scheme has the following characteristics: 100 | * Pre-conditions: **None** 101 | * Message encoding: **BASE64URL** 102 | * Signing algorithm: **ed25519** 103 | * Signature encoding: **BASE64URL** 104 | 105 | More advanced signature schemes can be used. For example, the CL_CRED_1 algorithm has the following characteristics. 106 | * Pre-conditions: **message is a typed CRED version 0.1 through 0.2, JSON** 107 | * Message encoding: **none** 108 | * Signing algorithm: **CL-RSA** 109 | * Signature encoding: **none** 110 | 111 | ### Topical Messages 112 | Messages are usually part of interactions. 113 | 114 | #### Topic ID (`tid`) 115 | Because multiple interactions can happen simultaneously, it's important to differentiate between them. This is done with a Topic ID or `tid`. 116 | 117 | The first message in an interaction should set a `tid` 118 | (128-bit random number) that the two parties use to keep 119 | track of an interaction. 120 | 121 | #### Message ID (`mid`) 122 | Each message in an interaction needs a way to be uniquely 123 | identified. This is done with Message ID (`mid`). The first 124 | message from each party has a `mid` of 0, 125 | the second message sent from each party is 1, and 126 | so forth. A message is uniquely identified in an 127 | interaction by its `tid`, the sender DID, and the `mid`. The combination of those three parts would be a way to uniquely identify a message. 128 | 129 | #### Last Message ID (`lmid`) 130 | In an interaction, it may be useful for the recipient of a message to know if their last message was received. A Last Message ID or `lmid` can be included to help detect missing messages. 131 | 132 | #### Example 133 | As an example, Alice is an issuer and she offers a credential to Bob. 134 | 135 | * Alice establishes a Topic ID, 7. 136 | * Alice sends a CRED_OFFER, `tid`=7, `mid`=0. 137 | * Bob responded with a CRED_REQUEST, `tid`=7, `mid`=0, `lmid`=0. 138 | * Alice sends a CRED, `tid`=7, `mid`=1, `lmid`=0. 139 | * Bob responds with an ACK, `tid`=7, `mid`=1, `lmid`=1. 140 | 141 | #### Nested interactions 142 | Sometimes there are interactions that need to occur with the same party, while an existing interaction is in-flight. 143 | 144 | When an interaction is nested within another, the initiator of a new interaction can include a Parent Topic ID (`ptid`). This signals to the other party that this is a topic that is branching off of an existing interaction. 145 | 146 | #### Nested Example 147 | As before, Alice is an issuer and she offers a credential to Bob. This time, she wants a bit more information before she is comfortable providing a credential. 148 | 149 | * Alice establishes a Topic ID, 7. 150 | * Alice sends a CRED_OFFER, `tid`=7, `mid`=0. 151 | * Bob responded with a CRED_REQUEST, `tid`=7, `mid`=0, `lmid`=0. 152 | * **Alice sends a PROOF_REQUEST, `tid`=11, `ptid`=7, `mid`=0.** 153 | * **Bob sends a PROOF, `tid`=11,`mid`=0, `lmid`=0.** 154 | * Alice sends a CRED, `tid`=7, `mid`=1, `lmid`=0. 155 | * Bob responds with an ACK, `tid`=7, `mid`=1, `lmid`=1. 156 | 157 | All of the steps are the same, except the two bolded steps that are part of a nested interaction. 158 | 159 | #### Topic object 160 | A topic object has the following fields discussed above: 161 | 162 | * `tid`: A mutually agreed identifier for the interaction. 163 | * `mid`: A message ID unique to the `tid` and sender. 164 | * `ptid`: An optional parent `tid`. Used when branching or nesting a new interaction off of an existing one. 165 | * `lmid`: A reference to the last message the sender received from the receiver. (Missing if it is the first message in an interaction.) 166 | 167 | The topic object can be associated with a message in one of two way. 168 | 169 | #### Wrapping Method 170 | In this method, the original message is wrapped as the `msg` element of a new object, along with a `topic` object: 171 | 172 | ```json 173 | { 174 | "topic": { }, 175 | "msg": { } 176 | } 177 | ``` 178 | 179 | #### Annotating method 180 | A `@topic` member is included in the message object itself, as a peer to the root members of the object. 181 | ```json 182 | { 183 | "@topic": {...}, 184 | 185 | } 186 | ``` 187 | 188 | ### Forward Messages 189 | A wrapper that includes an original message, plus a specific DID that is the intended recipient. 190 | 191 | Structure: 192 | ```json 193 | { 194 | "fwd": , 195 | "msg": 196 | } 197 | ``` 198 | 199 | ### Bundled Messages 200 | Sometimes, it's useful to send a collection of related messages. 201 | 202 | Structure: 203 | ```json 204 | { 205 | "bundled": [msg1, msg2], 206 | } 207 | ``` 208 | 209 | This can be useful when the recipient of a message is to forward a message on, but needs to have some information about the message. This is a common requirement with Agents, where the Agent needs to know that the message is a Credential Offer (CRED_OFFER), but doesn't need to know the details of the Credential itself. 210 | 211 | Example: 212 | ```json 213 | { 214 | "bundled": [ 215 | , 216 | { 217 | "fwd": , 218 | "msg": 219 | } 220 | ] 221 | } 222 | ``` 223 | 224 | ### Encrypted Messages 225 | There are two basic types of encrypted messages. 226 | 1. `anoncrypt`: public key anonymous encryption 227 | 1. `authcrypt`: public key authenticated encryption 228 | 229 | #### Public Key Authenticated Encryption 230 | Public Key Authenticated Encryption (PKAE) is a method where an elliptic curve diffie-hellman key exchange is used along with a nonce to compute a shared secret. This shared secret is used as a symmetric encryption key. The ciphertext can be decrypted, but only if the public key of the sender and the nonce used are communicated. The recipient knows the message is authentic because the symmetric key could only be known by the recipient and the sender. Authenticated Encryption is repudiable, meaning the recipient cannot prove to another party that the sender sent it. Because extra information is required to decrypt, this does not result in a self-contained message. 231 | 232 | #### Anoncrypt Messages 233 | `anoncrypt` messages use PKAE in conjunction with an ephemeral sender key pair to strongly encrypt a message to an intended recipient. 234 | 235 | The anoncrypt function takes the msg and the recipient's verkey as arguments. A nonce is used, but because the ephemeral key is used only once, it is deterministic. 236 | 237 | ``` 238 | anoncrypt(msg, recipient_verkey) 239 | ``` 240 | 241 | Anoncrypt messages can be decrypted. 242 | ``` 243 | anondecrypt(msg, recipient_private_key) 244 | ``` 245 | 246 | #### Authcrypt Messages 247 | `authcrypt` messages are like `anoncrypt` in that they are constructed with an ephemeral key pair. The difference is there are two attributes included with the message that make it possible to authenticate the sender: (1) sender's ver_key, and (2) signature over sender's ephemeral pub_key using the sender's sig_key (private counterpart to the ver_key). The sender's ver_key cannot be trusted. In order to trust the ver_key, the recipient must verify the signature. The signature proves to the recipient that the sender (the holder of the private counterpart to the ver_key) sent the message. This encryption retains the repudiable characteristic, in that the recipient cannot prove that the sender sent the message. They can only prove the sender once used the ephemeral key, which doesn't prove anything of any importance. 248 | 249 | Internal message structure: 250 | ```json 251 | { 252 | "from": "", 253 | "sig": "", 254 | "msg": "" 255 | } 256 | ``` 257 | 258 | #### Multiplexing Authcrypt Messages 259 | In cases where two different edge agents need to receive the same message, but the message is being sent through a common cloud agent, one solution is simply to send two separate authcrypt messages. 260 | 261 | If the message is large, this results in encrypting the message twice, and having to send it twice. It may be desireable to encrypt it and send it only once, while maintaining the requirement that both edge agents still be able to authenticate the message to the source. 262 | 263 | This can be done by a process called **Multiplexing**. 264 | 265 | In Multiplexing, the Authcrypt message is split into two parts. The **Meta** and the **Elemental**. At a high level, the Authcrypt Meta looks like a normal Authcrypt message, except the base message is moved into the Authcrypt Elemental. 266 | 267 | The Authcrypt **Meta** message holds the hash and the key of the base message, but the base is held encrypted in the **Elemental**. 268 | 269 | The sender generates a one-time random symmetric key, and encrypts the base message with this key. This is the Elemental. 270 | 271 | Then the sender constructs an Authcrypt Meta message for each recipient. It substitutes a hash of the Elemental and the symmetric key for the base message. 272 | 273 | Internal message structure (for each recipient): 274 | ```json 275 | { 276 | "from": "", 277 | "sig": "", 278 | "msg_hash": "", 279 | "msg_key": "" 280 | } 281 | ``` 282 | 283 | The Meta message's internal structure can be the same for each recipient, including using the same ephemeral keypair. However, each message is encrypted _for_ each recipient using X25519 just like any other message. 284 | 285 | The sender can then send a collection of Authcrypt Meta messages, one for each recipient, and one Authcrypt Elemental Message. The Cloud Agent can disperse the appropriate Authcrypt Meta message to each recipient, along with the Elemental Message. 286 | 287 | The recipients decrypt the Authcrypt Meta messages and verify it like any other Authcrypt message. Then it hashes Elemental and verifies it matches the hash in the Meta. Then it decrypts Elemental using the key in Meta. 288 | 289 | ##### Encryption 290 | To encrypt, the sender calls... 291 | ``` 292 | authcrypt(msg, recipient_verkey, sender_ver_key, sender_sig_key) 293 | ``` 294 | 295 | The authcrypt function... 296 | 1. Generates a new ephemeral keypair. 297 | 1. Signs the ephmeral public key using `sender_sig_key`. 298 | 1. Constructs a JSON object like so: 299 | ```json 300 | { 301 | "from": "", 302 | "sig": "", 303 | "msg": "" 304 | } 305 | ``` 306 | 1. Encrypts the object using the ephemeral private key. 307 | 1. Vigorously discards the ephemeral private key as it should only be used once. 308 | 1. Appends the ephemeral public key to the ciphertext 309 | 310 | ##### Decryption 311 | To decrypt, the recipient calls... 312 | ``` 313 | authdecrypt(msg, recipient_private_key) 314 | ``` 315 | 316 | The authdecrypt function... 317 | 318 | 1. Removes the appended ephemeral public key 319 | 1. Uses the ephemeral public key and its own private key to decrypt the ciphertext. 320 | 1. Verifies that the signature over the ephemeral public key is correct using the `sender's ver_key`. 321 | 322 | ##### Implementation using libsodium 323 | Anoncrypt is simply the sealed_box in libsodium. Authcrypt is similar, in that it uses the same deterministic nonce, and appends the ephemeral public key to the ciphertext. The main difference is the ephemeral public key must be signed in the message. Authcrypt uses a libsodium crypto_box with a deterministic nonce = hash(ephemeral pub key, recipient pub key), the same approach that sealed_box takes. 324 | 325 | ## Message Composition Patterns 326 | ### Routing Methods 327 | #### Just in Time Routing 328 | Just-in-time routing is a method where the sender sends a message to the next hop with enough information for that next hop to be able to send it to the hop after that. 329 | 330 | #### Onion Routing 331 | Onion routing is a method where the sender encapsulates all of the routing information to get the message to the end recipient. Each party in the path is able to decrypt one more layer to understand its part. 332 | 333 | ### Common Routes 334 | #### Alice Edge to Bob Edge 335 | This example assumes Just in Time Routing. 336 | 337 | Alice first constructs an "edge message" for bob, and encrypts it. 338 | ``` 339 | fwd( to=bob_did, 340 | authcrypt( to=bob_edge_ver_key, 341 | typed( 342 | MSG 343 | ) 344 | ) 345 | ) 346 | ``` 347 | This will be referred to as "edge_msg" below. 348 | 349 | Alice packages it for--and sends to--Bob's Agency's Router. 350 | ``` 351 | anoncrypt( to=bob's_agency's_router, 352 | 353 | ) 354 | ``` 355 | 356 | Bob's Agency's Router decrypts it, sees the FWD message, looks up the DID, and forwards to Bob's Cloud Agent. 357 | ``` 358 | anoncrypt( to=bob's_cloud_agent, 359 | 360 | ) 361 | ``` 362 | 363 | Bob's Cloud Agent decrypts it, sees the FWD message, looks up the DID, and forwards to Bob's Edge Agent. 364 | ``` 365 | authcrypt( to=bob's_edge_agent, 366 | 367 | ) 368 | ``` 369 | 370 | Bob's Edge Agent decrypts it and processes it. 371 | 372 | #### Alice Edge to Bob Edge though Cloud Agents 373 | Same as above, except the first hop goes to Alice's Agency's Router, then Alice's Cloud Agent, and then picks up with Bob's Agency's Router and so on. 374 | 375 | # Scratchpad below this point 376 | Bob wants Alice to share the topic info and type info with his Agent. 377 | 378 | 379 | 380 | Result: you have an authenticated message. 381 | 382 | Agency router gets 383 | sealed({to: DID, msg: }) 384 | 385 | 386 | Alice's Edge to Bob's Router to Bob's Cloud to Bob's Edge 387 | Alice's Edge to Alice’s Router to Alice's Cloud to Bob's Router to Bob's Cloud to Bob's Edge 388 | 389 | 390 | Secure Message to another party's Cloud: 391 | 392 | ``` 393 | anoncrypt( encrypted for router 394 | routed( 395 | authcrypt( encrypted for cloud 396 | topical( 397 | signed( CL_CRED 398 | typed( 399 | CRED 400 | ) 401 | ) 402 | ) 403 | ) 404 | ) 405 | ) 406 | ``` 407 | 408 | Secure Message to another party's Edge: 409 | 410 | ``` 411 | anoncrypt( encrypted for router 412 | routed( 413 | authcrypt( for cloud agent 414 | topical( 415 | shared( with credential_headers 416 | authcrypt( for edge agent 417 | signed( CL_CRED 418 | typed( 419 | CRED 420 | ) 421 | ) 422 | ) 423 | ) 424 | ) 425 | ) 426 | ) 427 | ) 428 | ``` 429 | 430 | Scenarios 431 | Msg to edge 432 | Msg to edge with part of headers revealed 433 | Msg to edge with headers revealed 434 | Msg to edge with headers and part of msg revealed 435 | Msg to edge with headers and msg revealed 436 | Msg to cloud (all revealed) 437 | 438 | 439 | Bob's router unseals the message, sees the DID,and forwards combo'ed to Bob's Cloud. 440 | 441 | 442 | 443 | 444 | 445 | Open question: 446 | 447 | Duck typing or wrap everywhere, or something in between. 448 | 449 | Candidates for duck typing: topic, 450 | 451 | @topic: { 452 | 453 | } 454 | 455 | 456 | -------------------------------------------------------------------------------- /janus/message-routing.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Message Routing 3 | TODO: Include Daniel's work here 4 | -------------------------------------------------------------------------------- /janus/message-transport.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Message Transport 3 | We need more details but here is some preliminary ideas. 4 | 5 | Messaging is transport agnostic. Messaging does not rely on transport for guarantees for delivery, security or routing. The same message package must be semantically equivalent regardless of the transport protocol used to move the bytes from one agent to another. 6 | 7 | Despite the agnostic nature of the messaging protocol, the use of a transport protocol requires agreement on conventions for the use of the said protocol. These conventions will be protocol specific and their scope is only decisions needed to transport the message on the said protocol. Anything related to the meaning, security or routing of the message is expressly out of scope. 8 | 9 | # HTTP/HTTPS 10 | ## URL 11 | The endpoint URL for messages should be a simple endpoint. It should not have route info (ex. DIDs) and should be consistent for all users of the endpoint service. 12 | 13 | Example: 14 | 15 | https://agency.example.com/msg/ 16 | ## Headers 17 | TODO: Any thoughts on http headers 18 | ## Response 19 | ### Codes 20 | #### OK 21 | How the message is processed and what response is given is the prerogative of the receiver of the message. There is two conventions for non-error response. 22 | 23 | **202 Accepted** -- The message is processed asynchronously. No content is return. 24 | 25 | **200 OK** -- If the message is processed synchronously and the return is the corresponding message. 26 | 27 | #### Error 28 | Standard 400s codes for client errors and standard 500s codes for server errors. -------------------------------------------------------------------------------- /janus/repudiation.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Repudiation 3 | 4 | If Carol receives a message that purports to come from Alice, she may naturally ask: 5 | 6 | Do I know that this really came from Alice? 7 | 8 | This is a fair question, and an important one. There are two ways to 9 | answer it: 10 | 11 | * Alice can send in a way that's repudiable 12 | * Alice can send in a way that's non-repudiable 13 | 14 | BOTH of these approaches can answer the question at hand, but they differ 15 | in _who can trust the answer_. If Carol knows Alice is the sender, 16 | but can't prove it to anybody else, then the message is publicly 17 | repudiable; if Carol can prove the origin 18 | to others, then the message is non-repudiable. 19 | 20 | # How It Works 21 | 22 | Repudiable sending may sound mysterious, but it's actually quite simple. 23 | Alice and Carol can negotiate a shared secret and trust one another not to 24 | leak it. Thereafter, if Alice sends Carol a message that uses the shared 25 | secret (e.g., it's encrypted by a negotiated symmetric 26 | encryption key), then Carol knows the sender must be Alice. However, 27 | she can't prove it to anyone, because Alice's immediate counter-response 28 | could be, "Carol could have encrypted this himself. She knows the key, too." 29 | Notice that this only works in a pairwise channel. 30 | 31 | Non-repudiable messages are typically accomplished with digital 32 | signatures. Everyone can examine a signature to verify its provenance. 33 | 34 | Fancy signature schemes such as ring signatures may represent intermediate 35 | positions, where the fact that a signature was provided by a member of 36 | a group is known--but not which specific member did the signing. 37 | 38 | # When To Use Which Strategy 39 | 40 | A common mistake of newcomers to cryptographically sophisticated 41 | communications is to assume that digital signatures should be used 42 | everywhere because they give the most guarantees. This is a misunderstanding 43 | of who needs which guarantees under which conditions. 44 | 45 | If Alice tells a secret to Carol, who should control whether the secret 46 | is reshared--Alice, or Carol? 47 | 48 | ![photo by Wassim Loumi, CC SA 2.0, Flickr: https://www.flickr.com/photos/sophotow/16559284088](whisper-secret.jpg) 49 | 50 | If Alice sends a repudiable message, _she_ gets a guarantee that Carol 51 | can't reshare it in a way that damages Alice. On the other hand, if 52 | she sends a message that's digitally signed, she has no control over 53 | where Carol shares the secret and proves its provenance. 54 | 55 | There are certainly cases where non-repudiation is appropriate. If 56 | Alice is entering into a borrower~lender relationship with Carol, 57 | Carol needs to prove to third parties that Alice, and only Alice, 58 | incurred the legal obligation. 59 | 60 | Janus supports both modes of communication. However, properly modeled 61 | interactions tend to favor repudiable messages; non-repudiation must be 62 | a deliberate choice. For this reason, Jason assumes repudiable until 63 | an explicit signature is required (in which case the `sign()` crypto 64 | primitive is invoked. This matches the physical world, where most 65 | communication is casual and does not carry the weight of legal 66 | accountability--and should not. 67 | -------------------------------------------------------------------------------- /janus/sealed-envelope.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/janus/sealed-envelope.jpg -------------------------------------------------------------------------------- /janus/security-context.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Security Context 3 | 4 | With physical mail, different approaches offer different guarantees. For 5 | example, if my letter is sealed with red wax and a stamp, I may be able 6 | to trust that it hasn't been tampered with since the wax hardened. Understanding 7 | such guarantees can have very high stakes, as with this envelope that 8 | was censored many years ago: 9 | 10 | ![By Russian post (Self-scanned) [Public domain], via Wikimedia Commons. 11 | Russia 1914-10-02 reverse of censored cover registered R-532, sent from 12 | St. Petersburg to Västerås Sweden. Opened by censor and sealed with large 13 | red circular wax seal at reverse and large purple censor marking. 14 | Stockholm 21.10.14 transit postmark and Vasteras receiver same day. 15 | Censor initials in blue crayon manuscript '3 HR'. Sent by ACEA or ASEA, 16 | Allmänna Svenska Elektriska Aktiebolaget.](sealed-envelope.jpg) 17 | 18 | Digital communication has similar variety in its guarantees, and a similar 19 | need to understand what can be trusted. Many exploits owe their existence 20 | to treating this need for clarity with casual disregard. 21 | 22 | Janus introduces a mechanism to clarify what can be trusted about a given 23 | communication -- the security context. 24 | 25 | ## What a security context can tell you 26 | 27 | All of the following questions can be answered by inspecting the security 28 | context associated with a message: 29 | 30 | * Confidentiality (_Could the message have been observed by another party_?) 31 | * Integrity (_Could the message have been tampered with since it was sent_?) 32 | * Origin (_Is the sender of the message known?_) 33 | * Non-repudiation (_Can the receiver prove the identity of 34 | the sender to a third party?_ See [this discussion about semantics of 35 | repudiation](repudiation.md).) 36 | * Traceability (_Could a third party have 37 | observed the transmission of this message from sender to receiver?_) 38 | * Replayability (_Could this message have been 39 | sent before, and copied to send again?_) 40 | * Sender Attributes (_Are certain attributes of 41 | the sender cryptographically verifiable?_ (See the [themis subprotocol]( 42 | ../themis/README.md).) 43 | * Forgeability (_Could a third party have forged this message?_) 44 | * Time Sensitive (_Has this message extended past the expiration time?_) 45 | * Multi-Factor Authentication (_Were multiple factors of authentication required to sign this message?_ 46 | 47 | 48 | ## How to use a security context 49 | 50 | When a party receives a Janus message, it also gains access to the 51 | message's security context. By inspecting the security context, it is 52 | possible to make informed decisions about how much trust should be 53 | imputed to the communication. This is a far safer model that traditional 54 | authentication, which simply asks for a party's identity, but has little 55 | to say about the way that identity is established and how it interacts 56 | with the communcations channel. 57 | 58 | Here is some pseudocode for a web service request handler that might 59 | take advantage of a Janus security context: 60 | 61 | ``` 62 | void handle_request_for_secret_meeting(HttpRequest locked, SecurityContext ctx) { 63 | boolean unlock = false; 64 | if (DANGEROUS_MODE) { 65 | ctx.ignore(CONFIDENTIALITY | INTEGRITY | ORIGIN | NONREPUDIATION); 66 | unlock = true; 67 | } else if (!ctx.has_confidentiality()) { 68 | ignore(); 69 | } else if (!ctx.has_integrity()) { 70 | ask_to_resend("Please prove your request for a secret meeting hasn't been tampered with."); 71 | } else if (!ctx.has_origin()) { 72 | int n = System.time().hourOfDay(); 73 | if (n < 6 or n > 20) { 74 | deny("I don't accept secret rendezvous requests from anonymous senders at night."); 75 | } else { 76 | unlock = true; 77 | } 78 | } else if (!ctx.has_nonrepudiation()) { 79 | deny("I don't accept secret rendezvous requests unless you give me evidence that I could later use to prove you asked for the appointment."); 80 | } else if (!ctx.has_nonforgeability()) { 81 | deny("This message uses an insecure MAC or digital signature scheme and could have been forged."); 82 | } else if (!ctx.within_elapsed_time()) { 83 | deny("This message was recieved after the elapsed amount of time. The message must be resent.) 84 | } else if (!ctx.has_mfa()) { 85 | deny("This message requires proof that Multi-Factor authentication was used to sign this signature to be accepted.") 86 | else { 87 | unlock = true; 88 | } 89 | if (unlock) { 90 | HttpRequest req = ctx.unlock_if_safe(locked, CONFIDENTIALITY | INTEGRITY | ORIGIN | NONREPUDIATION); 91 | // process request 92 | ... 93 | } 94 | } 95 | ``` 96 | 97 | 98 | -------------------------------------------------------------------------------- /janus/whisper-secret.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/janus/whisper-secret.jpg -------------------------------------------------------------------------------- /jigsaw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/jigsaw.png -------------------------------------------------------------------------------- /ledger/README.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Ledger 3 | The Ledger acts as a public, tamper evident data structure that is capable of storing and maintaining objects that support signing and authenticating, issuing and revoking, and proving and verifying peer-to-peer interactions. 4 | 5 | ## What's on the Ledger? 6 | The protocol stores the following Public Objects on the ledger: 7 | *Note: The public objects on the ledger are created/updated through events called transactions. Each transaction has 2 sections, a payload section called `data` and a meta section called `reqMetadata` that will contain metadata like the author of transaction, nonce for the transaction, etc.* 8 | 1. Public DIDs and DID Documents (including public keys and addressable endpoints) 9 | 1. Schema (supports public understanding of the organization and semantics of credentials and messages) 10 | 1. Credential Definitions (references a Schema and includes public keys created by the Issuer for that type of Credential) 11 | 1. Revocation Registries (supports proving a credential is still valid, references a Credential Definition) 12 | 1. Agent Authorization Policies (supports proving an agent is authorized to create proofs from certain credentials) 13 | 1. Anchors (supports proof of existence for objects or state of other ledgers, private or public) 14 | 15 | ## What's not on the Ledger? 16 | 1. Private keys, symmetric keys, 17 | 1. Personally identifiable information (PII), including hashes of PII 18 | 1. Credentials 19 | 1. Proofs 20 | 1. Authentication or Verification transactions 21 | 1. Application specific messages 22 | 23 | ### Requirements 24 | Generating a new Credential does not require writing to the ledger if the Issuer pre-issues the Revocation Registry. Authentication does not require a write to the ledger either; it requires a read though. 25 | 26 | Proving a Credential is not revoked, and verification of a Proof both require reading from the ledger. Therefore the ledger should have good read performance. 27 | -------------------------------------------------------------------------------- /patterns/abstract-negotiation-seq.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | title Abstract Negotiation Pattern Sequence 3 | actor Intiator as a 4 | actor Other as b 5 | 6 | note over a,b 7 | A proposal from A to B has two parts: 8 | 9 | (1) what party A commits to do 10 | (2) what A wants B to do in exchange 11 | 12 | An acceptance from B is a 13 | commitment. If B accepts, then the 14 | proposal with the acceptance 15 | together become a binding 16 | agreement. 17 | 18 | A proposal includes: 19 | (1) Party A's DID 20 | (2) Party B's DID 21 | (3) A's precondition (optional) 22 | (4) B's precondition (optional) 23 | (5) A's deliverables (array) 24 | (6) B's deliverables (array) 25 | (7) Sequencing and timing of deliverables 26 | (8) Relief for A in case of B's breach 27 | (9) Relief for B in case of A's breach 28 | (10) arbitrating authority in case of 29 | breach and relief not delivered 30 | 31 | Proposals can be pairwise, or they 32 | can be published in a public way 33 | such that anyone can accept. 34 | 35 | An acceptance needs an 36 | acknowledgement. TODO: when do the 37 | ACKs end? when published on a ledger? 38 | end note 39 | 40 | a -> b : PROPOSAL 41 | note left 42 | end note 43 | 44 | alt if proposal is unacceptable... 45 | opt can reject it 46 | a <-- b : REJECT 47 | else or counter it with a new proposal 48 | a <-- b : PROPOSAL 49 | note over a,b 50 | At this point, the other party becomes 51 | the Initiator, and the original Initiator 52 | follows this "alt" box. 53 | end note 54 | 55 | else or ignore the proposal altogether 56 | b --> b : do nothing 57 | end 58 | else if proposal is OK... 59 | a <-- b : ACCEPT 60 | alt if agreement indicates\nInitiator goes first... 61 | a -> b : delivers on commitment 62 | a <- b : delivers on commitment 63 | else if agreement indicates Other party\ngoes first 64 | a <- b : delivers on commitment 65 | a -> b : delivers on commitment 66 | end 67 | end 68 | 69 | note over a,b 70 | It's expected that the Negotiation Pattern 71 | (Offer, Request, Matter, Ack) will fit 72 | nicely in this one. It's also expected 73 | that Connection protocol will also fit 74 | nicely in this one. 75 | end note 76 | 77 | == Example: Connection == 78 | 79 | note over a,b 80 | A Connection Request is a Proposal with 81 | the following characteristics: 82 | 83 | TODO 84 | 85 | end note 86 | 87 | 88 | 89 | @enduml 90 | -------------------------------------------------------------------------------- /patterns/negotiation-seq.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | title Negotiation Pattern Sequence 3 | actor Acquirer as a 4 | actor Provider as p 5 | a <-- p : OFFER 6 | note left 7 | An initial offer is strictly required, 8 | though in practice, it is expected 9 | OFFERs will precede a REQUEST. 10 | end note 11 | 12 | a -> p : REQUEST 13 | opt optional; can loop as long as the parties have \npatience 14 | 15 | a <- p : OFFER 16 | note left 17 | If the Provider does not like the 18 | terms of a previous REQUEST, 19 | it may counter with a new 20 | OFFER, or it may abandon the 21 | negotiation. 22 | end note 23 | 24 | a -> p : REQUEST 25 | note left 26 | If the Acquirer does not like the 27 | terms of a previous OFFER, it 28 | may propose the terms they like 29 | in the REQUEST, or it may 30 | abandon the negotiation. 31 | end note 32 | 33 | end 34 | 35 | a <- p : 36 | note left 37 | The thing that was negotiated. 38 | end note 39 | 40 | a --> p : ACK 41 | note left 42 | An acknowledgement the 43 | was received. 44 | end note 45 | 46 | @enduml 47 | -------------------------------------------------------------------------------- /patterns/negotiation-state.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | title States for the Negotiation Pattern 3 | state Acquirer { 4 | state "Dead" as aDead 5 | state "Complete" as aComplete 6 | [*] --> HasOffer : got\nOFFER 7 | [*] --> Requested : send\nREQUEST 8 | Requested --> HasOffer : counter\noffer\nreceived\n(got\nOFFER) 9 | HasOffer --> Requested : accept\n(send\nREQUEST) 10 | HasOffer --> OfferDeclined : decline 11 | OfferDeclined --> aDead : abandon\nnegotiation 12 | OfferDeclined --> Requested : counter\n(send\nREQUEST) 13 | Requested --> Received : got\n 14 | Received --> aComplete : acknowledge\n(send\nACK) 15 | Received --> aComplete : ACK\nNot\nNeeded 16 | aDead --> [*] 17 | aComplete --> [*] 18 | } 19 | 20 | 21 | state Provider { 22 | state "Dead" as pDead 23 | state "Complete" as pComplete 24 | [*] --> Offered : offer\n(send\nOFFER) 25 | Offered -> HasRequest : got\nREQUEST 26 | [*] --> HasRequest : got\nREQUEST 27 | HasRequest --> RequestRejected : reject 28 | RequestRejected --> Offered : counter\n(send\nOFFER) 29 | HasRequest --> Fulfilled : fulfill\n(send\n) 30 | Fulfilled --> pComplete : got\nACK 31 | Fulfilled --> pComplete : ACK\nnot\nneeded 32 | RequestRejected --> pDead : abandon\nnegotiation 33 | pDead --> [*] 34 | pComplete --> [*] 35 | } 36 | 37 | @enduml 38 | -------------------------------------------------------------------------------- /patterns/protocol-patterns.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Protocol Patterns 3 | As we've modeled the various interactions between parties in the Sovrin protocol, patterns have emerged. Patterns are useful in that they allow us to reason about specific use cases in the context of other use cases just like them. The solution to a problem in one use case can apply nicely as a solution to other use cases that follow the same pattern. Patterns allow us to declare general solutions to problems and create and maintain a smaller and better tested codebase. 4 | 5 | ## Peer-to-peer Patterns 6 | 7 | ### The Negotiation Pattern 8 | This pattern allows two parties to asynchronously negotiate the transference of a matter (data) with a clear set of states. These states allow both sides to encapsulate intent and remain in control. 9 | 10 | This protocol was developed with the intended use with sovrin anonymous credentials (connections, credentials, and proofs). Those three use cases are quite different in material but have common elements in their product. 11 | 12 | Examples: 13 | 1. Credential Issuance 14 | 2. Proof Presentation 15 | 16 | #### Elements 17 | The following are higher level constructs that are used in the pattern description. 18 | 19 | ##### Matter 20 | The matter is the element that is being negotiated. This matter must have meaning to both parties and that meaning is understood outside of this framework. That understanding is important to the use of the protocol but not the framework itself. For example, a party that is deciding whether it should agree to terms presented must interpret the semantic meaning of the matter that is being discussed. But the mechanism for the act of agreement is the same regardless of the meaning of the matter. 21 | 22 | #### Party Roles 23 | During a negotiation there are two primary parties involved. There is a provider and a acquirer. Both parties must maintain their respective control of their side of the negotiation. They both are free to agree, counter and terminate the negotiation. And when they agree, they are the two parties that must come to agreement before the matter is exchanged. 24 | 25 | There may be other parties involved (ex. agents) but they should facilitate communication, do automated actions against a policy, or otherwise work on behalf of a primary party. They are not party to the negotiation outside of their relationship as an agent of a primary party member. 26 | 27 | ##### Provider 28 | The Provider is the holder of the matter that is being negotiated. They are responsible for the delivery of the matter in the event of a successful negotiation. The Provider uses an offer to express his intent before sending the matter if the negotiation is successful. 29 | 30 | ##### Acquirer 31 | The Acquirer will hold the matter if the negotiation is successful. The Acquirer uses requests to express his intent. The Acquirer is responsible of holding and protecting the matter once received. 32 | 33 | #### Message Types 34 | 35 | ##### Offer 36 | Sent by Provider to the Acquirer. This message must provide context to the Acquirer that provides understanding about the matter. This context could express the type, kind and content of the matter. To be effective the offer should be structured such that the Acquirer can reasonably extrapolate what the matter will contain. 37 | 38 | For example, in a verifiable credential the offer could contain the attributes that will be bound when issuing the credential (the matter). But would not contain signatures or other cryptographic elements that make the credential verifiable and useful in proofs. 39 | 40 | ##### Request 41 | Sent by the Acquirer to the Provider. This message must provide context to the Provider that provides understanding about the desired matter. This context could express the type, kind and/or context that would be an acceptable matter. This context could also express agreement with the offer. This message must precede the sending of the matter. 42 | 43 | ##### Matter 44 | Sent by the Provider. The matter message contains the matter that has been negotiated. Should match the semantics of the last request message that the Provider has agreed to. This message marks the end of the negotiation. 45 | 46 | ##### Confirmation 47 | The Acquirer can optionally send a confirmation message after receiving the matter. This confirmation will allow the Provider to know that the matter was received and in the possession of the Acquirer. Since this message is optional it is not reflected in the state diagram below. But this step could be required by the context of the negotiation. 48 | 49 | ##### Rejection 50 | Either the Provider or the Acquirer can send a rejection message. This message has context after either the Provider has received a request or the Acquirer has received an offer. Additionally, this message can be expressed as a response to any message from the other party after deciding to reject the negotiation. This message has the basic semantics that one party no longer want to negotiate over the matter. The cause may vary but the conversation is dead. Either party can initiate a negotiation by starting a new negotiation. 51 | 52 | ##### Expired 53 | Either the Provider or the Acquirer can send an expired message. This message is typically expressed as a response to any message from the other party after the negotiation has expired. The expiration time should be communicated in the offer and request messages previously sent. Either part must be able to independently set an expiration time and independently enforce it. 54 | 55 | ##### Permission Certification 56 | At any time and outside the flow of the other messages, either party should be able to ask for proof that the endpoint (eg. agents) that they interacting with is authorized by the identity owner. Maybe common for a either party to re-evaluate authorization after a long period (days) of inactivity in the negotiation (caused normal async human behavior like a weekend). 57 | 58 | #### Negotiation State Machine 59 | For either party the state machine is mostly the same. There are few paths that only one party can path through. For example, only the Acquirer can receive the matter while in the sent state and only the Provider can send the matter in the accepted state. But there is symmetry between the two parties in most areas of the exchange. For example, once either party sends an offer/req, it must wait for a response from the other party. 60 | 61 | See negotiation-seq.puml and negotiation-state.puml for the sequence diagram and states of this pattern, respectively. 62 | -------------------------------------------------------------------------------- /privacy_by_design_granular_requirements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/privacy_by_design_granular_requirements.png -------------------------------------------------------------------------------- /relationship-state-machine.md: -------------------------------------------------------------------------------- 1 | ![superseded](superseded.png) 2 | 3 | # Relationship State Machine 4 | 5 | A relationship is the way in which two or more people or things are connected. A state machine is a system that manages the transition between valid states. Events are inputs into a state machine that may cause transitions (changes in state). An indentity owner has a unique DID for every relationship he is part of. 6 | So in a 2 person relationship, there are two DIDs, one owned by each person. 7 | __For more refer: [Relationship State Machine](https://docs.google.com/document/d/1dFmQ_5NlAIrCYx7AYvvEeYlyvzv-2u3cpQqWTadJbPA/edit#).__ -------------------------------------------------------------------------------- /sovereign_privacy_by_design_distilled.md: -------------------------------------------------------------------------------- 1 | ![superseded](superseded.png) 2 | 3 | # Self-Sovereign Privacy By Design, Distilled 4 | 5 | November 2017 6 | 7 | *(This is a high-level overview of a more detailed document, [Sovereign Privacy by Design](self_sovereign_privacy_by_design_v1.md).)* 8 | 9 | Digital credentials are exciting, but they raise privacy concerns that were only latent with their physical counterparts. Given mass surveillance, proliferating cybercrime, and bulk correlation and data mining, defeatist attitudes toward privacy are unacceptable. Strong privacy is a prerequisite for true self-sovereign identity. We can and must achieve it. 10 | 11 | ## Guiding Principles 12 | 13 | **_Control_** for identity owners ~ **_Protection_** of secrets ~ **_Barriers_** against abuse ~ **_Usability_** for all 14 | 15 | ![Granular Experiments](privacy_by_design_granular_requirements.png) 16 | -------------------------------------------------------------------------------- /superseded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/superseded.png -------------------------------------------------------------------------------- /themis/README.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | 3 | ![Themis](themis.jpg) 4 | 5 | # Themis 6 | 7 | Themis is a protocol that enables powerful proving, so identity 8 | owners can know what they need to know about one another, trust that information, 9 | but also respect one another's privacy. Its name refers to a titan in 10 | Greek mythology who embodied judgment, impartiality, and fairness; she 11 | is often shown blindfolded and holding scales, which resonates with the 12 | anonymous, attribute-based credentials and the zero-knowledge proofs 13 | at the heart of Themis technology. 14 | 15 | Themis is a subset or subprotocol of the overarching protocol for self-sovereign 16 | identity. It assumes the existence of certain ecosystem features such as 17 | agents and keys, and is thus dependent on a larger context. 18 | 19 | 20 | ## Guiding Principles of this Protocol 21 | ### Distributed/Decentralized 22 | ### The Identity Owner is in control 23 | TODO: They hold the claims. They don't have to go back to the issuer to tweak their claims to be able to prove things on their claims. 24 | 25 | No coordination needed between Issuer and Relying Parties. 26 | 27 | ##### Selective Disclosure 28 | ###### True Selective Disclosure requires ZKP 29 | There are levels of selective disclosure. An example of selective disclosure might be to share just my birthdate from my driver license when I need to prove I'm over the age of 18. My birthdate can be used with other information about me shared or inferred to strongly identify me. We can do better. 30 | 31 | Better would be to share just my birth year, which would work for most people. If I turned 18 this year, then I'd have to fall back to showing birth month, and possibly birth day as well. But it's still better. 32 | 33 | Better might be to ask the Issuer to include a field just for "over 18". Then I can prove I'm over 18 without sharing my birthdate or birth year. But what if I'm a smoker and I travel to a state in the US that has a 19 year-old smoking statute? What if I'm over 18 in the UK, and I travel to the US and want to prove I'm over 21 (US drinking age). 34 | 35 | ### Themis sub-protocols 36 | The Sovrin Sub-protocols include: 37 | 1. Issuer Setup 38 | 1. Connecting 39 | 1. Issuing 40 | 1. Proving 41 | 1. Revoking 42 | 43 | #### Issuer Setup 44 | Issuers of Credentials need three basic Public Objects before they can issue Credentials: 45 | 1. A public DID and Document 46 | 1. Credential Definition 47 | 1. Revocation Registry 48 | 49 | ##### Public DID and DID Document 50 | An Issuer is a well-known entity in the Sovrin ecosystem. They have a public DID that is referenced by their Credential Definitions and Revocation Registries. 51 | 52 | ##### Credential Definition 53 | An Issuer issues Credentials against a Credential type, called a Credential Definition. A Credential Definition includes two major parts: (1) a reference to a Schema, and (2) public keys specific to the credentials issued under that Credential Definition. 54 | 55 | The Schema is a template that defines the fields and data types and semantics of the credentials issued under that Credential Definitions. A Credential Definition can reference any public Schema created by any party. This allows for public reuse of well-designed Schema, which should drive consolidation and a form of standardization over time. 56 | 57 | The public keys are used by Relying Parties to verify that a person really has a Credential from that Issuer. The issuer generates special private and public keys for a specific Credential Definition, securely storing the private keys, and publishing the public key in the Credential Definition on the ledger. 58 | 59 | These terms are abstract, so an example may be helpful. The California State Driver License Division is an Issuer. They have a number of fields on their standard driver license. They create a Schema (if an existing one is not adequate) with those fields they use on their driver license today. They call this Schema "Bear Driver License" and give it version "0.1.0". They generate the keys and publish it in a Credential Definition they call "California Driver License" and give it version "1". 60 | 61 | ##### Revocation Registry 62 | Holders of Credentials need the ability to prove the credential they have is valid without that Proof being linkable back to the Issuer or another Relying Party. The Revocation Registry is a mechanism that allows a Credential holder to prove in zero knowledge that the credential they hold has not been revoked. 63 | 64 | During setup, an Issuer creates one or more Revocation Registries to support this ability with its Credential holders. The credentials hold a special serial number that allows the holder to prove theirs is not revoked. 65 | 66 | Issuers can issue and revoke credentials in the Revocation Registry in a way that doesn't disclose which credential was revoked. If an issuer does not add the credential to the Registry, or revokes a credential, the next time a Credential holder tries to prove their credential is not revoked, they will be unable to do so. 67 | 68 | ##### Pre-issuing the Revocation Registry 69 | A credential needs to have its serial number in the Registry in order for its holder to prove it has not been revoked. Because Issuance and Revocation are done with a public Registry, there are some timing attacks that are possible if a Relying Party knows exactly when a Credential is issued. To guard against this, we recommend Issues pre-issue their revocation registry. This means every Credential they issue will already be part of the Registry, and only revocations need to be written to the public Registry. 70 | 71 | This has a side benefit of reducing the number writes to the public ledger, which also removes the chance of race conditions from using a credential too quickly after issuance. Of course more advanced schemes could be employed to limit timing attacks, but pre-issuance appears to be a simple solution. 72 | 73 | #### Connecting Sub-Protocol 74 | TODO 75 | 76 | #### Issuing Sub-Protocol 77 | The Issuing sub-protocol describes the interaction between the Issuer and Identity Owner. This interaction follows the Negotiation Pattern. Here is the mapping to the pattern: 78 | * The **Identity Owner** assumes the *Acquirer* role in the pattern. 79 | * The **Issuer** assumes the *Producer* role. 80 | * The **Credential Offer** maps to the *Offer*. 81 | * The **Credential Request** maps to the *Request*. 82 | * The **Credential** maps to the *Matter* in the pattern. 83 | 84 | If an Issuer is pre-issuing its Revocation Registry (recommended), then no ledger write is required for Issuance. Otherwise, a single transaction to update the Revocation Registry is required before the Credential can be used. 85 | 86 | Updates to a Revocation Registry can be batched. If an Issuer issues and revokes a large number of Credentials in a short period of time, these issuances and revocations can be combined in one efficient transaction. 87 | 88 | 89 | #### Proving Sub-Protocol 90 | The Proving sub-protocol describes the interaction between the Relying Party and Identity Owner. This interaction also follows the Negotiation Pattern with one caveat: there would not be a leading Proof Offer. The Authentication Sub-Protocol would start with a Proof Request. If a Credential holder could not or wished not to provide Proof as requested by the Proof Request, then the credential holder could send a Proof Offer that described the proof it was willing to share. The Authentication sub-protocol lists guidelines that the Relying Party could follow while constructing the Proof Request such that the Identity Owner can ensure that requested information respects its privacy. 91 | 92 | Here is the mapping to the pattern: 93 | * The **Relying Party** assumes the *Acquirer* role in the pattern. 94 | * The **Identity Owner** assumes the *Producer* role. 95 | * The **Proof Offer** maps to the *Offer*. 96 | * The **Proof Request** maps to the *Request*. 97 | * The **Proof** maps to the *Matter* in the pattern. 98 | 99 | #### Revoking Sub-Protocol 100 | Revocations are accomplished with a Ledger write to the Revocation Registry. The Issuer should also communicate with the Credential holder directly that their Credential was revoked using a CRED_NOTICE message. 101 | -------------------------------------------------------------------------------- /themis/cred-def.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Credential Definition 3 | *Note: The objects described below are the desired format, the current format will soon be changed to the one mentioned below. The format below is only for the `data` part of the ledger transaction.* 4 | 5 | For the holder to create a proof from a credential and the relying party to 6 | verify the proof generated from a credential, they need the issuer's public key. These public keys correspond to the secret keys the issuer used to sign the credential. 7 | A credential definition associates an issuer and their public issuance 8 | keys with a particular schema and revocation strategy. The credential definition 9 | also specifies the signature scheme used by the issuer and references the schema for the credential. 10 | Credential definitions are published on the ledger. 11 | 12 | ```json 13 | { 14 | "schemaId": "", // In Sovrin, it is the txn no of the schema 15 | "primary": { 16 | "sigType": "", 17 | "publicKey": { } 18 | }, 19 | "revocation": { 20 | "sigType": "", 21 | "publicKey": { } 22 | } // described below, this can be empty if the credential is not revocable. 23 | } 24 | ``` 25 | 26 | **Example of primary publicKey**: 27 | There is currently only one scheme in use today, "CL". This is the structure for that scheme. 28 | ```json 29 | { 30 | "rctxt": "", 31 | "z": "", 32 | "n": "", 33 | "s": "", 34 | "r": { 35 | "": "", 36 | "": "", 37 | ... 38 | } 39 | } 40 | ``` 41 | 42 | **Example of revocation public key**: 43 | There is currently only one revocation scheme in use today, "CKS" (named after its authors Jan Camenisch, Markulf Kohlweiss and Claudio Soriente, here is the [paper](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/main-51.pdf)). 44 | This is the structure for that scheme. 45 | ```json 46 | { 47 | "y": "", 48 | "pk": "", 49 | "h": "", 50 | "h0": "", 51 | "h1": "", 52 | "h2": "", 53 | "htilde": "", 54 | "hhat": "", 55 | "g": "", 56 | "gprime": "", 57 | "u": "", 58 | "qr": "", 59 | } 60 | ``` 61 | 62 | ## Revocation Registry Definition 63 | This describes the kind of revocation mechanism used for managing the revocation and/or issuance of credentials. 64 | The kind of data structure used, keys to manage that data structure and other data needed to compute the witness is mentioned here. 65 | ```json 66 | { 67 | "revocDefType": "", // In Sovrin, there is only 1 as of now called CL_ACCUM 68 | "credDefId": "", 69 | "issuanceType": "", 70 | "maxCredNum": "", 71 | "publicKey": "", // described below 72 | "tailsHash": "", 73 | "tailsLocation": "" 74 | } 75 | ``` 76 | 77 | **Revocation Registry Public Data**: 78 | ```json 79 | { 80 | "z": "" 81 | } 82 | ``` 83 | 84 | ## Revocation Registry Entry 85 | When claims are issued and/or revoked, the revocation registry needs to be updated. An update looks like this: 86 | ```json 87 | { 88 | "revocRegDefId": "", 89 | "prevAccum": "", 90 | "accum": "", 91 | "issued": [<0 or more entries>], 92 | "revoked": [<0 or more entries>], 93 | } 94 | ``` 95 | 96 | ## Code references to ledger objects 97 | 1. [CLAIM_DEF](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L234) 98 | -------------------------------------------------------------------------------- /themis/cred-offer.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Credential Offer (CRED_OFFER) 3 | 4 | A credential offer is sent from an issuer to a potential holder. It 5 | communicates the type of credential on offer, and possibly its proposed 6 | contents. It may also communicate a price that must be paid before the 7 | credential is issued. 8 | 9 | ```json 10 | { 11 | "schema_seq_no": "
", 12 | "issuer_did": "" 13 | } 14 | ``` 15 | 16 | Credential offers sent to a potential holder are typically followed by 17 | [credential request](cred-request.md) that flow the other direction. 18 | -------------------------------------------------------------------------------- /themis/cred-request.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Credential Request 3 | 4 | A credential request is sent from a potential credential holder to an 5 | issuer, asking that a credential be issued. This message is a necessary 6 | step in issuance, because the potential holder must provide a blinded 7 | _link secret_ that will be used to bind the credential exclusively 8 | to them. 9 | 10 | ```json 11 | { 12 | "data": { 13 | "issuer_did": "", 14 | "schema_seq_no": "", 15 | "blinded_ms": { 16 | "ur": "", 17 | "u": "" 18 | }, 19 | "prover_did": "" 20 | }, 21 | "nonce": "" 22 | } 23 | ``` 24 | 25 | ## Credential Notice 26 | When an issuer is making a change that affects its credential holders, it should let them know of the change. This could be because that the Issuer is updating its Credentials to a new schema, or rotating its public keys, or some breach was detected and credentials issued between a certain date period need to be reissued, or a particular credential was revoked (e.g, driver privileges suspended due to court order). This is done by sending the credential holder(s) a Credential Notice message. 27 | -------------------------------------------------------------------------------- /themis/credential.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Credential 3 | **TODO: Define** 4 | 5 | ## Locked Credentials 6 | Proofs generated from locked credentials are also locked, and these cannot be verified without being unlocked. The Relying Party can only unlock such a proof with the help of the Issuer. 7 | 8 | The privacy requirements are still in effect, in that the Relying Party and only knows what the ID Owner shares, and the Issuer knows nothing about the Proof or Credential except the Credential Pricing Class. 9 | 10 | ### Issuing a Locked Credential 11 | An Issuer can issue a **Locked Credential**, which is a Credential that can only be used to create Proofs that are locked. The Issuer locks that credential with a special key, called a **Locking Secret**. This Locking Secret will be needed to unlock Proofs during the Proving protocol. 12 | 13 | ### Creating a Proof 14 | A Credential holder that has a Locked Credential can generate a **Locked Proof**. A Locked Proof cannot be verified until it is unlocked. That proof contains a unique untraceable number called a **Locked Token**. 15 | 16 | ### Unlocking a Locked Proof 17 | The Relying Party sends the Locked Token in the form of an **Unlock Request** to the Issuer. The Unlock Request can come with a payment, which the Issuer may require in order to unlock the proof. In this case, the Unlock Request also includes proof of the Credential's **Pricing Class**, which is used to calculate the unlocking fee. 18 | 19 | The Issuer performs a calculation with both the Locked Token and the Locking Secret, to produce an **Unlocked Token**. The Issuer sends this back to the Relying Party. 20 | 21 | The Relying Party uses this Unlock Token to complete the Verification step. At this point, the Relying Party knows whatever is proven in the Proof, as if the Credential were never locked in the first place. 22 | 23 | ### Payments 24 | TODO: payments must be private to maintain privacy guarantees. 25 | 26 | ### Unlocking Coupons 27 | TODO: describe the Unlocking Coupons concept. -------------------------------------------------------------------------------- /themis/motivation.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Motivation 3 | Attributes describe the characteristics of an identity, name, birthdate, location, current employer, are all attributes (some attributes may change over time). A credential is a collection of attributes of an identity. When the credential is attested (using a digital signature) by another entity (usually an authority of some sort), the credential is called a **verifiable credential** and each attribute of the credential is called a **verifiable attribute**. 4 | Verifiable attributes allow individuals to use the relationship they have with trusted institutions to establish new trusted relationships with others, by sharing those attributes. The following objects are involved in Sovrin's attribute exchange protocol. 5 | 6 | __Taken from [Schema Elements doc](https://docs.google.com/document/d/1VT8myB5XcCJIrIU2xEE3Vgxpfa47aFswh1qDCFCBtIg/edit#). Reference this in that doc__ 7 | 1. [Schema](schema.md#Schema) 8 | 2. [Schema Elements](schema.md#Schema-Elements) 9 | 3. [Encodings](schema.md#Encodings) 10 | 4. [Subjects](schema.md#Subjects) 11 | 5. Holder 12 | This is the object that possesses the credential. It might or might not be the subject of the credential, like a father possessing the birth certificate credential is the holder of the credential, the child being the subject. 13 | 6. Issuer 14 | The object issuing the credential to a holder. This usually is an organisation like some government authority or even a private organisation. This object also possese some secret cryptographic data that is used to sign the credentials at the time of issuance. 15 | 7. Relying party 16 | The object that requests (from the holder) and receives verifiable attributes or some predicates over those. It then validates the signature over the verifiable attributes. 17 | 8. [Proof request](proof-request.md) 18 | 9. Proof 19 | The holders shares the verifiable attributes and any predicates over those with the relying party in the form of a proof. 20 | It consists of any revealed attribute values and additional cryptographic data that is sufficient for the relying party to verify the issuer's signature. 21 | More details can be found [here](proof.md) 22 | *Note: The request and generation of proof are using ZkLang which involves more objects, see [here](zklang.md) for details.* 23 | 10. [Credential Definition](cred-def.md#Credential-Definition) 24 | 11. [Credential Offer](cred-offer.md) 25 | 12. [Credential Request](cred-request.md) 26 | 13. Revocation Authority 27 | This is entity responsible for managing the revocation of credentials. This might or might not be the issuer of the credential. 28 | 14. [Revocation registry definition](cred-def.md#Revocation-Registry-Definition) 29 | 15. [Revocation registry entry](cred-def.md#Revocation-Registry-Entry) 30 | -------------------------------------------------------------------------------- /themis/non-public-objects.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Non Public Objects 3 | 4 | ## Credential Offer 5 | ```json 6 | { 7 | "schema_seq_no": "", 8 | "issuer_did": "" 9 | } 10 | ``` 11 | 12 | 13 | ## Credential Request 14 | ```json 15 | { 16 | "data": { 17 | "issuer_did": "", 18 | "schema_seq_no": "", 19 | "blinded_ms": { 20 | "ur": "", 21 | "u": "" 22 | }, 23 | "prover_did": "" 24 | }, 25 | "nonce": "" 26 | } 27 | ``` 28 | 29 | ## Proof Request 30 | ```json 31 | { 32 | "name": "", 33 | "version": "", 34 | "attributes": { 35 | "": "", 36 | "": "", 37 | "": "" 38 | }, 39 | "verifiableAttributes": "", 40 | "nonce": "" 41 | } 42 | ``` 43 | 44 | ## Credential Notice 45 | When an issuer is making a change that affects its credential holders, it should let them know of the change. This could be because that the Issuer is updating its Credentials to a new schema, or rotating its public keys, or some breach was detected and credentials issued between a certain date period need to be reissued, or a particular credential was revoked (e.g, driver privileges suspended due to court order). This is done by sending the credential holder(s) a Credential Notice message. 46 | 47 | ## Proof 48 | ```json 49 | { 50 | "msg_type": "proof", // required 51 | "version": "0.1", // required 52 | "to_did": "did:sov:BnRXf8yDMUwGyZVDkSENeq", // optional 53 | "from_did": "did:btc:GxtnGN6ypZYgEqcftSQFnC", // optional 54 | "proof_request_id": "cCanHnpFAD", 55 | "proofs": { ... }, 56 | "aggregated_proof": { ... }, 57 | "requested_proof": { ... } 58 | } 59 | ``` -------------------------------------------------------------------------------- /themis/proof-request-expression-language.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Proof Request Expression Language 3 | 4 | ## Options 5 | 6 | ### SQL-like Expressions 7 | I imagine a SQL-like language that allows for complex conditions like: 8 | * Complex natural language expression 9 | * (age > 18 from passport from US Gov't || (age > 16 from passport from US Gov't && guardian_present is true and date is today from travel_card from TSA)) || underage_ok is true from guardian_waiver from TSA 10 | * symbols 11 | * passport::US_Govt::age > 18 || (passport::US_Govt::age > 16 && guardian_present == true) 12 | * natural language 13 | * passport from US_Govt has age > 18 14 | * natural language with complex issuer 15 | * passport from (US_Govt or CAN_Govt) has age > 18 16 | ### Script-like (check on the return value of script, last expression as the return value) 17 | * valid_passport_issuer = (US_Govt or CAN_Govt) 18 | * passport from valid_passport_issuer has age > 18 19 | 20 | 21 | ## Considerations of a proof-request expression: 22 | * predicates between fields and constants 23 | * equality 24 | * greater than 25 | * greater than or equal 26 | * less than 27 | * less than or equal 28 | * between 29 | * predicates between fields and fields (from different credentials) 30 | * for example: proof that I have a passport and the name on the passport matches that of my driver license without revealing the name 31 | * logical composition 32 | * AND 33 | * OR 34 | * NOT 35 | * explicit order of operation (parentheses) 36 | * credentials about credentials 37 | * for example: I have a passport and I have a credential from a reputable authentication service that my picture matches me within the past 3 hours 38 | * conditions about revocation 39 | * proof of non-revocation 40 | * incentivizing RPs not to demand ultra-recent proof (this would be inefficient for all parties and add load to the ledger) 41 | * conditions about the issuers 42 | * for example: any driver license division of the following states (as verified by some federal authority) 43 | * conditions about how the credential was issued 44 | * All credentials are issued based on some level of authentication. How was the ID Owner authenticated? Did they know the password for their student account at a university? Was there an in-person interview at the driver license division? 45 | * conditions about insurance 46 | * if credential has errors or omissions 47 | * if credential is issued to the wrong person 48 | * if credential has been taken and is being held by the wrong person 49 | * acceptable insurers 50 | * who are the insured 51 | * required level of proceeds 52 | * conditions about semantics 53 | * perhaps there is a named Type that is "height" that has a named Encoding that is "microinch" that is "integer length in millionths of inches" 54 | -------------------------------------------------------------------------------- /themis/proof-request.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Proof Request 3 | The message sent by the relying party to the holder describing the verifiable attributes and appropriate conditions 4 | (predicates, issuer of attributes, schema of the credentials used, etc) that the holder need to satisfy. 5 | ```json 6 | { 7 | "name": "", 8 | "version": "", 9 | "attributes": { 10 | "": "", 11 | "": "", 12 | "": "" 13 | }, 14 | "verifiableAttributes": "", 15 | "nonce": "" 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /themis/proof.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Proof Format 3 | 4 | A proof is a JSON document that derives from one or more credentials. It 5 | demonstrates in a cryptographic/mathematical way that attributes within 6 | credentials held by the prover satisfy constraints requested by a verifier. 7 | 8 | Proof formats are likely to evolve over time, as the ecosystem's 9 | requirements for proving become more sophisticated, and as claims 10 | become richer. The format documented here is a good starting point, 11 | and should be sufficient for most high-priority use cases for the 12 | next year or two. 13 | 14 | Proofs generally conform to the following pattern: 15 | 16 | ```json 17 | { 18 | "msg_type": "proof", 19 | "version": "0.1", 20 | "to_did": "did:sov:BnRXf8yDMUwGyZVDkSENeq", 21 | "from_did": "did:btc:GxtnGN6ypZYgEqcftSQFnC", 22 | "proof_request_id": "cCanHnpFAD", 23 | "proofs": { ... }, 24 | "aggregated_proof": { ... }, 25 | "requested_proof": { ... } 26 | } 27 | ``` 28 | 29 | The `msg_type` and `version` fields are required and help to classify 30 | the json. `to_did` and `from_did` are optional and serve to bind the doc 31 | to a particular pairwise interaction (where `to_did` is the verifier, and 32 | `from_did` is the prover). Normally proofs are transmitted over a 33 | pairwise channel, so this information would be redundant--but having 34 | these fields continues to bind the proof to the channel even when 35 | data is at rest. 36 | 37 | The formats of `proofs` and `aggregated_proof` are documented and governed 38 | by indy-sdk. 39 | 40 | -------------------------------------------------------------------------------- /themis/public-objects.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Public Objects 3 | The public objects are stored on the ledger as transactions. [This](https://github.com/hyperledger/indy-node/blob/master/docs/transactions.md) document describes the transactions. The objects described below are the desired format, the current format will soon be changed to the one mentioned below. ALso in the actual ledger transaction, the format described below will be wrapped in a `data` section and there will be one more section called `reqMetadata` that will contain metadata like the author of transaction, nonce for the transaction, etc. 4 | 5 | ## Schema 6 | Examples: 7 | ``` 8 | { 9 | "name": "name", 10 | "items": [ 11 | {name: "first", element: , encoding: }, 12 | {name: "middle", element: , encoding: }, 13 | {name: "last", element: , encoding: } 14 | ] 15 | } 16 | 17 | { 18 | "name": "address", 19 | "items": [ 20 | {name: "line_1", element: , encoding: }, 21 | {name: "line_2", element: , encoding: }, 22 | {name: "line_3", element: , encoding: }, 23 | {element: , encoding: }, 24 | {name: "state", element: , encoding: }, 25 | {element: , encoding: } 26 | ] 27 | } 28 | 29 | { 30 | "name": "work_address", 31 | "spec": "address where subject is employed", 32 | "items": [{schema:
, flatten: true}] 33 | } 34 | 35 | { 36 | "name": "home_address", 37 | "spec": "address where subject lives", 38 | "items": [{schema:
, flatten: true}] 39 | } 40 | 41 | { 42 | "name": "loan_application", 43 | "spec": "application for a basic loan", 44 | "items": [ 45 | {schema: }, 46 | {schema: }, 47 | {schema: }, 48 | … 49 | ] 50 | } 51 | ``` 52 | 53 | ## Schema Elements 54 | ``` 55 | first_name: {spec: "subject's first given name"} 56 | 57 | middle_name: {spec: "subject's other given names minus surname"} 58 | 59 | surname: {spec: "subject's surname"} 60 | 61 | address_line: {spec: "one line of a physical address"} 62 | 63 | city: {spec: "third line of a physical address"} 64 | 65 | us_state: {spec: "one of the states or territories of the USA"} 66 | 67 | zip_code: {spec: "US zip code"} 68 | 69 | birthdate: {spec: "date subject was born"} 70 | 71 | expires: {spec: "date credential expires"} 72 | 73 | driving_class: {spec: "US driving classification"} 74 | 75 | hair_color: {spec: "color of the subject's hair"} 76 | 77 | eye_color: {spec: "color of the subject's eyes"} 78 | 79 | weight: {spec: "subject's weight"} 80 | 81 | height: {spec: "subject's height"} 82 | 83 | corrective_lenses: {spec: "subject is required to wear corrective lenses"} 84 | 85 | daytime_only: {spec: "a subject's privilege is restricted to daytime"} 86 | ``` 87 | 88 | ## Encodings 89 | ``` 90 | since_1870: {spec: "date as a count of days since 1/1/1870"} 91 | 92 | us_driving_class: {spec: "US driving class; 'standard' -> 0, 'commercial' -> 1"} 93 | 94 | utf8_sha256: {spec: "SHA256 hash of string encoded as UTF-8"} 95 | 96 | alpha2: {spec: "two character abbreviation"} 97 | 98 | dpbc: {spec: "9 digit integer; 5 digit zip code encoded with trailing zeros; remove hyphen in zip+4; examples: '90210' -> 90210000, '90210-2222' -> 902102222"} 99 | 100 | hair_color_codes: {spec: "color of hair; bald -> "BA", black -> "BL, blonde -> "BE", brown -> "BR", gray -> "GR", red/auburn -> "RA", sandy -> "SA", unknown -> "UN", white -> "WH"} 101 | 102 | hair_color: {spec: "color of hair; 'bald' -> 9, 'black' -> 1, 'blonde' -> 2, 'brown' -> 3, 'gray' -> 4, 'red/auburn' -> 5, 'sandy' -> 6, 'unknown' -> 7, 'white' -> 8"} 103 | 104 | eye_color: {spec: "color of eyes; 'black' -> 0, 'blue' -> 1, 'brown' -> 2, 'dichromat' -> 3, 'gray' -> 4, 'green' -> 5, 'hazel' -> 6, 'maroon' -> 7, 'pink' -> 8, 'unknown' -> 9"} 105 | weight_lbs: {spec: "weight in whole number of pounds (avoirdupois)"} 106 | 107 | weight_grams: {spec: "weight in whole number of grams"} 108 | 109 | length_half_inches: {spec: "length in whole number of half inches"} 110 | 111 | length_mm: {spec: "length in whole number of millimeters"} 112 | 113 | bool: {spec: "'true' -> 2, 'false' -> 1, 'unknown' -> 0"} 114 | ``` 115 | 116 | ## Credential Definition 117 | ```json 118 | "schemaId":21, // txn no of the schema 119 | "sigType": "CL", 120 | "publicKeys": { 121 | // One or more public keys, one is described below below 122 | }, 123 | ``` 124 | 125 | Public key 126 | ```json 127 | { 128 | "rctxt": "", 129 | "z": "", 130 | "n": "", 131 | "s": "", 132 | "r": { 133 | "": "", 134 | "": "", 135 | ... 136 | } 137 | } 138 | ``` 139 | 140 | ## Revocation Registry Definition 141 | ```json 142 | { 143 | "revocDefType":"type-3-pairing", 144 | "credDefId":"", 145 | "issuanceType": "", 146 | "maxCredNum": 1000000, 147 | "publicKeys": { 148 | // One or more public keys, one is described below below 149 | }, 150 | "tailsHash": "", 151 | "tailsLocation": "" 152 | } 153 | ``` 154 | 155 | Public key 156 | ```json 157 | { 158 | "y": "", 159 | "pk": "", 160 | "h": "", 161 | "h0": "", 162 | "h1": "", 163 | "h2": "", 164 | "htilde": "", 165 | "hhat": "", 166 | "g": "", 167 | "gprime": "", 168 | "u": "", 169 | "qr": "", 170 | } 171 | ``` 172 | ## Revocation Registry Entry 173 | ```json 174 | { 175 | "revocRegDefId": "reference to the revocation registry definition", 176 | "revocDefType":"type-3-pairing", 177 | "prevAccum":"", 178 | "accum":"", 179 | "issued": [], (optional) 180 | "revoked": [], 181 | } 182 | ``` 183 | 184 | 185 | ## Code references to ledger objects 186 | 1. [NYM](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L43) 187 | 1. [ATTRIB](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L88) 188 | 1. [SCHEMA](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L144) 189 | 1. [CLAIM_DEF](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L234) 190 | 1. [NODE](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L300) 191 | 1. [POOL_CONFIG](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L457) 192 | 1. [POOL_UPGRADE](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L477) -------------------------------------------------------------------------------- /themis/schema.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # Schema, Schema Elements and Encodings 3 | *Note: The objects described below are the desired format, the current format will soon be changed to the one mentioned below. The format below is only for the `data` part of the ledger transaction.* 4 | 5 | ## Schema 6 | Describes the various attributes present in a credential. Contains a field called *name* and an ordered array of locally named references to Schema Elements (see below) and other Schemas. Every member of a schema must have a unique name. It can optionally contains a field called *spec* that describes the schema. 7 | Note: When a field’s "name" attribute is missing, it inherits its name from the schema or schema element that named. 8 | ``` 9 | { 10 | "name": "name", 11 | "items": [ 12 | {name: "first", element: , encoding: }, 13 | {name: "middle", element: , encoding: }, 14 | {name: "last", element: , encoding: } 15 | ] 16 | } 17 | 18 | { 19 | "name": "address", 20 | "items": [ 21 | {name: "line_1", element: , encoding: }, 22 | {name: "line_2", element: , encoding: }, 23 | {name: "line_3", element: , encoding: }, 24 | {element: , encoding: }, 25 | {name: "state", element: , encoding: }, 26 | {element: , encoding: } 27 | ] 28 | } 29 | 30 | { 31 | "name": "work_address", 32 | "spec": "address where subject is employed", 33 | "items": [{schema:
, flatten: true}] 34 | } 35 | 36 | { 37 | "name": "home_address", 38 | "spec": "address where subject lives", 39 | "items": [{schema:
, flatten: true}] 40 | } 41 | 42 | { 43 | "name": "loan_application", 44 | "spec": "application for a basic loan", 45 | "items": [ 46 | {schema: }, 47 | {schema: }, 48 | {schema: }, 49 | … 50 | ] 51 | } 52 | ``` 53 | 54 | ## Schema Elements 55 | These are the low-level reusable elements that can be composed into Schema. 56 | ``` 57 | first_name: {spec: "subject's first given name"} 58 | 59 | middle_name: {spec: "subject's other given names minus surname"} 60 | 61 | surname: {spec: "subject's surname"} 62 | 63 | address_line: {spec: "one line of a physical address"} 64 | 65 | city: {spec: "third line of a physical address"} 66 | 67 | us_state: {spec: "one of the states or territories of the USA"} 68 | 69 | zip_code: {spec: "US zip code"} 70 | 71 | birthdate: {spec: "date subject was born"} 72 | 73 | expires: {spec: "date credential expires"} 74 | 75 | driving_class: {spec: "US driving classification"} 76 | 77 | hair_color: {spec: "color of the subject's hair"} 78 | 79 | eye_color: {spec: "color of the subject's eyes"} 80 | 81 | weight: {spec: "subject's weight"} 82 | 83 | height: {spec: "subject's height"} 84 | 85 | corrective_lenses: {spec: "subject is required to wear corrective lenses"} 86 | 87 | daytime_only: {spec: "a subject's privilege is restricted to daytime"} 88 | ``` 89 | 90 | ## Encodings 91 | Data must be encoded in order to prove things about it. Cryptographic methods work with large integer in finite fields, so we must encode elements of a credential in integers. 92 | ``` 93 | since_1870: {spec: "date as a count of days since 1/1/1870"} 94 | 95 | us_driving_class: {spec: "US driving class; 'standard' -> 0, 'commercial' -> 1"} 96 | 97 | utf8_sha256: {spec: "SHA256 hash of string encoded as UTF-8"} 98 | 99 | alpha2: {spec: "two character abbreviation"} 100 | 101 | dpbc: {spec: "9 digit integer; 5 digit zip code encoded with trailing zeros; remove hyphen in zip+4; examples: '90210' -> 90210000, '90210-2222' -> 902102222"} 102 | 103 | hair_color_codes: {spec: "color of hair; bald -> "BA", black -> "BL, blonde -> "BE", brown -> "BR", gray -> "GR", red/auburn -> "RA", sandy -> "SA", unknown -> "UN", white -> "WH"} 104 | 105 | hair_color: {spec: "color of hair; 'bald' -> 9, 'black' -> 1, 'blonde' -> 2, 'brown' -> 3, 'gray' -> 4, 'red/auburn' -> 5, 'sandy' -> 6, 'unknown' -> 7, 'white' -> 8"} 106 | 107 | eye_color: {spec: "color of eyes; 'black' -> 0, 'blue' -> 1, 'brown' -> 2, 'dichromat' -> 3, 'gray' -> 4, 'green' -> 5, 'hazel' -> 6, 'maroon' -> 7, 'pink' -> 8, 'unknown' -> 9"} 108 | weight_lbs: {spec: "weight in whole number of pounds (avoirdupois)"} 109 | 110 | weight_grams: {spec: "weight in whole number of grams"} 111 | 112 | length_half_inches: {spec: "length in whole number of half inches"} 113 | 114 | length_mm: {spec: "length in whole number of millimeters"} 115 | 116 | bool: {spec: "'true' -> 2, 'false' -> 1, 'unknown' -> 0"} 117 | ``` 118 | In the case where only one encoding is used for both proving and revealing, the encoding attribute can be a simple reference to an encoding. 119 | 120 | `"encoding": "length_mm"` 121 | 122 | When different encodings are used for proving and revealing, the encoding attribute can be a value with "prove" and "reveal" attributes. 123 | 124 | `"encoding": {"prove": "utf8_sha256", "reveal": "utf8"}` 125 | 126 | When multiple encodings are included for an attribute, the encoding attribute can be an array. These encodings can be used for both proving and revealing. 127 | 128 | `"encoding": ["length_mm", "length_meters"]` 129 | 130 | If multiple encodings are used for proving, but a different encoding is used for revealing, then the encoding attribute can be an object where the "prove" attribute is an array of encodings. 131 | 132 | `"encoding": {"prove": ["utf8_sha256", "D–M Soundex"], "reveal": "utf8"}` 133 | 134 | **Units of Measure** 135 | 136 | Units of measure are encapsulated in encodings. For example: 137 | 138 | `length_half_inches: {spec: "length in whole number of half inches"}` 139 | 140 | `length_mm: {spec: "length in whole number of millimeters"}` 141 | 142 | **Code Lists** 143 | 144 | Code lists are also encapsulated in encodings, for example: 145 | 146 | `hair_color_codes: {spec: "color of hair; bald -> 'BA', black -> 'BL', blonde -> 'BE', brown -> 'BR', gray -> 'GR', red/auburn -> 'RA', sandy -> 'SA', unknown -> 'UN', white -> 'WH'}` 147 | 148 | ## Subjects 149 | Fields can have a subject, which communicates who or what the attribute is about. 150 | ``` 151 | { 152 | name: "person" 153 | "items": [ 154 | {schema: }, 155 | {schema:
}, 156 | {schema_element: , encoding: }, 157 | ] 158 | } 159 | 160 | { 161 | "name": "birth_certificate", 162 | "items": [ 163 | {subject: "father", schema: , flatten: true}, 164 | {subject: "mother", schema: , flatten: true}, 165 | {subject: "child", schema: , flatten: true}, 166 | {subject: "father", schema_element: }, 167 | {subject: "mother", schema_element: }, 168 | ] 169 | } 170 | ``` 171 | ## Code references to ledger objects 172 | 1. [SCHEMA](https://github.com/hyperledger/indy-sdk/blob/778a38d92234080bb77c6dd469a8ff298d9b7154/libindy/src/services/ledger/types.rs#L144) -------------------------------------------------------------------------------- /themis/themis.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sovrin-foundation/protocol/0a1696282df4067fff256cb2d18cf03af658f848/themis/themis.jpg -------------------------------------------------------------------------------- /themis/unlocking_seq.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | actor Issuer as i 3 | actor "ID Owner" as ido 4 | actor "Relying Party" as rp 5 | == Issuer Setup == 6 | i -> i : generate **locking_secret**\n""new_locking_secret()"" 7 | == Issuing == 8 | i -> ido : CRED_OFFER 9 | i <- ido : CRED_REQUEST 10 | i -> i : generate **credential* 11 | i -> i : generate **locked_credential**\n""lock(credential, locking_secret)"" 12 | i -> ido : locked_credential 13 | == Proving == 14 | ido -> rp : request access 15 | ido <- rp : PROOF_REQUEST 16 | ido -> ido : generate **locked_proof** \n""generate(locked_credential, ...)"" 17 | ido -> rp: locked_proof 18 | i <- rp : UNLOCK_REQUEST(locked_token) 19 | i -> i : generate **unlocked_token** from \n""unlock(locked_token, locking_secret)"" 20 | i -> rp: unlocked_token 21 | rp -> rp: ""verify(proof, unlocked_token)"" 22 | 23 | @enduml -------------------------------------------------------------------------------- /themis/zklang.md: -------------------------------------------------------------------------------- 1 | ![superseded](../superseded.png) 2 | # ZKLang 3 | A typical interaction between an identity owner and relying party (which has asked for proof) looks like this. 4 | 1. Relying party asks for proof using Proof Request. 5 | 2. Identity owner examines the proof request and decides what credential definitions need to be used for creating the proof. The resulting object is called a proof resolution. 6 | 3. The identity owner then generates a ZKL ProofSpec defining which statement should be proven. It contains only public information (since the verifier also gets this object), and contains everything required to verify a proof, so it includes e.g. the public keys of issuers. 7 | 4. The identity owner takes his private data like values of all the attributes, credentials, link secret that is used in the chosen credentials to create a ZKL Witness. 8 | 5. The identity owner then uses the ProofSpec and Witness data to create a Proof object. 9 | 6. The identity owner then sends the Proof and the ProofSpec to the relying party. 10 | 7. The relying party then checks that the ProofSpec is compatible with the sent Proof Request and then verifies the Proof. 11 | 12 | __More on ZKLang in [ZKLang Spec](https://docs.google.com/document/d/1CLdkd70Mfa-AhnrqwTMVwBdF-HdvVNBiOKcq13lPstY/edit)__ 13 | -------------------------------------------------------------------------------- /todos.md: -------------------------------------------------------------------------------- 1 | ![superseded](superseded.png) 2 | 3 | # TODOs 4 | This document describes the various items that need to be flushed out or reconciled with different documents in this repository. 5 | Creating github issues from them is an option too. 6 | 7 | 1. Reconcile the following with [Self-Sovereign Privacy By Design](self_sovereign_privacy_by_design_v1.md) 8 | ``` 9 | ## Core Principles 10 | 11 | 1. The Identity Owner is in control 12 | 1. Distributed/Decentralized 13 | 1. Privacy by design 14 | 1. Security by design 15 | 1. Accessible for all 16 | 1. Financially accessible to all (basic identity should be free or very low cost) 17 | 1. Functionally accessible (great experience for all users, including low latency) 18 | 1. Scales to work for every person, org, or thing 19 | 20 | 21 | One of the core principles of SSI is the issuer has minimal coordination with relying parties. The more flexibility an Identity Owner has to prove things about him/herself the more useful those credentials will be. 22 | 23 | Sovrin credentials allow the identity holder to prove arbitrary predicates. My driver license can contain my birthdate, and I can prove that I am over 18, or over 19, or over 27.5, or under 65. 24 | 25 | Even for (especially for) service providers. 26 | 27 | ###### True Selective Disclosure prohibits sharing identifiers and signatures across relationships 28 | This concept is also known as Correlation Privacy. 29 | 30 | Using the same identifier for multiple relationships allows the other partyies in those relationships to share information with each other in a very efficient way. If I share my identifier and attribute x with party A, and I share that same identifier and attribute y and z with party B, then A and B have an easy way to horse-trade data about me, create a collective identity record for me. This shadow identity record would be under their control, not mine. 31 | 32 | Zero-knowledge proofs mentioned above are also required to combat another correlation point. Hashes and traditional digital signatures are by design universally unique. If I use a digital signature from an Issuer to prove attribute w and x to relying party A, and I use the same digital signature to prove attribute x and y to relying party B, then that signature serves as a unique identifier. ZKP allows for proving attributes without sharing the unique digital signatures from the issuers. 33 | 34 | Facebook is a centralized service, but even they realized this correlation risk in their SSO product and shifted to using unique identifiers for you when you authenticated for different Relying Parties. 35 | 36 | Some may argue that Relying Parties will simply ask for enough information to uniquely identify you anyway, so its no use. But until a system that allows for true selective disclosure and privacy from correlation is in use, legislatures won't prescribe its concepts, and people won't know its possible. Sovrin credentials come with this built in. When Relying Parties realize they can have strong authentication without collecting excessive toxic PII, they'll stop asking for so much of it. When people get used to sharing less PII with so many Relying Parties, they will become warry of those Relying Parties that ask for too much. 37 | 38 | ##### Minimize dependency on the ledger. 39 | ### Security by design 40 | ##### Keys at the edge 41 | ##### Private keys never shared 42 | ##### Every actor is authorized and every communication verified (zero-trust) 43 | ##### Principle of least privilege/authorization (zero-trust) 44 | ##### Minimal risk and impact of impersonation (service providers) 45 | ### Financially accessible to all 46 | ##### Minimize writes to the ledger. 47 | ### Functionally accessible 48 | ##### Allow for third party app and service providers while maintaining other security and privacy principles. 49 | ### Scalable 50 | ##### Minimize dependency on the ledger, especially writes. 51 | 52 | ## Basic Description of What's Possible with Sovrin 53 | ``` --------------------------------------------------------------------------------