From f430c5cb8e57c52b68c7956f7393ec80f860e424 Mon Sep 17 00:00:00 2001 From: stevenvegt Date: Mon, 4 Jan 2021 12:37:57 +0100 Subject: [PATCH 01/21] Initial proposal for did documents --- examples/nuts-did.md | 86 ++++++++++++++++++++++++++++++++++++ examples/organisation-did.md | 26 +++++++++++ examples/vendor-did.md | 37 ++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 examples/nuts-did.md create mode 100644 examples/organisation-did.md create mode 100644 examples/vendor-did.md diff --git a/examples/nuts-did.md b/examples/nuts-did.md new file mode 100644 index 0000000..f861255 --- /dev/null +++ b/examples/nuts-did.md @@ -0,0 +1,86 @@ +The example below describes a generic DID as can be used in the Nuts network: + +```json +{ + "@context": [ + "https://www.w3.org/ns/did/v1" + ], + // The ID of this care organization DID document. Notice the ID doesn't indicate the entity type (vendor/care organization), + // that should be derived from the entity's credentials. + // MUST start with `did` + // MUST be a `nuts` method + // Should be a UUID (type 4) without meaning (in contrary to e.g. a public key like in DIDKey) to decouple resolving from presentation. + // How to make sure someone does not try to recreate a DID with same id? -> TODO: fix in network layer? + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", + // Who may create/update/delete this document? + // OPTIONAL: + // If not present DID subject is the only controller of the DID. + // If present and lists another DID, that subject can also control the DID + // If present but the DID subject itself is not listed, the DID subject DOES NOT have control over this document. + "controller": [ + // This organisation controls its own document + "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", + // This entity is allowed to make changes to this document as well + // example usages are: + // - a trusted third party (e.g. nuts foundation or a vendor). + // - another document for the same legal organisation (when care organizations merge). + // - parent document of this organisation document which holds all key material (allows nesting for larger or complex organizations). + "did:nuts:f03a00f1-9615-4060-bd00-bd282e150c46" + ], + // All cryptographic methods associated with this DID + // SHOULD these keys always be referenced in one of the verification relationships? + "verificationMethod": [ + // Key used by the care organization to control this document (e.g. alter services) + { + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1", + "type": "RsaVerificationKey2018", + "controller": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", + "publicKeyJwk": { + "crv": "Ed25519", + "x": "VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ", + "kty": "OKP", + "kid": "_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A" + } + } + ], + // Keys specified in the section below are used to authenticate as DID controller. In other words; + // keys specified below can alter this DID document. + "authentication": [ + // Refers to a key specified in `verificationMethod` + "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1", + // This could be a recovery key for when the organization loses its private key, + // residing on a hardtoken (e.g. a Yubikey in a safe). + // This key COULD also reside in `verificationMethod` and be referenced by this section. + { + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-2", + "type": "JsonWebKey2020", + "controller": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", + "publicKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ" + } + } + ], + "assertionMethod": [ + "did:nuts:vendor:123#key-2" + // key used to sign claims + ], + "service": [ + { + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-1", + // must be the same type as the type in the vendor service + "type": "nuts:bolt:eoverdracht", + "serviceEndpoint": "did:nuts:#service-76" + }, + { + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-2", + // must be the same type as the type in the vendor service + "type": "nuts:core:consent", + "serviceEndpoint": "did:nuts:#service-2" + } + ], + "created": "2019-03-23T06:35:22Z", + "updated": "2020-08-10T13:40:06Z" +} +``` \ No newline at end of file diff --git a/examples/organisation-did.md b/examples/organisation-did.md new file mode 100644 index 0000000..2e11d1b --- /dev/null +++ b/examples/organisation-did.md @@ -0,0 +1,26 @@ +The example below describes a DID Document for a care organization: + +```json +{ + "@context": [ + "https://www.w3.org/ns/did/v1" + ], + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", + "service": [ + { + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-1", + // must be the same type as the type in the vendor service + "type": "nuts:bolt:eoverdracht", + "serviceEndpoint": "did:nuts:#service-76" + }, + { + "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-2", + // must be the same type as the type in the vendor service + "type": "nuts:core:consent", + "serviceEndpoint": "did:nuts:#service-2" + } + ], + "created": "2019-03-23T06:35:22Z", + "updated": "2020-08-10T13:40:06Z" +} +``` \ No newline at end of file diff --git a/examples/vendor-did.md b/examples/vendor-did.md new file mode 100644 index 0000000..052e531 --- /dev/null +++ b/examples/vendor-did.md @@ -0,0 +1,37 @@ +The example below describes a DID Document for a vendor: + +```json +{ + "@context": [ + "https://www.w3.org/ns/did/v1" + ], + "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266", + "service": [ + { + "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-1", + "type": "nuts:core:oauth", + "version": "1.0", + "serviceEndpoint": "https://api.example.org/oauth" + }, + { + "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-2", + "type": "nuts:core:consent", + "version": "1.0", + "serviceEndpoint": "https://corda.example.org/" + }, + { + "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-76", + // Specifies the type of the service, generally a Nuts Bolt. If a care organization refers to this service, + // it must specifiy the same type (`nuts:bolt:eoverdracht` in this case). + "type": "nuts:bolt:eoverdracht", + "version": "1.0", + "serviceEndpoint": { + "data": "https://api.example.org/fhir/", + "auth": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-1" + } + } + ], + "created": "2019-03-23T06:35:22Z", + "updated": "2020-08-10T13:40:06Z" +} +``` \ No newline at end of file From fddcf9b0705c924a32420ab564597ca565a67d94 Mon Sep 17 00:00:00 2001 From: stevenvegt Date: Mon, 4 Jan 2021 17:11:14 +0100 Subject: [PATCH 02/21] Add Nuts DID method --- examples/nuts-did.md | 45 ++++++++------ examples/organisation-did.md | 2 +- examples/vendor-did.md | 2 +- rfc/rfcdid-did-nuts-method.md | 107 ++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 rfc/rfcdid-did-nuts-method.md diff --git a/examples/nuts-did.md b/examples/nuts-did.md index f861255..8963846 100644 --- a/examples/nuts-did.md +++ b/examples/nuts-did.md @@ -1,11 +1,11 @@ -The example below describes a generic DID as can be used in the Nuts network: +The example below describes a generic Nuts DID to be used in the Nuts network: ```json { "@context": [ "https://www.w3.org/ns/did/v1" ], - // The ID of this care organization DID document. Notice the ID doesn't indicate the entity type (vendor/care organization), + // The ID of the DID. Notice the ID doesn't indicate the entity type (vendor/care organization), // that should be derived from the entity's credentials. // MUST start with `did` // MUST be a `nuts` method @@ -18,19 +18,18 @@ The example below describes a generic DID as can be used in the Nuts network: // If present and lists another DID, that subject can also control the DID // If present but the DID subject itself is not listed, the DID subject DOES NOT have control over this document. "controller": [ - // This organisation controls its own document + // First controller equals this document's DID, meaning it controls its own document "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", // This entity is allowed to make changes to this document as well // example usages are: // - a trusted third party (e.g. nuts foundation or a vendor). - // - another document for the same legal organisation (when care organizations merge). - // - parent document of this organisation document which holds all key material (allows nesting for larger or complex organizations). + // - another document for the same legal care organization (when organizations merge). + // - parent document of this document which holds all key material (allows nesting for larger or complex organizations). "did:nuts:f03a00f1-9615-4060-bd00-bd282e150c46" ], - // All cryptographic methods associated with this DID - // SHOULD these keys always be referenced in one of the verification relationships? + // `verificationMethod` contains all cryptographic keys associated with this DID. They are referenced by the + // verification relationships (e.g. `authentication` or `assertionMethod`) "verificationMethod": [ - // Key used by the care organization to control this document (e.g. alter services) { "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1", "type": "RsaVerificationKey2018", @@ -41,16 +40,9 @@ The example below describes a generic DID as can be used in the Nuts network: "kty": "OKP", "kid": "_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A" } - } - ], - // Keys specified in the section below are used to authenticate as DID controller. In other words; - // keys specified below can alter this DID document. - "authentication": [ - // Refers to a key specified in `verificationMethod` - "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1", - // This could be a recovery key for when the organization loses its private key, + }, + // This could be a recovery key for when the party loses its private key, // residing on a hardtoken (e.g. a Yubikey in a safe). - // This key COULD also reside in `verificationMethod` and be referenced by this section. { "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-2", "type": "JsonWebKey2020", @@ -62,10 +54,23 @@ The example below describes a generic DID as can be used in the Nuts network: } } ], + // Keys specified in the section below are used to authenticate as DID controller. In other words; + // keys specified below can alter this DID document. + // Entries MUST NOT contain embedded key material and all MUST reference keys containing in the verificationMethod + "authentication": [ + // Key used by the party to control this document (e.g. alter services) + "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1", + // Recovery key (e.g. hardtoken) + "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-2" + ], + // `assertionMethod` indicates the keys used when signing Verifiable Credentials (VC). Examples use cases: + // - Vendor issuing a VC to care organization stating "this is my client" + // - Care organization issuing a VC stating "this is my software vendor" + // TODO: discuss these use cases and specify "assertionMethod": [ - "did:nuts:vendor:123#key-2" - // key used to sign claims + "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1" ], + // `service` indicate high-level "service": [ { "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-1", @@ -80,7 +85,9 @@ The example below describes a generic DID as can be used in the Nuts network: "serviceEndpoint": "did:nuts:#service-2" } ], + // MUST contain the timestamp at which the DID document was first created "created": "2019-03-23T06:35:22Z", + // MUST contain the timestamp at which the DID document was last updated "updated": "2020-08-10T13:40:06Z" } ``` \ No newline at end of file diff --git a/examples/organisation-did.md b/examples/organisation-did.md index 2e11d1b..588ae74 100644 --- a/examples/organisation-did.md +++ b/examples/organisation-did.md @@ -1,4 +1,4 @@ -The example below describes a DID Document for a care organization: +The example below expands on the generic Nuts DID and describes a DID Document for a care organization: ```json { diff --git a/examples/vendor-did.md b/examples/vendor-did.md index 052e531..7642385 100644 --- a/examples/vendor-did.md +++ b/examples/vendor-did.md @@ -1,4 +1,4 @@ -The example below describes a DID Document for a vendor: +The example below expands on the generic Nuts DID and describes a DID Document for a vendor: ```json { diff --git a/rfc/rfcdid-did-nuts-method.md b/rfc/rfcdid-did-nuts-method.md new file mode 100644 index 0000000..7ff61a0 --- /dev/null +++ b/rfc/rfcdid-did-nuts-method.md @@ -0,0 +1,107 @@ +# Nuts DID Method Specification + +## About + +## Abstract + +## Status +Draft + +#### Copyright Notice +This document is released under the [Attribution-ShareAlike 4.0 International \(CC BY-SA 4.0\) license](https://creativecommons.org/licenses/by-sa/4.0/). + +## 1. Nuts DID Method +The Nuts DID scheme is defined as follows: +``` +did = "did:nuts:" idstring +idstring = 21*22(base58char) +base58char = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "A" / "B" / "C" + / "D" / "E" / "F" / "G" / "H" / "J" / "K" / "L" / "M" / "N" / "P" / "Q" + / "R" / "S" / "T" / "U" / "V" / "W" / "X" / "Y" / "Z" / "a" / "b" / "c" + / "d" / "e" / "f" / "g" / "h" / "i" / "j" / "k" / "m" / "n" / "o" / "p" + / "q" / "r" / "s" / "t" / "u" / "v" / "w" / "x" / "y" / "z" + +``` + +Where the `idstring` is generated from taking the SHA-256 hash of the public key from a Ed25519: + +`idstring = BASE-58(SHA-256(raw-public-key-bytes))` + +Example: +Consider the following JWK encoded Ed25519. + +```javascript +var key = { + "kty" : "OKP", + "crv" : "Ed25519", + "x" : "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", + "d" : "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", + "use" : "sig", + "kid" : "FdFYFzERwC2uCBB46pZQi4GG85LujR8obt-KWRBICVQ" +} +``` +Where the `x` parameter is the base64 encoded public key. +`idString = Base58Encode(Sha256(Base64urlDecode(key.x)))` + +## 2. Namespace Specific Identifier (NSI) + +Identifiers are derived from public keys that are valid at the moment of creating the DID document. +It MUST be the public key that corresponds to the private key that was used to sign the Nuts registry document (RFC004). +The public key MUST also be present in the `verificationMethods`. When multiple keys are present, one MUST verify in this matter. + +## 3. Method operations + +Changes to DID documents can only be accepted if the update is signed with one of the following keys: + +- a key referenced from the `authentication` section of the latest DID document version. +- a key referenced from the `authentication` section of a controller. One of the entries in the `controller` field MAY refer to a different DID Document. + The `authentication` keys of the latest version of that DID Document can be used as authorized key. +- a key referenced from the `authentication` section of the given DID document if it is a `Create` action. + +The `controller` field MAY be present. If no `controller` field is present, the DID subject itself is the controller. +If the `controller` field is present, only the DID subjects from the `controller` field can change the DID document. + +### Create (Register) + +Jws payload: +```json +{ + "id": "", + "controller": [], + "verificationMethod": [], + "authentication": [], + "service":[] +} +``` + +### Read (Resolve) +A Nuts DID can only be resolved locally. The concept of the Nuts registry is the state based upon all Create, Update and Delete operations received through the Nuts Network. +Therefore any DID SHOULD already be present in the local storage. + +### Update (Replace or patch?) +Only the following properties COULD be updated: + + +The following example shows a replace: +```json +{ + "did": "", + "document": { + "controller": [], + "verificationMethod": [], + "authentication": [], + "service":[] + } +} +``` + +### Delete (Revoke) + +DID Documents cannot be deleted as in being "erased", only its keys can be removed as to prevent future changes (revocation). +To revoke the keys to prevent future updates; + +1. Remove all keys (specified by `verificationMethod`) and references (specified by e.g. `authentication`) to + these keys from the document. +2. Remove all controllers from the document. + +## 4. Security Considerations From 6bcfa4ca02cc72577e5cdbd96d9725b1970f6846 Mon Sep 17 00:00:00 2001 From: stevenvegt Date: Tue, 5 Jan 2021 12:09:28 +0100 Subject: [PATCH 03/21] More details and changes to rfc004 --- examples/nuts-did.md | 6 +- rfc/rfc004-distributed-document-format.md | 24 ++-- rfc/rfcdid-did-nuts-method.md | 160 ++++++++++++++++++++-- 3 files changed, 159 insertions(+), 31 deletions(-) diff --git a/examples/nuts-did.md b/examples/nuts-did.md index 8963846..11341a5 100644 --- a/examples/nuts-did.md +++ b/examples/nuts-did.md @@ -84,10 +84,6 @@ The example below describes a generic Nuts DID to be used in the Nuts network: "type": "nuts:core:consent", "serviceEndpoint": "did:nuts:#service-2" } - ], - // MUST contain the timestamp at which the DID document was first created - "created": "2019-03-23T06:35:22Z", - // MUST contain the timestamp at which the DID document was last updated - "updated": "2020-08-10T13:40:06Z" + ] } ``` \ No newline at end of file diff --git a/rfc/rfc004-distributed-document-format.md b/rfc/rfc004-distributed-document-format.md index 9369cb9..2407aa7 100644 --- a/rfc/rfc004-distributed-document-format.md +++ b/rfc/rfc004-distributed-document-format.md @@ -45,11 +45,8 @@ Documents MUST be encoded as [RFC7515 JSON Web Signature](https://tools.ietf.org In addition to required header parameters as specified in RFC7515 the following requirements apply: -* **x5c**: MUST be present and contain exactly one entry with the X.509 signing certificate associated with the private key. - - The certificate MUST have the digitalSignature and contentCommitment key usages and must be valid at time of signing. - - The certificate SHOULD conform to [RFC008 Certificate Structure](rfc008-certificate-structure.md) so other parties can validate it. +* The signing key is indicated by **kid** or **jwk**. One of them MUST be present, but not both. If **kid** is present + the key must be known and looked up locally. Otherwise the key must be taken from the **jwk** header. * **alg**: MUST be one of the following algorithms: `PS256`, `PS384`, `PS512`, `ES256`, `ES384` or `ES512`. @@ -58,7 +55,7 @@ In addition to required header parameters as specified in RFC7515 the following * **cty**: MUST contain the type of the payload indicating how to interpret the payload encoded as string. * **crit** MUST contain the **sigt**, **ver** and **prevs** headers. -The **jku**, **jwk**, **kid** and **x5u** header parameters SHOULD NOT be used and MUST be ignored by when processing the document. +The **jku**, **x5c** and **x5u** header parameters SHOULD NOT be used and MUST be ignored by when processing the document. In addition to the registered header parameters, the following headers MUST be present as protected headers: @@ -75,7 +72,7 @@ The following headers MAY be present as protected headers \(see section 3.4 for defaults to `0`. -To aid performance of validating the DAG the JWS SHALL NOT contain the actual contents of the document. Instead, the JWS payload MUST contain the SHA-1 hash of the contents encoded as hexadecimal, lower case string, e.g.: `148b3f9b46787220b1eeb0fc483776beef0c2b3e` +To aid performance of validating the DAG the JWS SHALL NOT contain the actual contents of the document. Instead, the JWS payload MUST contain the SHA-256 hash of the contents encoded as hexadecimal, lower case string, e.g.: `148b3f9b46787220b1eeb0fc483776beef0c2b3e` The contents then MAY be stored next to or apart from the document itself \(but that's out of scope for this RFC\). @@ -83,7 +80,7 @@ There SHOULD be only 1 signature on the JWS. If there are multiple signatures al #### 3.2. Document Reference -The document reference uniquely identifies a document and is used to refer to it. It MUST be calculated by taking the bytes of the JWS EXACTLY as received and hashing it using SHA-1. +The document reference uniquely identifies a document and is used to refer to it. It MUST be calculated by taking the bytes of the JWS EXACTLY as received and hashing it using SHA-256. When serializing a reference to string form it MUST be hexadecimal encoded and SHOULD be lowercase, e.g.: `148b3f9b46787220b1eeb0fc483776beef0c2b3e` @@ -155,14 +152,9 @@ until queue empty; take document from queue #### 3.6. Signature verification -Before interpreting a document's payload it SHOULD be validated according to the following rules: - -* Assert cryptographic signature; can it be validated with the public key in the signing certificate? -* Assert the certificate is trusted. -* Assert the certificate and chain was valid at signing time. -* Assert the certificate is meant for signing; key usage MUST be `digitalSignature`. - -Note there's no need for certificate revocation status checking; certificates are generally short-lived \(as specified by [RFC008 Certificate Structure](rfc008-certificate-structure.md)\). +Before interpreting a document's payload the JWS' signature MUST be validated. When **kid** is used to specify the +signing key and the system knows additional usage restrictions (e.g. the key is valid from X to Y, to be checked against **sigt**), +the system MUST assert the usage is compliant. ## 4. Example diff --git a/rfc/rfcdid-did-nuts-method.md b/rfc/rfcdid-did-nuts-method.md index 7ff61a0..d787a80 100644 --- a/rfc/rfcdid-did-nuts-method.md +++ b/rfc/rfcdid-did-nuts-method.md @@ -8,6 +8,8 @@ Draft #### Copyright Notice +![](../.gitbook/assets/license.png) + This document is released under the [Attribution-ShareAlike 4.0 International \(CC BY-SA 4.0\) license](https://creativecommons.org/licenses/by-sa/4.0/). ## 1. Nuts DID Method @@ -43,6 +45,13 @@ var key = { Where the `x` parameter is the base64 encoded public key. `idString = Base58Encode(Sha256(Base64urlDecode(key.x)))` +example: +```json +{ + "id": "did:nuts:e3cacd5c2d931295a64f6c3bb3f6ea58c3a9b253b990e32c5abce43c2f94c564" +} +``` + ## 2. Namespace Specific Identifier (NSI) Identifiers are derived from public keys that are valid at the moment of creating the DID document. @@ -51,6 +60,11 @@ The public key MUST also be present in the `verificationMethods`. When multiple ## 3. Method operations +DID documents are enclosed in a message envelope to ensure consistency in the network. +The envelope is in the form of a JWS as described in [RFC004]. +Once the network layer has confirmed the signature of the JWS, the registry MUST validate if the submitter is authorized to create, update or delete the document. +If the authorization fails, the document should be ignored. + Changes to DID documents can only be accepted if the update is signed with one of the following keys: - a key referenced from the `authentication` section of the latest DID document version. @@ -61,40 +75,131 @@ Changes to DID documents can only be accepted if the update is signed with one o The `controller` field MAY be present. If no `controller` field is present, the DID subject itself is the controller. If the `controller` field is present, only the DID subjects from the `controller` field can change the DID document. +jws specification + +`cty` MUST contain the value `application/json+did-document` + + ### Create (Register) +Example JOSE header + +```json +{ + "alg": "PS256", + "cty": "application/json+did-document", + "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "jwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC", + "kid": "_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + }, + "crit": [ + "sigt", + "ver", + "prevs" + ], + "sigt": "", + "ver": "1", + "prevs": [ + "148b3f9b46787220b1eeb0fc483776beef0c2b3e" + ] +} +``` + Jws payload: + ```json { "id": "", "controller": [], - "verificationMethod": [], - "authentication": [], - "service":[] + "verificationMethod": [{ + "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "type": "JsonWebKey2020", + "controller": "did:nuts:123", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC", + "kid": "_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + } + }], + "authentication": ["did:example:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], + "service": [] } ``` +Example signature: +``` +SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + ### Read (Resolve) A Nuts DID can only be resolved locally. The concept of the Nuts registry is the state based upon all Create, Update and Delete operations received through the Nuts Network. -Therefore any DID SHOULD already be present in the local storage. +Therefore, any DID SHOULD already be present in the local storage. -### Update (Replace or patch?) -Only the following properties COULD be updated: - - -The following example shows a replace: ```json { - "did": "", "document": { + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3", "controller": [], "verificationMethod": [], "authentication": [], "service":[] + }, + "metadata": { + "kid": "did:nuts:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3#key1", + "created": "2021-01-04T12:15:06Z", + "updated": "2021-01-05T10:27:22Z" } } ``` +### Update (Replace) +The complete document gets replaced. + +The following example shows a replace (not a patch): +Example JOSE header +```json +{ + "alg": "PS256", + "cty": "application/json+did-document", + "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "crit": ["sigt", "ver","prevs"], + "sigt": "", + "ver": "1", + "prevs": ["148b3f9b46787220b1eeb0fc483776beef0c2b3e"], + "tid": "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", + "tiv": "1" +} +``` + +Example payload: +```json +{ + "id": "did:nuts:123", + "controller": [], + "verificationMethod": [{ + "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "type": "JsonWebKey2020", + "controller": "did:nuts:123", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC", + "kid": "_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + } + }], + "authentication": ["did:example:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], + "service":[] +} +``` + ### Delete (Revoke) DID Documents cannot be deleted as in being "erased", only its keys can be removed as to prevent future changes (revocation). @@ -104,4 +209,39 @@ To revoke the keys to prevent future updates; these keys from the document. 2. Remove all controllers from the document. +Deletion can not be undone. + ## 4. Security Considerations + +Almost all security considerations are covered by the mechanisms described in RFC004. An overview of countermeasures: + +- **eavesdropping** - All communications is sent over two-way TLS. All data is public anyway. +- **replay** - DID documents are identified and published by their hash (SHA256). Replaying will result in replaying the exact same content. +- **message insertion** - RFC004 defines hashing and signing of published documents. +- **deletion** - All DID documents are published and copied on a mesh network. Deletion of a single document will only occur locally and will not damage other nodes. +- **modification** - DID documents can only be modified if they are published with a signature from one of the `authentication` keys. +- **man-in-the-middle** - All communications is sent over two-way TLS and all documents are signed. A DID can not be hijacked since it is derived from the public key. +- **denial of service** - This is out of scope and handled by RFC004. + +### 4.1. Protection against DID hijacking + +The Nuts network is a mesh network without central authority. This means that any party can generate a DID. +This DID must be protected against forgery and hijacking since duplicates are accepted in the Nuts network. +The duplicates are sorted and one will eventually be accepted (consistency rules of RFC004). This would open up a DID to hijacking. +Therefore, the DID MUST be a derivative of the public key used to sign the document as described in chapter 2. + +### 4.2 Protection against loss of private key + +The loss of a single private key can be countered by registering multiple keys. Keys can be kept offline, in a vault for example. +Such a key can later be used to register new keys when needed. Another option is to add a second controller that acts as an emergency backup. +The keys of that controller can be kept offline. + +### 4.3 Protection against theft of private key + +A stolen key can alter the DID document in such a way that the attacker can get full control with a new key and can exclude the previous owner from making changes. +Appropriate measures MUST be taken to keep authentication keys secure. + +It's recommended to add a 2nd controller to every DID document. That DID document MAY have more than 1 controller as well. +The DID subject whose DID document only contains a single controller SHOULD keep their authentication keys offline. +Since the controller field may not be altered, this would always allow the owner of the offline key to be in control. + From 1adb811c7659f4c41c2db56f788c5c28ea8ae8c6 Mon Sep 17 00:00:00 2001 From: stevenvegt Date: Tue, 5 Jan 2021 15:20:29 +0100 Subject: [PATCH 04/21] Update section about DID hijacking --- rfc/rfcdid-did-nuts-method.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/rfc/rfcdid-did-nuts-method.md b/rfc/rfcdid-did-nuts-method.md index d787a80..26f4427 100644 --- a/rfc/rfcdid-did-nuts-method.md +++ b/rfc/rfcdid-did-nuts-method.md @@ -223,7 +223,7 @@ Almost all security considerations are covered by the mechanisms described in RF - **man-in-the-middle** - All communications is sent over two-way TLS and all documents are signed. A DID can not be hijacked since it is derived from the public key. - **denial of service** - This is out of scope and handled by RFC004. -### 4.1. Protection against DID hijacking +### 4.1 Protection against DID hijacking The Nuts network is a mesh network without central authority. This means that any party can generate a DID. This DID must be protected against forgery and hijacking since duplicates are accepted in the Nuts network. @@ -241,7 +241,10 @@ The keys of that controller can be kept offline. A stolen key can alter the DID document in such a way that the attacker can get full control with a new key and can exclude the previous owner from making changes. Appropriate measures MUST be taken to keep authentication keys secure. -It's recommended to add a 2nd controller to every DID document. That DID document MAY have more than 1 controller as well. -The DID subject whose DID document only contains a single controller SHOULD keep their authentication keys offline. -Since the controller field may not be altered, this would always allow the owner of the offline key to be in control. +When control over a DID document has been lost, the DID subject will have to have all Verifiable Credentials revoked. +Without Verifiable Credentials linked to the DID document, the DID document no longer has any value. +The DID subject will have to go through the process of reacquiring all Verifiable Credentials for a new DID document. +## 5. Privacy considerations + +All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. \ No newline at end of file From 6a182286ce1cf094d29c092b772b427530d0c317 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Tue, 5 Jan 2021 16:42:50 +0100 Subject: [PATCH 05/21] added intro chapters and expanded on create method spec --- rfc/rfc004-distributed-document-format.md | 33 +++--- rfc/rfcdid-did-nuts-method.md | 134 +++++++++++++++------- 2 files changed, 108 insertions(+), 59 deletions(-) diff --git a/rfc/rfc004-distributed-document-format.md b/rfc/rfc004-distributed-document-format.md index 2407aa7..21ba50c 100644 --- a/rfc/rfc004-distributed-document-format.md +++ b/rfc/rfc004-distributed-document-format.md @@ -1,47 +1,45 @@ # RFC004 Distributed Document Format -## RFC004 Distributed Document Format - | | | | :--- | :--- | | Nuts foundation | R.G. Krul | | Request for Comments: 004 | Nedap | | | September 2020 | -### Distributed Document Format +## Distributed Document Format -#### Abstract +### Abstract This RFC describes an interoperable, content agnostic data format for distributed networks which provides cryptographic authentication and verification of its contents, guaranteed ordering and access control. -#### Status of document +### Status of document This document is currently a draft. -#### Copyright Notice +### Copyright Notice ![](../.gitbook/assets/license.png) This document is released under the [Attribution-ShareAlike 4.0 International \(CC BY-SA 4.0\) license](https://creativecommons.org/licenses/by-sa/4.0/). -### 1. Introduction +## 1. Introduction Because Nuts is a decentralized network there needs to be a standardized format for structuring public information \(like where to find another care organization's data\) in a way that allows each party to independently verify the authenticity and integrity of that information. This document proposes such a format. Systems can use the format to build their application on top of it making it suitable for publishing on a distributed network. This document does not define how to transport data to other participants in a distributed network. -### 2. Terminology +## 2. Terminology * **Document**: piece of application data enveloped with metadata like signatures and references to other documents published on a distributed network. * **Root document** the first document published on a network. Other terminology comes from the [Nuts Start Architecture](rfc001-nuts-start-architecture.md#nuts-start-architecture). -### 3. Document Format +## 3. Document Format Documents MUST be encoded as [RFC7515 JSON Web Signature](https://tools.ietf.org/html/rfc7515). It can be serialized in either compact \([RFC7515 section 7.1](https://tools.ietf.org/html/rfc7515#section-7.1)\) or JSON \([RFC7515 section 7.2](https://tools.ietf.org/html/rfc7515#section-7.2)\) form. When the document data starts with an accolade \(`{`\) it MUST be assumed the document is serialized in JSON format, otherwise compact format MUST be assumed. -#### 3.1. JWS implementation +### 3.1. JWS implementation In addition to required header parameters as specified in RFC7515 the following requirements apply: @@ -78,13 +76,13 @@ The contents then MAY be stored next to or apart from the document itself \(but There SHOULD be only 1 signature on the JWS. If there are multiple signatures all signatures except the first one MUST be ignored. -#### 3.2. Document Reference +### 3.2. Document Reference The document reference uniquely identifies a document and is used to refer to it. It MUST be calculated by taking the bytes of the JWS EXACTLY as received and hashing it using SHA-256. When serializing a reference to string form it MUST be hexadecimal encoded and SHOULD be lowercase, e.g.: `148b3f9b46787220b1eeb0fc483776beef0c2b3e` -#### 3.3. Ordering, branching and merging +### 3.3. Ordering, branching and merging Documents MUST form a rooted DAG \(Directed Acyclic Graph\) by referring to the previous document. This MAY be used to establish _casual ordering_, e.g. registration of a care organization as child object of a vendor. A new document MUST be appended to the end of the DAG by referring to the last document of the DAG \(_leaf_\) by including its reference in the **prevs** field. @@ -108,7 +106,7 @@ The following orders are invalid: * `A -> B -> D -> F -> C -> E` \(merger processed before all previous were processed\) * `A -> B -> D -> E -> C -> F` \(branch C is processed out-of-order\) -#### 3.4. Timelines +### 3.4. Timelines Since documents are immutable, the only way to update them it by creating a new document. Subsequent versions of a document SHOULD be tracked by creating a _timeline_ using the optional **tid** and **tiv** fields. These fields SHALL NOT be used on the first document in the timeline, only on updates. The **tid** field identifies the timeline and MUST contain the reference to the first document. The **tid** field MUST be present when **tiv** is specified. @@ -116,7 +114,7 @@ For signalling updates based on out-of-date state **tiv** \(timeline version\) i Incorrect state due to incorrect updates \(e.g. duplicate **tiv**, see below\) SHOULD be fixed by issuing a new update with incremented **tiv**. -**3.4.1. Timeline validation** +#### 3.4.1. Timeline validation It's up to the processing application to validate the timeline, but the following points SHOULD be taken into consideration: @@ -128,7 +126,7 @@ It's up to the processing application to validate the timeline, but the followin If **iat**s are equal the document with the lowest hash should be applied first. -#### 3.5. Processing the DAG +### 3.5. Processing the DAG Processing the DAG can be seen as planning tasks required for construction: some tasks can happen in parallel \(laying floors and installing electricity\), some tasks must happen sequentially \(foundation must be poured before building the walls\). This is the same for documents on the DAG: documents on a branch MUST be processed sequentially but processing order of parallel branches is unspecified, and before processing a merging document all **prevs** \(branches\) must have been processed. @@ -150,12 +148,15 @@ until queue empty; take document from queue process document ``` -#### 3.6. Signature verification +### 3.6. Signature and payload verification Before interpreting a document's payload the JWS' signature MUST be validated. When **kid** is used to specify the signing key and the system knows additional usage restrictions (e.g. the key is valid from X to Y, to be checked against **sigt**), the system MUST assert the usage is compliant. +Furthermore, since the payload is detached from the document itself and referred to by hash, the payload MUST be hashed +and compared to the hash specified in the document, to assert that the retrieved payload is actually the expected payload. + ## 4. Example ### 4.1. Compact Serialization diff --git a/rfc/rfcdid-did-nuts-method.md b/rfc/rfcdid-did-nuts-method.md index 26f4427..e47c0ab 100644 --- a/rfc/rfcdid-did-nuts-method.md +++ b/rfc/rfcdid-did-nuts-method.md @@ -1,18 +1,47 @@ -# Nuts DID Method Specification +# RFCXXX Distributed Registry with Decentralized Identifiers -## About +| | | +| :--- | :--- | +| Nuts foundation | Author | +| Request for Comments: 00x | Nedap | +| | January 2021 | -## Abstract +## Distributed Registry with Decentralized Identifiers +### Abstract -## Status -Draft +This RFC describes a protocol to build a registry containing information required for (care) organizations to exchange data. +The registry typically contains organizations, software vendors acting on behalf of their client (organizations), +data exchange services offered by organizations and their technical endpoints. +It describes how these are mapped to [Decentralized Identifiers](https://www.w3.org/TR/did-core/) and how DID Documents +are encapsulated in [RFC004 Distributed Documents](rfc004-distributed-document-format.md) to provide cryptographic +integrity and consistent state across distributed networks. -#### Copyright Notice +### Status + +This document is currently a draft. + +### Copyright Notice ![](../.gitbook/assets/license.png) This document is released under the [Attribution-ShareAlike 4.0 International \(CC BY-SA 4.0\) license](https://creativecommons.org/licenses/by-sa/4.0/). -## 1. Nuts DID Method +## 1. Introduction + +When care organizations want to exchange data using Nuts they need to know where to find that data and how to authenticate it. +This knowledge is recorded in a distributed registry, writable and queryable by all network participants. +This RFC describes how to create, update and resolve the data structures required to achieve that goal. + +## 2. Terminology + +* **Bolt**: a use case built on top of the functionality Nuts provides. +* **JWS**: JSON Web Signature as specified by [RFC004](rfc004-distributed-document-format.md). +* **Organization**: a care organization exchanging data with other care organizations over a Nuts network. + By giving other DIDs control over its DID Document organizations can delegate data exchange to another party, + e.g. a care software vendor or SaaS provider. +* **Endpoint**: a URI or URL exposed by a network participant which can be used by other participants to pull data. +* **Service**: a group of endpoints implementing a service required by a Bolt. + +## 3. Nuts DID Method The Nuts DID scheme is defined as follows: ``` did = "did:nuts:" idstring @@ -25,7 +54,7 @@ base58char = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "A" / "B" / " ``` -Where the `idstring` is generated from taking the SHA-256 hash of the public key from a Ed25519: +Where the `idstring` is generated from taking the SHA-256 hash of the public key from an Ed25519 curve: `idstring = BASE-58(SHA-256(raw-public-key-bytes))` @@ -52,49 +81,47 @@ example: } ``` -## 2. Namespace Specific Identifier (NSI) +### 3.1 Namespace Specific Identifier (NSI) Identifiers are derived from public keys that are valid at the moment of creating the DID document. It MUST be the public key that corresponds to the private key that was used to sign the Nuts registry document (RFC004). The public key MUST also be present in the `verificationMethods`. When multiple keys are present, one MUST verify in this matter. -## 3. Method operations +### 3.2 Method operations DID documents are enclosed in a message envelope to ensure consistency in the network. The envelope is in the form of a JWS as described in [RFC004]. Once the network layer has confirmed the signature of the JWS, the registry MUST validate if the submitter is authorized to create, update or delete the document. If the authorization fails, the document should be ignored. -Changes to DID documents can only be accepted if the update is signed with one of the following keys: - -- a key referenced from the `authentication` section of the latest DID document version. -- a key referenced from the `authentication` section of a controller. One of the entries in the `controller` field MAY refer to a different DID Document. - The `authentication` keys of the latest version of that DID Document can be used as authorized key. -- a key referenced from the `authentication` section of the given DID document if it is a `Create` action. - The `controller` field MAY be present. If no `controller` field is present, the DID subject itself is the controller. If the `controller` field is present, only the DID subjects from the `controller` field can change the DID document. -jws specification +#### 3.2.1 Create (Register) -`cty` MUST contain the value `application/json+did-document` +A Create operation for a DID Document puts the following additional requirements on the Nuts document JOSE header: +- `cty` MUST contain the value `application/json+did-document` +- `tiv` MUST be absent or `0` +- `tid` MUST be absent -### Create (Register) +A `jwk` MUST be provided. The `kid` field of the jwk MUST be prefixed by the id of the did document. +The `jwk` field will make sure the Nuts document can be processed on the network layer. +In order for the contents to be accepted in the Nuts registry, the `jwk` MUST match the `authentication` key in the DID document with the same identifier. +The `kid` from the Nuts document `jwk` field MUST match the `id` from the verification key in the DID document. Example JOSE header ```json { "alg": "PS256", - "cty": "application/json+did-document", - "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "cty": "application/json+did-document`", "jwk": { "crv": "P-256", "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", "kty": "EC", - "kid": "_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" }, "crit": [ "sigt", @@ -109,22 +136,36 @@ Example JOSE header } ``` -Jws payload: +The DID document has the following basic requirements: + +- the `id` MUST be generated according to the method specified at the beginning of §3 +- at least 1 key MUST be present in the `verificationMethod` and `authentication` +- all key references in `authentication` MUST refer to keys listed under `verificationMethods` + +Each key listed in `verificationMethod` MUST have an `id` equal to the DID followed by a `#` followed by XXXXX???? +Each key MUST be of type `JsonWebKey2020` (TODO: follow that spec) +TODO limit curve + +The `controller` field MAY be present. This RFC follows the [did-core-spec](https://www.w3.org/TR/did-core/#did-controller). + +TODO: `assertion` field + +Example DID document: ```json { + "@context": [ "https://www.w3.org/ns/did/v1" ], "id": "", "controller": [], "verificationMethod": [{ "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", - "type": "JsonWebKey2020", "controller": "did:nuts:123", + "type": "JsonWebKey2020", "publicKeyJwk": { "crv": "P-256", "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", - "kty": "EC", - "kid": "_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + "kty": "EC" } }], "authentication": ["did:example:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], @@ -132,12 +173,7 @@ Jws payload: } ``` -Example signature: -``` -SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c -``` - -### Read (Resolve) +#### 3.2.2 Read (Resolve) A Nuts DID can only be resolved locally. The concept of the Nuts registry is the state based upon all Create, Update and Delete operations received through the Nuts Network. Therefore, any DID SHOULD already be present in the local storage. @@ -159,10 +195,16 @@ Therefore, any DID SHOULD already be present in the local storage. } ``` -### Update (Replace) -The complete document gets replaced. +#### 3.2.3 Update (Replace) +The complete document gets replaced with a newer version. + +Changes to DID documents can only be accepted if the update is signed with one of the following keys: + +- a key referenced from the `authentication` section of the latest DID document version. +- a key referenced from the `authentication` section of a controller. One of the entries in the `controller` field MAY refer to a different DID Document. + The `authentication` keys of the latest version of that DID Document can be used as authorized key. +- a key referenced from the `authentication` section of the given DID document if it is a `Create` action. -The following example shows a replace (not a patch): Example JOSE header ```json { @@ -200,7 +242,7 @@ Example payload: } ``` -### Delete (Revoke) +#### 3.2.4 Delete (Revoke) DID Documents cannot be deleted as in being "erased", only its keys can be removed as to prevent future changes (revocation). To revoke the keys to prevent future updates; @@ -211,7 +253,7 @@ To revoke the keys to prevent future updates; Deletion can not be undone. -## 4. Security Considerations +### 3.3 Security Considerations Almost all security considerations are covered by the mechanisms described in RFC004. An overview of countermeasures: @@ -223,20 +265,20 @@ Almost all security considerations are covered by the mechanisms described in RF - **man-in-the-middle** - All communications is sent over two-way TLS and all documents are signed. A DID can not be hijacked since it is derived from the public key. - **denial of service** - This is out of scope and handled by RFC004. -### 4.1 Protection against DID hijacking +#### 3.3.1 Protection against DID hijacking The Nuts network is a mesh network without central authority. This means that any party can generate a DID. This DID must be protected against forgery and hijacking since duplicates are accepted in the Nuts network. The duplicates are sorted and one will eventually be accepted (consistency rules of RFC004). This would open up a DID to hijacking. Therefore, the DID MUST be a derivative of the public key used to sign the document as described in chapter 2. -### 4.2 Protection against loss of private key +#### 3.3.2 Protection against loss of private key The loss of a single private key can be countered by registering multiple keys. Keys can be kept offline, in a vault for example. Such a key can later be used to register new keys when needed. Another option is to add a second controller that acts as an emergency backup. The keys of that controller can be kept offline. -### 4.3 Protection against theft of private key +#### 3.3.3 Protection against theft of private key A stolen key can alter the DID document in such a way that the attacker can get full control with a new key and can exclude the previous owner from making changes. Appropriate measures MUST be taken to keep authentication keys secure. @@ -245,6 +287,12 @@ When control over a DID document has been lost, the DID subject will have to hav Without Verifiable Credentials linked to the DID document, the DID document no longer has any value. The DID subject will have to go through the process of reacquiring all Verifiable Credentials for a new DID document. -## 5. Privacy considerations +### 3.4 Privacy considerations + +All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. + +## 4. Additional registry requirements + +### 4.1 Operation validations -All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. \ No newline at end of file +Other stuff \ No newline at end of file From acf516bc90e654f8bf3a5ff0febb6fab1abd16d2 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Wed, 6 Jan 2021 17:47:36 +0100 Subject: [PATCH 06/21] complete CRUD part and add section on services and deployment scenarios --- rfc/rfcdid-did-nuts-method.md | 233 ++++++++++++++++++++++++++-------- 1 file changed, 179 insertions(+), 54 deletions(-) diff --git a/rfc/rfcdid-did-nuts-method.md b/rfc/rfcdid-did-nuts-method.md index e47c0ab..a135208 100644 --- a/rfc/rfcdid-did-nuts-method.md +++ b/rfc/rfcdid-did-nuts-method.md @@ -99,16 +99,16 @@ If the `controller` field is present, only the DID subjects from the `controller #### 3.2.1 Create (Register) -A Create operation for a DID Document puts the following additional requirements on the Nuts document JOSE header: +A Create operation for a DID Document puts the following additional requirements on the JWS header: - `cty` MUST contain the value `application/json+did-document` - `tiv` MUST be absent or `0` - `tid` MUST be absent A `jwk` MUST be provided. The `kid` field of the jwk MUST be prefixed by the id of the did document. -The `jwk` field will make sure the Nuts document can be processed on the network layer. +The `jwk` field will make sure the JWS can be processed on the network layer. In order for the contents to be accepted in the Nuts registry, the `jwk` MUST match the `authentication` key in the DID document with the same identifier. -The `kid` from the Nuts document `jwk` field MUST match the `id` from the verification key in the DID document. +The `kid` from the JWS `jwk` field MUST match the `id` from the verification key in the DID document. Example JOSE header @@ -155,8 +155,11 @@ Example DID document: ```json { "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "", - "controller": [], + "id": "did:nuts:123", + "controller": [ + "did:nuts:123", + "did:nuts:7368245" + ], "verificationMethod": [{ "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", "controller": "did:nuts:123", @@ -168,48 +171,33 @@ Example DID document: "kty": "EC" } }], - "authentication": ["did:example:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], + "authentication": ["did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], "service": [] } ``` #### 3.2.2 Read (Resolve) A Nuts DID can only be resolved locally. The concept of the Nuts registry is the state based upon all Create, Update and Delete operations received through the Nuts Network. -Therefore, any DID SHOULD already be present in the local storage. - -```json -{ - "document": { - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "did:nuts:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3", - "controller": [], - "verificationMethod": [], - "authentication": [], - "service":[] - }, - "metadata": { - "kid": "did:nuts:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3#key1", - "created": "2021-01-04T12:15:06Z", - "updated": "2021-01-05T10:27:22Z" - } -} -``` +Therefore, any DID document SHOULD already be present in local storage. #### 3.2.3 Update (Replace) -The complete document gets replaced with a newer version. +The complete document gets replaced with a newer version. -Changes to DID documents can only be accepted if the update is signed with one of the following keys: +Changes to DID documents can only be accepted if the update is signed with current controller authentication key: - a key referenced from the `authentication` section of the latest DID document version. - a key referenced from the `authentication` section of a controller. One of the entries in the `controller` field MAY refer to a different DID Document. The `authentication` keys of the latest version of that DID Document can be used as authorized key. - a key referenced from the `authentication` section of the given DID document if it is a `Create` action. -Example JOSE header +The `kid` will hold the reference to the correct key. +The `tid` and `tiv` fields are filled according to RFC004. + +Example JWS ```json { "alg": "PS256", - "cty": "application/json+did-document", + "cty": "application/json+did-document`", "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", "crit": ["sigt", "ver","prevs"], "sigt": "", @@ -220,28 +208,6 @@ Example JOSE header } ``` -Example payload: -```json -{ - "id": "did:nuts:123", - "controller": [], - "verificationMethod": [{ - "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", - "type": "JsonWebKey2020", - "controller": "did:nuts:123", - "publicKeyJwk": { - "crv": "P-256", - "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", - "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", - "kty": "EC", - "kid": "_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" - } - }], - "authentication": ["did:example:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], - "service":[] -} -``` - #### 3.2.4 Delete (Revoke) DID Documents cannot be deleted as in being "erased", only its keys can be removed as to prevent future changes (revocation). @@ -253,6 +219,18 @@ To revoke the keys to prevent future updates; Deletion can not be undone. +Example DID document: + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:123", + "controller": [], + "verificationMethod": [], + "authentication": [] +} +``` + ### 3.3 Security Considerations Almost all security considerations are covered by the mechanisms described in RFC004. An overview of countermeasures: @@ -287,12 +265,159 @@ When control over a DID document has been lost, the DID subject will have to hav Without Verifiable Credentials linked to the DID document, the DID document no longer has any value. The DID subject will have to go through the process of reacquiring all Verifiable Credentials for a new DID document. +TODO Is this acceptable? A SaaS provider will have to re-add all care organizations as DID documents (including services). Then all care organizations must also re-add the VC that proves their name/address to the new DID document! + ### 3.4 Privacy considerations All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. -## 4. Additional registry requirements +## 4. Services +It is to be expected that each DID subject will add services to the DID Document. Specific services will be specified in their own RFC. Both services with a `serviceEndpoint` URI and with a set of properties MUST be supported. + +The service identifier MUST be constructed from the DID followed by a `#`, the service type, a `-` and an identifier unique to the DID document. + +Below is an example of a service registered by a care organization that uses the endpoints from a SaaS provider: + +The SaaS provider defines the actual URL: +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:123", + ... + "service": [ + { + "id": "did:nuts:123#NutsOAuth-1", + "type": "NutsOAuth", + "serviceEndpoint": "https://example.com/oauth" + }, + { + "id": "did:nuts:123#NutsFHIR-1", + "type": "NutsFHIR", + "serviceEndpoint": "https://example.com/fhir" + } + ] +} +``` + +The care organisation refers to it: +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:abc", + ... + "service": [ + { + "id": "did:nuts:abc#NutsCompoundService-1", + "type": "NutsCompoundService", + "serviceEndpoint": { + "oauthEndpoint": "did:nuts:123#NutsOAuth-1", + "fhirEndpoint": "did:nuts:123#NutsFHIR-1" + } + } + ] +} +``` + +## 5. Deployment scenarios + +The definition of the Nuts DID method enables a wide variety of usages. +To better understand the usages, this chapter illustrates some example scenarios. + +This section is non-normative. + +### 5.1 SaaS provider + +This example consists of a SaaS provider that acts as enabler, controller and node operator for all of its customers. The SaaS provider has access to all the key material and the care organizations do not. + +The SaaS provider registers itself with: + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:1", + "verificationMethod": [ + { + "id": "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:1", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }, + { + "id": "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA", + "controller": "did:nuts:1", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }], + "authentication": [ + "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA" + ], + "service": [ + { + "id": "did:nuts:123#NutsOAuth-1", + "type": "NutsOAuth", + "serviceEndpoint": "https://example.com/oauth" + }, + { + "id": "did:nuts:123#NutsFHIR-1", + "type": "NutsFHIR", + "serviceEndpoint": "https://example.com/fhir" + } + ] +} +``` + +It registers two keys: one if kept offline as backup, and the other is available in the software of the SaaS provider. + +The SaaS provider registers a care organization as: + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:2", + "verificationMethod": [ + { + "id": "did:nuts:2#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:2", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }], + "authentication": [ + "did:nuts:2#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + ], + "controller": [ + "did:nuts:1" + ], + "service": [ + { + "id": "did:nuts:abc#NutsCompoundService-1", + "type": "NutsCompoundService", + "serviceEndpoint": { + "oauthEndpoint": "did:nuts:1#NutsOAuth-1", + "fhirEndpoint": "did:nuts:1#NutsFHIR-1" + } + } + ] +} +``` + +The care organization does have an `authentication` key, this is required for the generation of the `id`. The SaaS provider will most likely not store the key since that key is not in control of the DID document. The DID document of the SaaS provider is the controller of the DID document. -### 4.1 Operation validations +### 5.2 Hospital -Other stuff \ No newline at end of file +### 5.3 Single person deployment \ No newline at end of file From a65026c2ab48f5e05a8ee5fc3a4bf7d85450aaf0 Mon Sep 17 00:00:00 2001 From: stevenvegt Date: Thu, 7 Jan 2021 13:18:26 +0100 Subject: [PATCH 07/21] another round of changes --- rfc/rfcdid-did-nuts-method.md | 114 +++++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 35 deletions(-) diff --git a/rfc/rfcdid-did-nuts-method.md b/rfc/rfcdid-did-nuts-method.md index a135208..62c1343 100644 --- a/rfc/rfcdid-did-nuts-method.md +++ b/rfc/rfcdid-did-nuts-method.md @@ -42,7 +42,8 @@ This RFC describes how to create, update and resolve the data structures require * **Service**: a group of endpoints implementing a service required by a Bolt. ## 3. Nuts DID Method -The Nuts DID scheme is defined as follows: + +The Nuts DID URI scheme is defined as follows: ``` did = "did:nuts:" idstring idstring = 21*22(base58char) @@ -54,27 +55,26 @@ base58char = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "A" / "B" / " ``` -Where the `idstring` is generated from taking the SHA-256 hash of the public key from an Ed25519 curve: +Where the `idstring` is derived from the public key: `idstring = BASE-58(SHA-256(raw-public-key-bytes))` -Example: -Consider the following JWK encoded Ed25519. +For example, consider the following Ed25519 key (as JWK): -```javascript -var key = { +```json +{ "kty" : "OKP", "crv" : "Ed25519", "x" : "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", - "d" : "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", "use" : "sig", "kid" : "FdFYFzERwC2uCBB46pZQi4GG85LujR8obt-KWRBICVQ" } ``` -Where the `x` parameter is the base64 encoded public key. -`idString = Base58Encode(Sha256(Base64urlDecode(key.x)))` -example: +For this key type the `x` parameter is used to derive `idstring`: +`idstring = BASE-59(SHA-256(BASE64URL-DECODE(key.x)))` + +Outputs: ```json { "id": "did:nuts:e3cacd5c2d931295a64f6c3bb3f6ea58c3a9b253b990e32c5abce43c2f94c564" @@ -84,13 +84,13 @@ example: ### 3.1 Namespace Specific Identifier (NSI) Identifiers are derived from public keys that are valid at the moment of creating the DID document. -It MUST be the public key that corresponds to the private key that was used to sign the Nuts registry document (RFC004). +It MUST be the public key that corresponds to the private key that was used to sign the Nuts registry document ([RFC004](rfc004-distributed-document-format.md)). The public key MUST also be present in the `verificationMethods`. When multiple keys are present, one MUST verify in this matter. ### 3.2 Method operations DID documents are enclosed in a message envelope to ensure consistency in the network. -The envelope is in the form of a JWS as described in [RFC004]. +The envelope is in the form of a JWS as described in [RFC004](rfc004-distributed-document-format.md). Once the network layer has confirmed the signature of the JWS, the registry MUST validate if the submitter is authorized to create, update or delete the document. If the authorization fails, the document should be ignored. @@ -99,23 +99,23 @@ If the `controller` field is present, only the DID subjects from the `controller #### 3.2.1 Create (Register) -A Create operation for a DID Document puts the following additional requirements on the JWS header: +A Create operation for a DID Document puts the following additional requirements on the JWS header parameters: +- `jwk` MUST be present - `cty` MUST contain the value `application/json+did-document` - `tiv` MUST be absent or `0` - `tid` MUST be absent -A `jwk` MUST be provided. The `kid` field of the jwk MUST be prefixed by the id of the did document. -The `jwk` field will make sure the JWS can be processed on the network layer. -In order for the contents to be accepted in the Nuts registry, the `jwk` MUST match the `authentication` key in the DID document with the same identifier. -The `kid` from the JWS `jwk` field MUST match the `id` from the verification key in the DID document. +The `kid` field of the `jwk` header parameter MUST be prefixed by the `id` of the DID document. +In order for the contents to be accepted in the Nuts registry, the JWK MUST match the `authentication` key in the DID document with the same identifier. +The `kid` field from the JWK MUST match the `id` from the verification key in the DID document. -Example JOSE header +Example JWS header ```json { "alg": "PS256", - "cty": "application/json+did-document`", + "cty": "application/json+did-document", "jwk": { "crv": "P-256", "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", @@ -180,6 +180,25 @@ Example DID document: A Nuts DID can only be resolved locally. The concept of the Nuts registry is the state based upon all Create, Update and Delete operations received through the Nuts Network. Therefore, any DID document SHOULD already be present in local storage. +##### 3.2.2.1 Resolution Input Metadata +All historic versions of a DID Document SHOULD be stored and queryable. This allows clients to resolve the document +for a specific moment in time (e.g. a previous version) instead of the last one. For this the resolution input metadata +MAY contain the `timestamp` field indicating this moment in time. This field MUST be formatted according to [RFC3339](https://tools.iets.org/html/rfc3339). + +Example: +```json +{ + "timestamp": "2020-01-06T15:00:00Z" +} +``` + +If `timestamp` is not present the current date/time MUST be assumed. + +##### 3.2.2.2 Document Metadata +The resolved DID Document Metadata contains the `created` and `updated` fields, in accordance with the [did-core-spec](https://www.w3.org/TR/did-core/#did-document-metadata-properties). They are +derived from the underlying Nuts Documents. `created` MUST contain the `sigt` timestamp from the first version of the +document. `updated` MUST contain the `sigt` timestamp of the last version of the DID Document. + #### 3.2.3 Update (Replace) The complete document gets replaced with a newer version. @@ -190,17 +209,19 @@ Changes to DID documents can only be accepted if the update is signed with curre The `authentication` keys of the latest version of that DID Document can be used as authorized key. - a key referenced from the `authentication` section of the given DID document if it is a `Create` action. -The `kid` will hold the reference to the correct key. -The `tid` and `tiv` fields are filled according to RFC004. +The following requirements on the JWS header parameter apply: + +- `kid` MUST hold the reference to the correct key. +- `tid` and `tiv` MUST be filled according to [RFC004](rfc004-distributed-document-format.md). -Example JWS +Example JWS header: ```json { "alg": "PS256", - "cty": "application/json+did-document`", + "cty": "application/json+did-document", "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", "crit": ["sigt", "ver","prevs"], - "sigt": "", + "sigt": "2020-01-06T15:00:00Z", "ver": "1", "prevs": ["148b3f9b46787220b1eeb0fc483776beef0c2b3e"], "tid": "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", @@ -233,21 +254,21 @@ Example DID document: ### 3.3 Security Considerations -Almost all security considerations are covered by the mechanisms described in RFC004. An overview of countermeasures: +Almost all security considerations are covered by the mechanisms described in [RFC004](rfc004-distributed-document-format.md). An overview of countermeasures: - **eavesdropping** - All communications is sent over two-way TLS. All data is public anyway. -- **replay** - DID documents are identified and published by their hash (SHA256). Replaying will result in replaying the exact same content. -- **message insertion** - RFC004 defines hashing and signing of published documents. +- **replay** - DID documents are identified and published by their hash (SHA-256). Replaying will result in replaying the exact same content. +- **message insertion** - [RFC004](rfc004-distributed-document-format.md) defines hashing and signing of published documents. - **deletion** - All DID documents are published and copied on a mesh network. Deletion of a single document will only occur locally and will not damage other nodes. - **modification** - DID documents can only be modified if they are published with a signature from one of the `authentication` keys. - **man-in-the-middle** - All communications is sent over two-way TLS and all documents are signed. A DID can not be hijacked since it is derived from the public key. -- **denial of service** - This is out of scope and handled by RFC004. +- **denial of service** - This is out of scope and handled by [RFC004](rfc004-distributed-document-format.md). #### 3.3.1 Protection against DID hijacking The Nuts network is a mesh network without central authority. This means that any party can generate a DID. This DID must be protected against forgery and hijacking since duplicates are accepted in the Nuts network. -The duplicates are sorted and one will eventually be accepted (consistency rules of RFC004). This would open up a DID to hijacking. +The duplicates are sorted and one will eventually be accepted (consistency rules of [RFC004](rfc004-distributed-document-format.md)). This would open up a DID to hijacking. Therefore, the DID MUST be a derivative of the public key used to sign the document as described in chapter 2. #### 3.3.2 Protection against loss of private key @@ -272,7 +293,12 @@ TODO Is this acceptable? A SaaS provider will have to re-add all care organizati All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. ## 4. Services -It is to be expected that each DID subject will add services to the DID Document. Specific services will be specified in their own RFC. Both services with a `serviceEndpoint` URI and with a set of properties MUST be supported. +It is to be expected that each DID subject will add services to the DID Document. Specific services will be specified in their own RFC. +A service can define an absolute endpoint URI or be a compound service, referring to a set of services. This is often the case +when a SaaS provider defines endpoints to be used for all clients. + +For an absolute endpoint URI the `serviceEndpoint` MUST be a string containing the URI. For a compound service the +`serviceEndpoint` MUST contain a map containing references to absolute endpoint URI services. The service identifier MUST be constructed from the DID followed by a `#`, the service type, a `-` and an identifier unique to the DID document. @@ -283,7 +309,6 @@ The SaaS provider defines the actual URL: { "@context": [ "https://www.w3.org/ns/did/v1" ], "id": "did:nuts:123", - ... "service": [ { "id": "did:nuts:123#NutsOAuth-1", @@ -304,7 +329,6 @@ The care organisation refers to it: { "@context": [ "https://www.w3.org/ns/did/v1" ], "id": "did:nuts:abc", - ... "service": [ { "id": "did:nuts:abc#NutsCompoundService-1", @@ -327,7 +351,7 @@ This section is non-normative. ### 5.1 SaaS provider -This example consists of a SaaS provider that acts as enabler, controller and node operator for all of its customers. The SaaS provider has access to all the key material and the care organizations do not. +This example consists of a SaaS provider that acts as enabler, controller and node operator for all of its customers. The SaaS provider has access to all the key material, while the care organizations hasn't. The SaaS provider registers itself with: @@ -416,8 +440,28 @@ The SaaS provider registers a care organization as: } ``` -The care organization does have an `authentication` key, this is required for the generation of the `id`. The SaaS provider will most likely not store the key since that key is not in control of the DID document. The DID document of the SaaS provider is the controller of the DID document. +The care organization does have an `authentication` key, this is required for the generation of the `id`. The SaaS provider will most likely not store the key since that key is not in control of the DID document. +Since this key isn't after initial creation of the document the SaaS provider SHOULD remove it from the authentication document afterwards to improve security and clarity. +The DID document of the SaaS provider is the controller of the DID document. ### 5.2 Hospital -### 5.3 Single person deployment \ No newline at end of file +### 5.3 Single person deployment + + +## Current issues + +### Key management and mitigating impact of key loss +Considering the case a care provider has outsourced its key management to a service provider. +When discussing deployment scenarios, we should consider the different roles at the service provider like: +* Sales and support department who can create and delete DID documents +* System administrators who alter serviceEndpoints + +It might not be desirable for these roles have access to the same key material. We can suggest configurations with different DID documents with different keys for services and for controller. + +### Management of VCs by a trusted service provider +Considering the case a care provider has outsourced it key management to a service provider. +When obtaining a VC from a trusted party, how does the care provider prove that it is the party represented by the DID without being able to provide private key material? + +### Resolvability of the DID document +The fundamental idea of a DID document is that it should be resolvable by other parties. Section [7.2.2 of the did-core spec](https://w3c.github.io/did-core/#read-verify) requires a specification how a DID resolver could resolve and verify a DID document from the registry. Since the Nuts registry will be a local registry this is not yet a consideration but when federation with other registries will become relevant, a proper specification should be written. \ No newline at end of file From d6d762ae6e6b668ace3cbfd1a10210a72880e4f3 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Thu, 7 Jan 2021 15:40:30 +0100 Subject: [PATCH 08/21] revamped RFC008 - certificate structure --- rfc/rfc008-certificate-structure.md | 117 ++++++++-------------------- 1 file changed, 33 insertions(+), 84 deletions(-) diff --git a/rfc/rfc008-certificate-structure.md b/rfc/rfc008-certificate-structure.md index 5b227da..d3c42cf 100644 --- a/rfc/rfc008-certificate-structure.md +++ b/rfc/rfc008-certificate-structure.md @@ -4,15 +4,15 @@ | :--- | :--- | | Nuts foundation | W.M. Slakhorst | | Request for Comments: 003 | Nedap | -| | R.G. Krul | -| | Nedap | | | October 2020 | ## Certificate Structure ### Abstract -This RFC specifies which certificates are used in which situation. The basic concept is that a vendor creates a self-signed CA certificate and that this certificate can be trusted by various methods. The vendor CA is then used to sign various other certificates, each with a different purpose \(signing, TLS, etc\). The separation between vendor CA and other certificates allows for various deployment scenarios. All certificates, except for the vendor CA, are short-lived certificates with a maximum life-span of 4 days. This removes the requirement for supporting CRLs and OCSP responders. Beside the before mentioned certificates, server certificates issued by the well-known public authorities still play a role. +This RFC specifies which certificates are used in which situation. The basic concept is that certificates are only used to create a secured connection. +Certificates and keys related to the certificates are not used in any signing or validation operation. +Instead, the DID and Verifiable Credentials standard are used. ### Status of document @@ -33,98 +33,47 @@ When it comes to certificates, we’d like to be at the edge of usability and se ## 2. Terminology * **CA**: Certificate authority as defined by [RFC2459](https://tools.ietf.org/html/rfc2459). -* **event type**: the type of entry in the document log. +* **CPS**: Certification Practise Statement. +* **CRL**: Certificate Revocation List. * **node**: a running instance of a Nuts implementation \(a.k.a. Nuts node\). * **node operator**: an organization running a node. Typically a vendor that creates healthcare software for care organizations. -* **shared network state**: the accumulation of events or document log entries that are in the right order and where every node agrees upon. -* **truststore**: The file that contains the trusted CA's. +* **PKIo**: Public Key Infrastructure overheid. The by the Dutch government controlled PKI structure. +* **TSP**: Trusted Service Provider. Party that can issue PKIo certificates. Other terminology is taken from the [Nuts Start Architecture](rfc001-nuts-start-architecture.md#nuts-start-architecture). -## 3. Overview +## 3. PKIoverheid -Nodes establish trust by using a PKI infrastructure. This infrastructure doesn't rely on central certificate authorities \(CA\) but rather on 3rd party proofs. Each vendor is a CA with a root certificate. Nodes trust a CA by either manually adding it to a truststore or relying on another cryptographic proof. The first mechanism relies on out-of-band distribution and face-to-face identity checking. For the second mechanism, all nodes should agree on which proofs to trust. This is not part of the specification, it should be part of some network agreement. [RFC006 Distributed Registry](https://github.com/nuts-foundation/nuts-specification/tree/4127385cab773917fd5bd642dd7f2fa94f48655e/rfc/rfc006-distributed-registry.md) explains which type of proofs must be supported. +The PKIoverheid CA tree is the choice of CA to trust for production use. It's widely trusted and supported. +There are multiple vendors that can issue a certificate. +A PKIo certificate MUST be used to secure inter-node connections as well as the peer-to-peer connections used to exchange data. +Production nodes MUST not accept any other certificate than a PKIoverheid certificate. +The certificate MUST be used as both server as client certificate in a mutual TLS connection. -![Certificate structure](../.gitbook/assets/certificates_v1.png) +### 3.1 Certificate Authority trust chain +A node will need to configure the correct CA-tree so other nodes can connect. +The certificate to configure are the **Staat der Nederlanden Private Root CA G1** root certificate and the **Staat der Nederlanden Private Services CA – G1** CA. +All certificates can be downloaded from the [PKIoverheid](https://cert.pkioverheid.nl/cert-pkioverheid-nl.htm) website. -The figure above shows the vendor CA tree. The lines indicate that a lower certificate is signed by a higher one in the graph. As can be seen, the vendor CA is the root of the tree. Each vendor MUST generate a self-signed certificate and have it published by another node. An organization proof SHOULD be published in the same event linking the certificate to the real world organization. See \([RFC006 Distributed Registry](https://github.com/nuts-foundation/nuts-specification/tree/4127385cab773917fd5bd642dd7f2fa94f48655e/rfc/rfc006-distributed-registry.md)\) for a detailed explanation on how trust can be established between nodes. +TSPs are responsible for signing certificates. The TSPs have their own CA. +To trust all PKIo certificates, any software that validates a certificate and its chain, MUST trust any intermediate CA below the **Staat der Nederlanden Private Services CA – G1** CA. -Typically, a PKI infrastructure also defines CRLs and OCSP endpoints. More recent insights show that short-lived certificates offer the same level of security since CRLs and OCSP return values tend to be cached for a longer period of time. A case could even be made that short-lived certificates are more secure since they allow for faster key rotation as well. [Short lived certificates @ Netflix](https://medium.facilelogin.com/short-lived-certificates-netflix-fd5f3ae5bc9) +The PKIoverheid private services CA is not by default accepted by browsers and operating systems. -The node certificates from the diagram are specific per machine/deployment. This allows for multiple topologies. The private key SHOULD never leave the deployment instance. Together with short-lived certificates, the private key can even be stored in memory rather than somewhere else, increasing security. +### 3.2 Certification Practise Statement +The different Certification Practise Statements for the Dutch government can be found on https://cps.pkioverheid.nl/ +The relevant CPS is the **CPS PA PKIoverheid Private Root v1.5**. -The node signing certificates are used for signing documents \([RFC004 Distributed Document Format](https://github.com/nuts-foundation/nuts-specification/tree/4127385cab773917fd5bd642dd7f2fa94f48655e/rfc/rfc004-distributed-document-format.md)\) and for signing JWTs\([RFC003 OAuth2 authorization](rfc003-oauth2-authorization.md)\). The node TLS certificates are used for connections between nodes. They also are short-lived and are deployment instance specific. +### 3.3 CRL +The Certificate Revocation Lists for PKIoverheid certificates are maintained by the different TSPs. +The time between signing of a CRL differs per TSP. A node MUST at least update all CRLs every hour. -Summarized, there are 3 classes of certificates: 1. Vendor CA certificates are used to issue certificates. 2. TLS certificates are used for authentication when connecting to node endpoints. 3. Signing certificates are used for signing documents on the document log, so their authenticity can be established. They are also used to sign JWTs in an OAuth flow. +## 4. Test and development +PKIoverheid certificates are not cheap and the associated private key should not be shared amongst developers or test servers. +Therefore, any node MUST be able to support any set of certificates. This will allow anyone to setup their own test/development network. -In the next chapter, these certificates will be explained in detail. - -## 4. Certificate types - -These paragraphs describe the main usage of certificate usage. All edge cases are described in the Key compromisation matrix paragraph in the Private key management chapter. Whenever the term certificate is used in the context of signing, we mean the private key associated with the public key of the certificate. - -### 4.1. Vendor CA - -This CA signs TLS certificates and signing certificates. This is a very important certificate and it MUST be stored securely in a secure key management module. This module MUST only be accessible from within the vendor’s infrastructure. This will allow nodes that support Nuts functionality to request and renew certificates. This certificate identifies the vendor, it MUST have its identifier \(vendor ID\) as SAN. It may only be used to issue certificates for its own organization. - -| Field | Value | -| :--- | :--- | -| Validity | 3 years | -| Is CA? | true | -| Key Usage | certSign | -| Extended Key Usage | serverAuthentication, clientAuthentication | -| SubjectAlternativeName | otherName=1.3.6.1.4.1.54851.4: | -| Subject | Free to choose, but must comply with the following rules: Country \(C\) must be present and contain the vendor’s country where it’s registered\*. Organization \(O\) must be present and contain the organization’s name as registered. Common Name \(CN\) MUST be present and have the following format: CA. ‘Legal Name’ contains the name of the vendor as registered. ‘Optional Text’ is optional and can contain anything the vendor wishes to specify. ‘CA’ postfix is mandatory, indicating it’s a Certificate Authority | - -\* as registered means: as the legal entity is registered \(e.g. Chamber of Commerce registration\) - -### 4.2. Signing certificate - -Any change to the shared state of the network MUST be signed by the node that announces it \(event signing\). This means that every node needs their own signing key, linked to the identity of the vendor CA. The vendor CA can’t be used, since that CA should be kept secure and separate from any service open to the outside. The signing certificate acts as a proof of ownership for the vendor. This certificate MAY also be used to sign the JWTs for the OAuth flow. The certificate MUST NOT be valid for more than 4 days, meaning the vendor SHOULD support automatic renewal/rekeying within the infrastructure. - -| Field | Value | -| :--- | :--- | -| Validity | 4 days | -| Is CA? | false | -| Key Usage | digitalSignature, non-repudiation | -| SubjectAlternativeName | otherName=1.3.6.1.4.1.54851.4: | - -### 4.3. - -The TLS certificate is used for setting up connections between the nodes. When a vendor adds another vendor to the network, its CA \(Vendor CA\) will be added to the shared network state. The TLS certificate that the vendor will use MUST be trusted by the other vendors implicitly. To support configuration of a reverse-proxy \(and for internal use\), the node COULD provide an endpoint with the current approved CA’s. The validity of the TLS certificate MUST NOT be longer than 4 days. - -| Field | Value | -| :--- | :--- | -| Validity | 4 days | -| Is CA? | false | -| Key Usage | digitalSignature | -| Extended Key Usage | serverAuthentication, clientAuthentication | -| SubjectAlternativeName | otherName=1.3.6.1.4.1.54851.4: | - -## 5. Private key algorithms - -The private key algorithm MUST be one of _secp384r1_, _secp521r1_. 384 bits is one step above 256 which should already give 10 years of protection. When key rotation is set up from the beginning, we can change the desired key algorithm easily. A specific command SHOULD be available on a node to help the administrator achieve this. Some diagnostics on when a key has to be rotated COULD be provided as well. - -## 6. Private key management - -The following paragraphs are recommendations since it involves the internal workings of a node. - -### 6.1. Storage - -Keeping the private key safe is of enormous importance. The best way is to not store it next to the application or service at all. A nuts node SHOULD support two ways of using a private key for specific actions \(mostly CA related\). The first is to pass the private key location as argument to the specific CLI commands. This is not recommended for production, since it involves a key on disk, even if it is encrypted with a passphrase. It’s useful for a local setup or development. The preferred way is to store the key \(and certificate\) in a [Hashicorp Vault instance](https://www.vaultproject.io/). Vault supports all required CA commands\(Sign, self-sign and revoke\). For all relevant commands an access token has to be used as an argument in the CLI command. This access token gives access to the required Vault commands. The benefit is that the administrator does not need access to all stored keys and that the access token can be short-lived. - -### 6.2. Key compromisation matrix - -The matrix below contains some basics on what to do in various situations involving the private key of the various certificates. - -| | Vendor CA | TLS | Signing | -| :--- | :--- | :--- | :--- | -| where is the key used? | For signing signing keys and TLS keys | in TLS connections as client certificate. It's basically the gateway to the Nuts network. | In the registry for signing events. And for signing JWTs | -| how is it approved? | Self signed, but has to be added by another node to the network. Has to be accompanied with an organization proof | It is automatically accepted due to its CA being accepted | It is automatically accepted due to its CA being accepted | -| how often is it used? | Every 3 days per issued certificate. | Multiple connections to multiple registries and for each connection to retrieve data/get an access token. | Everytime an entry is added to the registry and when a JWT is signed. | -| algo's allowed? | secp384r1 | TLS 1.2+, ECDHE and AES-GCM | secp384r1/Ed25519 | -| what if key is stolen? | If stolen, the organization proof means must be used to revoke the old key and approve a new one. | It's only valid for a few days. | It's only valid for a few days. | -| what if key is lost? | The organization proof means must be used to approve a new one. | Generate a new key and certificate | Generate a new key and certificate | -| what if key is old? \(key rotation\) | Publish a new self-signed certificate | same as lost | same as lost | -| how is the cert revoked? | By registering a new key using the organization means | expires | expires | +## 5. Private key management +A PKIo certificate is costly and it's associated with a single private key. +Appropriate measures SHOULD be taken to reduce the number of stored instances of the private key. Reverse/forwarding proxies and centralized keystores with strong encryption can help. +In case of theft or loss of a private key and/or certificate, please consult the TSP documentation. \ No newline at end of file From 37b6effc94c3b52c4ab8b463ba089576815cb9e3 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 7 Jan 2021 15:44:38 +0100 Subject: [PATCH 09/21] Replaced RFC006 --- .../assets/rfc006-registry-domainmodel.svg | 63 -- .gitbook/assets/spec-relations.svg | 124 ++-- .../source/rfc006-registry-domainmodel.dot | 17 - .gitbook/source/spec-relations.dot | 2 +- SUMMARY.md | 2 +- rfc/rfc006-distributed-registry.md | 652 ++++++++++-------- rfc/rfcdid-did-nuts-method.md | 467 ------------- 7 files changed, 438 insertions(+), 889 deletions(-) delete mode 100644 .gitbook/assets/rfc006-registry-domainmodel.svg delete mode 100644 .gitbook/source/rfc006-registry-domainmodel.dot delete mode 100644 rfc/rfcdid-did-nuts-method.md diff --git a/.gitbook/assets/rfc006-registry-domainmodel.svg b/.gitbook/assets/rfc006-registry-domainmodel.svg deleted file mode 100644 index e5a3fca..0000000 --- a/.gitbook/assets/rfc006-registry-domainmodel.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - -D - - - -vendor - -Vendor - - - -endpoint - -Endpoint - - - -vendor->endpoint - -exposes - - - -organization - -Organization - - - -vendor->organization - -registers clients - - - -service - -Service - - - -organization->service - - -offers - - - -service->endpoint - -offers functionality -through - - - diff --git a/.gitbook/assets/spec-relations.svg b/.gitbook/assets/spec-relations.svg index 88a5ae6..b74e9fe 100644 --- a/.gitbook/assets/spec-relations.svg +++ b/.gitbook/assets/spec-relations.svg @@ -4,26 +4,26 @@ - + D - + cluster_internal - + cluster_external - + RFC001 - -RFC001 -Nuts Start Architecture + +RFC001 +Nuts Start Architecture @@ -31,165 +31,165 @@ RFC002 - -RFC002 -Authentication token + +RFC002 +Authentication token RFC002->RFC001 - - + + RFC003 - -RFC003 -OAuth2 Authorization + +RFC003 +OAuth2 Authorization RFC003->RFC001 - - + + RFC003->RFC002 - - + + RFC7662_EXT - -RFC7662 -OAuth 2.0 Token Introspection + +RFC7662 +OAuth 2.0 Token Introspection RFC003->RFC7662_EXT - - + + RFC7523_EXT - -RFC7523 -JSON Web Token (JWT) Profile -for OAuth 2.0 Client Authentication and Authorization Grants + +RFC7523 +JSON Web Token (JWT) Profile +for OAuth 2.0 Client Authentication and Authorization Grants RFC003->RFC7523_EXT - - + + RFC7515_EXT - -RFC7515 -JSON Web Signature (JWS) + +RFC7515 +JSON Web Signature (JWS) RFC003->RFC7515_EXT - - + + RFC004 - -RFC004 -Distributed Document Format + +RFC004 +Distributed Document Format RFC004->RFC001 - - + + RFC008 - -RFC008 -Certificate Structure + +RFC008 +Certificate Structure RFC004->RFC008 - - + + RFC004->RFC7515_EXT - - + + RFC005 - -RFC005 -Distributed Document Network using gRPC -(Planned) + +RFC005 +Distributed Document Network using gRPC +(Planned) RFC005->RFC004 - - + + RFC006 - - -RFC006 -Distributed Registry + + +RFC006 +Distributed Registry using DIDs RFC006->RFC004 - - + + RFC006->RFC008 - - + + diff --git a/.gitbook/source/rfc006-registry-domainmodel.dot b/.gitbook/source/rfc006-registry-domainmodel.dot deleted file mode 100644 index b242972..0000000 --- a/.gitbook/source/rfc006-registry-domainmodel.dot +++ /dev/null @@ -1,17 +0,0 @@ -digraph D { - splines = ortho; - rankdir = LR; - node [shape = box,fontname = "Helvetica",fontsize = 9]; - edge [fontname = "Helvetica" fontsize = 7]; - - vendor [label = "Vendor"]; - endpoint [label = "Endpoint"]; - organization [label = "Organization"]; - service [label = "Service"]; - - vendor -> endpoint [headlabel = "exposes", dir = none] - vendor -> organization [constraint = false,headlabel = "registers clients", dir = none] - organization -> service [headlabel = "offers",arrowtail = diamond,dir = back] - service -> endpoint [headlabel = "offers functionality\nthrough", dir = none, constraint = false] - -} \ No newline at end of file diff --git a/.gitbook/source/spec-relations.dot b/.gitbook/source/spec-relations.dot index 749bfac..29918ed 100644 --- a/.gitbook/source/spec-relations.dot +++ b/.gitbook/source/spec-relations.dot @@ -12,7 +12,7 @@ digraph D { RFC003 [label = "RFC003\nOAuth2 Authorization",href = "rfc003-oauth2-authorization"]; RFC004 [label = "RFC004\nDistributed Document Format",href = "rfc004-distributed-document-format"]; RFC005 [label = "RFC005\nDistributed Document Network using gRPC\n(Planned)",href = "rfc005-distributed-document-network-grpc"]; - RFC006 [label = "RFC006\nDistributed Registry",href = "rfc006-distributed-registry"]; + RFC006 [label = "RFC006\nDistributed Registry using DIDs",href = "rfc006-distributed-registry"]; RFC008 [label = "RFC008\nCertificate Structure",href = "rfc008-certificate-structure"]; RFC009 [label = "RFC009\nVerifiable Presentations",href = "rfc009-verifiable-presentations"]; } diff --git a/SUMMARY.md b/SUMMARY.md index 2d73ad0..e6e0e72 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -8,7 +8,7 @@ * [RFC002 Authentication token](rfc/rfc002-authentication-token.md) * [RFC003 OAuth2 Authorization](rfc/rfc003-oauth2-authorization.md) * [RFC004 Distributed Document Format](rfc/rfc004-distributed-document-format.md) -* [RFC006 Distributed Registry](rfc/rfc006-distributed-registry.md) +* [RFC006 Distributed Registry with Decentralized Identifiers (DID)](rfc/rfc006-distributed-registry.md) * [RFC008 Certificate Structure](rfc/rfc008-certificate-structure.md) * [RFC009 Verifiable Presentations](rfc/rfc009-verifiable-presentations.md) diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index da62a13..871bb01 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -1,378 +1,474 @@ -# RFC006 Distributed Registry +# RFC006 Distributed Registry with Decentralized Identifiers (DID) | | | | :--- | :--- | -| Nuts foundation | R.G. Krul | +| Nuts foundation | W.M. Slakhorst | | Request for Comments: 006 | Nedap | -| | September 2020 | - -## Distributed Registry +| | S. van der Vegt | +| | Nedap | +| | R.G. Krul | +| | Nedap | +| | January 2021 | +## Distributed Registry with Decentralized Identifiers (DID) ### Abstract -This RFC describes a protocol to build a registry containing information required for care organizations to exchange data -through their software vendors. The registry typically contains vendors, organizations, services and endpoints. -It uses [RFC004](rfc004-distributed-document-format.md)'s documents as underlying data format. +This RFC describes a protocol to build a registry containing information required for (care) organizations to exchange data. +The registry typically contains organizations, software vendors acting on behalf of their client (organizations), +data exchange services offered by organizations and their technical endpoints. +It describes how these are mapped to [Decentralized Identifiers (DID)](https://www.w3.org/TR/did-core/) and how DID Documents +are encapsulated in [RFC004 Distributed Documents](rfc004-distributed-document-format.md) to provide cryptographic +integrity and consistent state across distributed networks. -### Status of document +### Status This document is currently a draft. ### Copyright Notice - ![](../.gitbook/assets/license.png) This document is released under the [Attribution-ShareAlike 4.0 International \(CC BY-SA 4.0\) license](https://creativecommons.org/licenses/by-sa/4.0/). -## 1. Introduction +## 1. Introduction When care organizations want to exchange data using Nuts they need to know where to find that data and how to authenticate it. -This RFC describes the document types containing the information required to form this registry. -It uses [RFC004](rfc004-distributed-document-format.md) as underlying data format. The origin and requirements of -certificates are defined by RFC008. +This knowledge is recorded in a distributed registry, writable and queryable by all network participants. +This RFC describes how to create, update and resolve the data structures required to achieve that goal. ## 2. Terminology * **Bolt**: a use case built on top of the functionality Nuts provides. -* **Document**: a distributed document as specified by [RFC004](rfc004-distributed-document-format.md). +* **JWS**: JSON Web Signature as specified by [RFC004](rfc004-distributed-document-format.md). * **Organization**: a care organization exchanging data with other care organizations over a Nuts network. -* **Vendor**: an object developing software for care organizations participating in a Nuts network. - Organizations access the Nuts network through their vendor's software. -* **Endpoint**: a URI or URL exposed by a vendor which can be used by other vendors to pull data. + By giving other DIDs control over its DID Document organizations can delegate data exchange to another party, + e.g. a care software vendor or SaaS provider. +* **Endpoint**: a URI or URL exposed by a network participant which can be used by other participants to pull data. * **Service**: a group of endpoints implementing a service required by a Bolt. -* **Object**: an instance of a vendor, organization or endpoint. - -Other terminology comes from the [RFC001 Nuts Start Architecture](rfc001-nuts-start-architecture.md#nuts-start-architecture). -## 3. Domain Model -The following UML entity diagram displays how vendors, organizations, endpoints and services relate: +## 3. Nuts DID Method -![RFC006 Domain Model](../.gitbook/assets/rfc006-registry-domain-model.svg) - -## 4. Format -Entities MUST be represented as JSON document as the JWS payload defined by [RFC004](rfc004-distributed-document-format.md). -The **cty** header parameter from [RFC004](rfc004-distributed-document-format.md)) MUST contain the type defined for -that particular object type. The type parameter `o` MUST be used to indicate creation or an update, e.g: +The Nuts DID URI scheme is defined as follows: +``` +did = "did:nuts:" idstring +idstring = 21*22(base58char) +base58char = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "A" / "B" / "C" + / "D" / "E" / "F" / "G" / "H" / "J" / "K" / "L" / "M" / "N" / "P" / "Q" + / "R" / "S" / "T" / "U" / "V" / "W" / "X" / "Y" / "Z" / "a" / "b" / "c" + / "d" / "e" / "f" / "g" / "h" / "i" / "j" / "k" / "m" / "n" / "o" / "p" + / "q" / "r" / "s" / "t" / "u" / "v" / "w" / "x" / "y" / "z" + +``` -`registry/vendor;o=update` +Where the `idstring` is derived from the public key: -Other values than `update` or `create` for the `o` parameter SHALL NOT be used. +`idstring = BASE-58(SHA-256(raw-public-key-bytes))` -## 4.1. Creating and updating -When creating entities its required fields MUST be specified as JSON document. The `o` parameter MUST be specified as `create`. +For example, consider the following Ed25519 key (as JWK): -To update an object's fields [JSON Patch (RFC6902)](https://tools.ietf.org/html/rfc6902) is used. The object to update -MUST be specified by specifying the **tid** (*timeline ID*, see [RFC004](rfc004-distributed-document-format.md)) -The `o` parameter MUST be specified as `update`. An update document MUST contain the following fields: -* **patch** MUST contain an array with patch operations according to [RFC6902](https://tools.ietf.org/html/rfc6902). +```json +{ + "kty" : "OKP", + "crv" : "Ed25519", + "x" : "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", + "use" : "sig", + "kid" : "FdFYFzERwC2uCBB46pZQi4GG85LujR8obt-KWRBICVQ" +} +``` -If one of the operations fails the document MUST be rejected. +For this key type the `x` parameter is used to derive `idstring`: +`idstring = BASE-59(SHA-256(BASE64URL-DECODE(key.x)))` -Example for document type `registry/organization;o=update`: +Outputs: ```json { - "patch": [ - { "op": "replace", "path": "/name", "value": "NoPlaceLikeHome Thuiszorg" } - ] + "id": "did:nuts:e3cacd5c2d931295a64f6c3bb3f6ea58c3a9b253b990e32c5abce43c2f94c564" } ``` -When using a destructive operation (especially when using `remove` or `replace` on arrays) vendors COULD use the -`test` operation to make sure the intended values are removed. +Nuts DID Documents are wrapped in a JWS (JSON Web Signature) to ensure cryptographic authenticity and integrity through +([RFC004](rfc004-distributed-document-format.md)). Please refer to that RFC for how specifically create the JWS. -## 4.2. Signing -All documents (registration or update) MUST be signed by the vendor who owns the object (be it a vendor, organization or endpoint). The only -exception is when registering a new vendor; in that case it MUST be another, already registered vendor. If a new CA certificate -is registered for a vendor, signing certificate issued by that CA certificate can also be used for updating previously -published documents from that point on the DAG (see [RFC004](rfc004-distributed-document-format.md)). +### 3.1 Namespace Specific Identifier (NSI) -In any case the signing certificate MUST conform to [RFC008](rfc008-certificate-structure.md). +Identifiers are derived from public keys that are valid at the moment of creating the DID document. +It MUST be the public key that corresponds to the private key that was used to sign the JWS. +The public key MUST also be present in the `verificationMethods`. When multiple keys are present, one MUST verify in this matter. -## 5. Object types -This section describes each of the supported object types. +### 3.2 Method operations -### 5.1. Vendor -This document registers a vendor on the registry. It's identified by the type `registry/vendor`. -Since new vendors can't connect to other nodes in the network since their CA certificate isn't trusted yet, -another vendor (**Alice**) SHOULD register the new vendor (**Bob**) through the following process: +DID documents are enclosed in a message envelope to ensure consistency in the network. +The envelope is in the form of a JWS as described in [RFC004](rfc004-distributed-document-format.md). +Once the network layer has confirmed the signature of the JWS, the registry MUST validate if the submitter is authorized to create, update or delete the document. +If the authorization fails, the document should be ignored. -1. **Bob** generates his CA certificate (see [RFC008](rfc008-certificate-structure.md)) and creates the vendor proof (see section 6, "Vendor proof"). -2. **Bob** sends his CA certificate and vendor proof to **Alice** via an out-of-band mechanism (see below). -3. **Alice** creates the vendor registration document with **Bob**'s CA certificate and vendor proof, then signs and publishes it. -4. **Bob** adds **Alice**'s CA certificate to its truststore. -5. **Bob** connects to **Alice** and starts receiving documents. +The `controller` field MAY be present. If no `controller` field is present, the DID subject itself is the controller. +If the `controller` field is present, only the DID subjects from the `controller` field can change the DID document. -Before **Alice** connects to **Bob** they communicate out-of-band. A (relatively) trusted means of communication SHOULD -be used, like signed e-mail or authenticated chat. +#### 3.2.1 Create (Register) -#### Fields -The following fields MUST be present: -* **certs** (certificates): MUST contain an array containing base64 encoded vendor CA certificates. -* **prfs**: MUST contain an array of cryptographic proofs asserting the vendor being a real software company. +A Create operation for a DID Document puts the following additional requirements on the JWS header parameters: -Example: -```json -{ - "certs": ["CA certificate as base64 ASN.1"], - "prfs": ["vendor proof"] -} -``` +- `jwk` MUST be present +- `cty` MUST contain the value `application/json+did-document` +- `tiv` MUST be absent or `0` +- `tid` MUST be absent + +The `kid` field of the `jwk` header parameter MUST be prefixed by the `id` of the DID document. +In order for the contents to be accepted in the Nuts registry, the JWK MUST match the `authentication` key in the DID document with the same identifier. +The `kid` field from the JWK MUST match the `id` from the verification key in the DID document. + +Example JWS header -#### Duplicates -Vendors COULD re-register their vendor e.g. in case of loss of CA and signing key. As long as the new proof is valid -the new CA certificate MUST be deemed valid to authenticate that vendor. The original registration MUST be kept as well, -essentially merging the two. - -#### Validation -When processing a vendor registration or update it MUST be validated as follows: - -1. Assert all required fields are present. -2. Assert all fields value formats are valid. -3. For updates: assert only modifiable fields are updated (**certs**, **prfs** are modifiable). -4. Validate **prfs**: - * Assert there is at least one proof. - * Assert proofs are valid at the time they're introduced. - * Assert all proofs authenticate the same vendor. -5. Validate **certs**: - * Assert there is at least one certificate. - * Assert all certificates conform to the vendor CA certificate specification (see [RFC008](rfc008-certificate-structure.md)). - * Assert all certificates have the same MUST contain the same vendor ID. - -If any of these steps fail the registration or update SHALL NOT be processed. - -#### Revoking CA certificates -When a vendor loses or leaks its private key, the vendor SHOULD remove the certificate from its registration to avoid -malicious parties exploiting it. However, other parties MUST regard signatures created before removal of the certificate - as valid. How the vendor SHOULD change its CA certificate depends on the situation: - -##### CA certificate private key loss -In case the vendor loses its CA private key it MUST register a new vendor CA certificate. This can be done in two ways, -depending on what was lost: - -1. If the vendor still has a valid signing certificate it COULD sign the update using that private key. -2. Otherwise, when the signing certificate has expired or the private key is lost as well, the vendor MUST also provide -new proof to authenticate ownership of the vendor. The new proof MUST be the first operation in the **patch** field. - -Example update: ```json { - "patch": [ - { "op": "add", "path": "/prfs", "value": "some new proof" }, - { "op": "replace", "path": "/crts", "value": ["CA certificate as base64 ASN.1"] } + "alg": "PS256", + "cty": "application/json+did-document", + "jwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC", + "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + }, + "crit": [ + "sigt", + "ver", + "prevs" + ], + "sigt": "", + "ver": "1", + "prevs": [ + "148b3f9b46787220b1eeb0fc483776beef0c2b3e" ] } -``` +``` + +The DID document has the following basic requirements: + +- the `id` MUST be generated according to the method specified at the beginning of §3 +- at least 1 key MUST be present in the `verificationMethod` and `authentication` +- all key references in `authentication` MUST refer to keys listed under `verificationMethods` + +Each key listed in `verificationMethod` MUST have an `id` equal to the DID followed by a `#` followed by XXXXX???? +Each key MUST be of type `JsonWebKey2020` (TODO: follow that spec) +TODO limit curve + +The `controller` field MAY be present. This RFC follows the [did-core-spec](https://www.w3.org/TR/did-core/#did-controller). + +TODO: `assertion` field + +Example DID document: -##### CA certificate private key leakage -In case the vendor leaks its CA private key (or it gets stolen), it MUST remove the associated certificate as soon as possible -and register a new one. -In the same update it MUST register new proof and CA certificate as in the key loss process. -Example update: ```json { - "patch": [ - { "op": "add", "path": "/prfs", "value": "some new proof" }, - { "op": "replace", "path": "/crts", "value": ["CA certificate as base64 ASN.1"] } - ] + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:123", + "controller": [ + "did:nuts:123", + "did:nuts:7368245" + ], + "verificationMethod": [{ + "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:123", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }], + "authentication": ["did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], + "service": [] } -``` - -To avoid attackers re-adding the previously removed CA certificate, the application SHOULD allow administrators to - register compromised X.509 certificate thumbprints with the date it was compromised. The application SHALL NOT accept - certificates or signatures on or after this date. Communication of network participants regarding this compromised - certificate list SHOULD happen out-of-band over an authenticated channel. - -### 5.2. Organization -This document registers a care organization as a client of registered vendor (section 5.1). It's identified by the type `registry/organization`. - -#### Fields -The following fields MUST be present: -* **id**: MUST contain the organization's ID encoded as URN. This can be any valid URN, for instance an AGB-code or - KVK-number e.g.: `urn:oid:2.16.840.1.113883.2.4.6.1:06123456` (AGB-code). It is used to refer to the organization by the - vendor itself or other vendors. The organisation ID SHALL NOT be changed. -* **vid** (vendor ID): MUST be the organization's software vendor's ID as URN (e.g. `urn:oid:1.3.6.1.4.1.54851.4:1234`). - The vendor ID SHALL NOT be changed; relation to a care organization SHALL NOT be transfered to another vendor. -* **name**: MUST contain the organization's commonly known name as string. Only alphanumeric, dashes (`-`) and space characters are allowed, - it SHALL NOT be empty or only contain spaces. It MUST conform to the following regex: `[a-zA-Z0-9 ]+`. -* **prfs** (proofs): MUST contain an array with cryptographic proofs asserting the organization as being an actual care organization. - at the same it serves as commitment from the care organization that it uses the vendor's (identified by **vid**) software. - See section 7 for supported proof types. +``` + +#### 3.2.2 Read (Resolve) +A Nuts DID can only be resolved locally. The concept of the Nuts registry is the state based upon all Create, Update and Delete operations received through the Nuts Network. +Therefore, any DID document SHOULD already be present in local storage. + +##### 3.2.2.1 Resolution Input Metadata +All historic versions of a DID Document SHOULD be stored and queryable. This allows clients to resolve the document +for a specific moment in time (e.g. a previous version) instead of the last one. For this the resolution input metadata +MAY contain the `timestamp` field indicating this moment in time. This field MUST be formatted according to [RFC3339](https://tools.iets.org/html/rfc3339). Example: ```json { - "id": "urn:oid:2.16.840.1.113883.2.4.6.1:06123456", - "vid": "urn:oid:1.3.6.1.4.1.54851.4:1234", - "name": "HomeSweetHome Thuiszorg", - "prfs": ["organisation proof"] + "timestamp": "2020-01-06T15:00:00Z" } ``` -#### Validation -When processing an organization registration or update it MUST be validated as follows: - -1. Assert all required fields are present. -2. Assert all fields value formats are valid. -3. For updates: assert only modifiable fields are updated (**name**, **prfs** are modifiable). -4. Assert the document is signed by the vendor identified by **vid**. -5. Validate **prfs**: - * Assert there is at least one proof. - * Assert proofs are valid at the time they're introduced. - * Assert all proofs authenticate the same organisation. - -### 5.3. Endpoint -This document registers an endpoint exposed by a vendor which CAN be used to exchange data with the vendor or its organizations. -It's identified by the type `registry/endpoint`. - -#### Fields -The following fields MUST be present: -* **id**: MUST be a string identifying this endpoint. It must be unique for the vendor. -* **vid** (vendor ID): MUST contain the ID of the vendor this endpoint belongs to. -* **type**: MUST be a URN describing the type of this endpoint in the form of `urn:oid:1.3.6.1.4.1.54851.2:type`. - The actual type MUST be an ASCII alphanumeric (a-z, 0-9) lowercase string. -* **loc** (location): MUST be a URL pointing to where the endpoint is exposed (e.g. `https://nuts.nl/some/path`) -* **nbf** (not before): MUST contain an RFC 3339 timestamp indicating from what date/time the endpoint SHOULD be considered valid. - -The following fields MAY be present: -* **exp** (expiration): MUST contain an RFC 3339 timestamp indicating when the endpoint expires and SHOULD NOT be considered valid anymore. +If `timestamp` is not present the current date/time MUST be assumed. -Example: +##### 3.2.2.2 Document Metadata +The resolved DID Document Metadata contains the `created` and `updated` fields, in accordance with the [did-core-spec](https://www.w3.org/TR/did-core/#did-document-metadata-properties). They are +derived from the underlying Nuts Documents. `created` MUST contain the `sigt` timestamp from the first version of the +document. `updated` MUST contain the `sigt` timestamp of the last version of the DID Document. + +#### 3.2.3 Update (Replace) +The complete document gets replaced with a newer version. + +Changes to DID documents can only be accepted if the update is signed with current controller authentication key: + +- a key referenced from the `authentication` section of the latest DID document version. +- a key referenced from the `authentication` section of a controller. One of the entries in the `controller` field MAY refer to a different DID Document. + The `authentication` keys of the latest version of that DID Document can be used as authorized key. +- a key referenced from the `authentication` section of the given DID document if it is a `Create` action. + +The following requirements on the JWS header parameter apply: + +- `kid` MUST hold the reference to the correct key. +- `tid` and `tiv` MUST be filled according to [RFC004](rfc004-distributed-document-format.md). + +Example JWS header: ```json { - "id": "de59b062-d783-4727-a05e-57ed6035f00d", - "vid": "urn:oid:2.16.840.1.113883.2.4.6.1:1234", - "type": "urn:oid:1.3.6.1.4.1.54851.2:fhir", - "loc": "https://nuts.nl/some/path", - "nbf": "2020-04-23T18:25:43.511Z" + "alg": "PS256", + "cty": "application/json+did-document", + "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "crit": ["sigt", "ver","prevs"], + "sigt": "2020-01-06T15:00:00Z", + "ver": "1", + "prevs": ["148b3f9b46787220b1eeb0fc483776beef0c2b3e"], + "tid": "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", + "tiv": "1" } ``` -### 5.4. Service -A service groups a set of endpoints to be used for a specific use case (Bolt) for a specific organization. It's identified by the type `registry/service`. -It MUST contain the following fields: -* **oid** (organization ID): MUST contain the ID of the organization this service belongs to. -* **vid** (vendor ID): MUST contain the ID of the vendor this endpoint belongs to. -* **name**: MUST contain the service's case sensitive name. It MUST be unique within the organization and vendor combination. - It is used by other parties who want to execute a specific Bolt (with this organization) to look up the correct endpoints. -* **eps** (endpoints): MUST contain an array of endpoint IDs to be used for this service. The endpoints MUST have the - same **vid** field as the service. -* **nbf** (not before): MUST contain an RFC 3339 timestamp indicating from what date/time the service could be used. +#### 3.2.4 Delete (Revoke) -The following fields MAY be present: -* **exp** (expiration): MUST contain an RFC 3339 timestamp indicating when the service expires and SHOULD NOT be used anymore. +DID Documents cannot be deleted as in being "erased", only its keys can be removed as to prevent future changes (revocation). +To revoke the keys to prevent future updates; + +1. Remove all keys (specified by `verificationMethod`) and references (specified by e.g. `authentication`) to + these keys from the document. +2. Remove all controllers from the document. + +Deletion can not be undone. + +Example DID document: -Example: ```json { - "oid": "urn:oid:2.16.840.1.113883.2.4.6.1:06123456", - "vid": "urn:oid:1.3.6.1.4.1.54851.4:1234", - "name": "some-bolt", - "eps": ["1B5E2A91-5C19-41B6-9709-BC9050D193E5", "some-other-endpoint-ID"], - "nbf": "2020-10-20T20:30:50.52Z" + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:123", + "controller": [], + "verificationMethod": [], + "authentication": [] } ``` -#### Validation -When processing a service registration or update it MUST be validated as follows: +### 3.3 Security Considerations + +Almost all security considerations are covered by the mechanisms described in [RFC004](rfc004-distributed-document-format.md). An overview of countermeasures: -1. Assert all required fields are present. -2. Assert all fields value formats are valid. -3. For updates: assert only modifiable fields are updated (**eps**, **nbf** and **exp** are modifiable). -4. Assert the vendor identified by **vid** is registered. -5. Assert the organization identified by **oid** is registered. -6. Assert the endpoints referenced in **eps** are registered. -7. Assert the document is signed by the vendor identified by **vid**. -8. Assert the combination of **oid**, **vid** and **name** is not already registered. +- **eavesdropping** - All communications is sent over two-way TLS. All data is public anyway. +- **replay** - DID documents are identified and published by their hash (SHA-256). Replaying will result in replaying the exact same content. +- **message insertion** - [RFC004](rfc004-distributed-document-format.md) defines hashing and signing of published documents. +- **deletion** - All DID documents are published and copied on a mesh network. Deletion of a single document will only occur locally and will not damage other nodes. +- **modification** - DID documents can only be modified if they are published with a signature from one of the `authentication` keys. +- **man-in-the-middle** - All communications is sent over two-way TLS and all documents are signed. A DID can not be hijacked since it is derived from the public key. +- **denial of service** - This is out of scope and handled by [RFC004](rfc004-distributed-document-format.md). -## 6. Vendor proof -Vendor proof authenticates the registration of a vendor, assuring that it: -1. represents a real company, registered at the (Dutch) Chamber of Commerce and, -2. commits to an agreement if required by the network (optional). +#### 3.3.1 Protection against DID hijacking -TODO: Include public key of vendor CA certificate +The Nuts network is a mesh network without central authority. This means that any party can generate a DID. +This DID must be protected against forgery and hijacking since duplicates are accepted in the Nuts network. +The duplicates are sorted and one will eventually be accepted (consistency rules of [RFC004](rfc004-distributed-document-format.md)). This would open up a DID to hijacking. +Therefore, the DID MUST be a derivative of the public key used to sign the document as described in chapter 2. -Vendor proof MUST be a JSON Web Token (JWT) encoded as string. The JWT MUST be signed using the algorithm specified by -the specific proof type. - -The JWT SHALL NOT be encrypted. +#### 3.3.2 Protection against loss of private key -### 6.1. Fields -The following claims MUST be present: -* **sub** (subject): MUST contain the fully qualified vendor ID. -* **iat** (issued at): MUST contain the time at which the proof was issued. -* **x5c** (X.509 certificate chain): MUST contain an array of base64 encoded signing certificates. +The loss of a single private key can be countered by registering multiple keys. Keys can be kept offline, in a vault for example. +Such a key can later be used to register new keys when needed. Another option is to add a second controller that acts as an emergency backup. +The keys of that controller can be kept offline. -The following claims MAY be present: -* **agrs** (agreements): MUST contain an array with network usage agreements (see Agreements section below) that the - signer commits to when signing the proof. - -Other claims SHOULD NOT be present and MUST be ignored. - -### 6.2. Agreements -Networks COULD decide they want every vendor to sign an agreement when registering. In that case the vendor SHOULD specify -the SHA-1 hash(es) of the agreement(s) that it commits to in the proof. The agreements SHOULD be published out of band -on a well-known location. Other vendors SHOULD verify that the newly registered vendor specified an agreement they accept -(accepted agreements COULD be configured in the vendor software). +#### 3.3.3 Protection against theft of private key -### 6.3. Accepted certificates -This describes which certificates are accepted as vendor proof. +A stolen key can alter the DID document in such a way that the attacker can get full control with a new key and can exclude the previous owner from making changes. +Appropriate measures MUST be taken to keep authentication keys secure. -#### 6.3.1. PKIoverheid Persoonlijk Organisatiegebonden Certificaat +When control over a DID document has been lost, the DID subject will have to have all Verifiable Credentials revoked. +Without Verifiable Credentials linked to the DID document, the DID document no longer has any value. +The DID subject will have to go through the process of reacquiring all Verifiable Credentials for a new DID document. -When using this proof type the certificate MUST be a trusted PKIoverheid TSP CA (Trust Service Provider Certificate Authority). -The signature algorithm MUST be one of the following: PS256, PS384, PS512, ES256, ES384 or ES512. Other algorithms SHALL NOT be used. +TODO Is this acceptable? A SaaS provider will have to re-add all care organizations as DID documents (including services). Then all care organizations must also re-add the VC that proves their name/address to the new DID document! -The **x5c** field MUST contain the end object certificate and all intermediate CA certificates except the *Staat der Nederlanden* Root CA certificate. -The root CA certificate SHOULD NOT be included. +### 3.4 Privacy considerations -TODO: KVK-nummer +All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. -## 7. Organization proof -TODO: Consider using DIF Verifyable Credentials instead of JWT/JWS +## 4. Services +It is to be expected that each DID subject will add services to the DID Document. Specific services will be specified in their own RFC. +A service can define an absolute endpoint URI or be a compound service, referring to a set of services. This is often the case +when a SaaS provider defines endpoints to be used for all clients. -Organization proof authenticates the registration of a care organization, assuring that it: -1. represents a real care organization and, -2. wants to exchange data using Nuts through the vendor's software. +For an absolute endpoint URI the `serviceEndpoint` MUST be a string containing the URI. For a compound service the +`serviceEndpoint` MUST contain a map containing references to absolute endpoint URI services. + +The service identifier MUST be constructed from the DID followed by a `#`, the service type, a `-` and an identifier unique to the DID document. + +Below is an example of a service registered by a care organization that uses the endpoints from a SaaS provider: + +The SaaS provider defines the actual URL: +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:123", + "service": [ + { + "id": "did:nuts:123#NutsOAuth-1", + "type": "NutsOAuth", + "serviceEndpoint": "https://example.com/oauth" + }, + { + "id": "did:nuts:123#NutsFHIR-1", + "type": "NutsFHIR", + "serviceEndpoint": "https://example.com/fhir" + } + ] +} +``` -Organization proof MUST be a JSON Web Token (JWT) encoded as string. The JWT MUST be signed using the algorithm specified by -the specific proof type. - -The JWT SHALL NOT be encrypted. +The care organisation refers to it: +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:abc", + "service": [ + { + "id": "did:nuts:abc#NutsCompoundService-1", + "type": "NutsCompoundService", + "serviceEndpoint": { + "oauthEndpoint": "did:nuts:123#NutsOAuth-1", + "fhirEndpoint": "did:nuts:123#NutsFHIR-1" + } + } + ] +} +``` -### 7.1. Accepted certificates -This describes which certificates are accepted as vendor proof. +## 5. Deployment scenarios -### 7.1.1 UZI certificate signature -TODO +The definition of the Nuts DID method enables a wide variety of usages. +To better understand the usages, this chapter illustrates some example scenarios. -## 8. Trust +This section is non-normative. + +### 5.1 SaaS provider + +This example consists of a SaaS provider that acts as enabler, controller and node operator for all of its customers. The SaaS provider has access to all the key material, while the care organizations hasn't. + +The SaaS provider registers itself with: + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:1", + "verificationMethod": [ + { + "id": "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:1", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }, + { + "id": "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA", + "controller": "did:nuts:1", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }], + "authentication": [ + "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA" + ], + "service": [ + { + "id": "did:nuts:123#NutsOAuth-1", + "type": "NutsOAuth", + "serviceEndpoint": "https://example.com/oauth" + }, + { + "id": "did:nuts:123#NutsFHIR-1", + "type": "NutsFHIR", + "serviceEndpoint": "https://example.com/fhir" + } + ] +} +``` + +It registers two keys: one if kept offline as backup, and the other is available in the software of the SaaS provider. + +The SaaS provider registers a care organization as: + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:2", + "verificationMethod": [ + { + "id": "did:nuts:2#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:2", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }], + "authentication": [ + "did:nuts:2#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + ], + "controller": [ + "did:nuts:1" + ], + "service": [ + { + "id": "did:nuts:abc#NutsCompoundService-1", + "type": "NutsCompoundService", + "serviceEndpoint": { + "oauthEndpoint": "did:nuts:1#NutsOAuth-1", + "fhirEndpoint": "did:nuts:1#NutsFHIR-1" + } + } + ] +} +``` -There's no central authority controlling access to the network (see section 4.4 of [Nuts Start Architecture](rfc001-nuts-start-architecture.md)); -a new vendor gets access by asking another vendor, who already has access, to register it (the new vendor) to get access. -This means there's a chain of trust: if vendor A and B form a network and vendor C joins through vendor B, new vendor C -is trusted by vendor A because it (A) trusts vendor B. This is like vouching; you should only register other vendors you -trust because if that vendor turns out to be malicious, it could backfire to you as well. In the worst case other vendors -could blacklist your vendor as well, denying you from accessing the network. +The care organization does have an `authentication` key, this is required for the generation of the `id`. The SaaS provider will most likely not store the key since that key is not in control of the DID document. +Since this key isn't after initial creation of the document the SaaS provider SHOULD remove it from the authentication document afterwards to improve security and clarity. +The DID document of the SaaS provider is the controller of the DID document. -### 8.1. Network bootstrapping +### 5.2 Hospital -Having no central authority causes a bootstrapping problem: how to establish trust between the first two nodes which -form a new network. This SHOULD be solved by exchanging the vendor CA certificate and proofs and registering the other -vendor on the local node. After that one vendor can connect to the other vendor (or both, bi-directional) causing the -registration documents to be exchanged, forming the network. +### 5.3 Single person deployment -### 8.2. Accepting invalid proof -When implementing this RFC there might be no viable means to create vendor and/or organization proof. In that case -implementations SHOULD allow node administrators to explicitly accept a document with missing or invalid proof. -That way vendors can still start exchanging data when viable means of authenticating vendors and/or organizations -are not available yet. However, when the proof means become available and common the vendors and organizations MUST -update their registration so authenticated proof can be made mandatory. +## Current issues -## 9. Security & Privacy +### Key management and mitigating impact of key loss +Considering the case a care provider has outsourced its key management to a service provider. +When discussing deployment scenarios, we should consider the different roles at the service provider like: +* Sales and support department who can create and delete DID documents +* System administrators who alter serviceEndpoints -All information published in the registry is public. Vendors MUST take care NOT to publish sensitive information. -The distributed nature makes it very hard or even impossible to have information removed. The authenticity and integrity -of the published information is protected by the [RFC004 Distributed Document Format](rfc004-distributed-document-format.md). +It might not be desirable for these roles have access to the same key material. We can suggest configurations with different DID documents with different keys for services and for controller. +### Management of VCs by a trusted service provider +Considering the case a care provider has outsourced it key management to a service provider. +When obtaining a VC from a trusted party, how does the care provider prove that it is the party represented by the DID without being able to provide private key material? +### Resolvability of the DID document +The fundamental idea of a DID document is that it should be resolvable by other parties. Section [7.2.2 of the did-core spec](https://w3c.github.io/did-core/#read-verify) requires a specification how a DID resolver could resolve and verify a DID document from the registry. Since the Nuts registry will be a local registry this is not yet a consideration but when federation with other registries will become relevant, a proper specification should be written. \ No newline at end of file diff --git a/rfc/rfcdid-did-nuts-method.md b/rfc/rfcdid-did-nuts-method.md deleted file mode 100644 index 62c1343..0000000 --- a/rfc/rfcdid-did-nuts-method.md +++ /dev/null @@ -1,467 +0,0 @@ -# RFCXXX Distributed Registry with Decentralized Identifiers - -| | | -| :--- | :--- | -| Nuts foundation | Author | -| Request for Comments: 00x | Nedap | -| | January 2021 | - -## Distributed Registry with Decentralized Identifiers -### Abstract - -This RFC describes a protocol to build a registry containing information required for (care) organizations to exchange data. -The registry typically contains organizations, software vendors acting on behalf of their client (organizations), -data exchange services offered by organizations and their technical endpoints. -It describes how these are mapped to [Decentralized Identifiers](https://www.w3.org/TR/did-core/) and how DID Documents -are encapsulated in [RFC004 Distributed Documents](rfc004-distributed-document-format.md) to provide cryptographic -integrity and consistent state across distributed networks. - -### Status - -This document is currently a draft. - -### Copyright Notice -![](../.gitbook/assets/license.png) - -This document is released under the [Attribution-ShareAlike 4.0 International \(CC BY-SA 4.0\) license](https://creativecommons.org/licenses/by-sa/4.0/). - -## 1. Introduction - -When care organizations want to exchange data using Nuts they need to know where to find that data and how to authenticate it. -This knowledge is recorded in a distributed registry, writable and queryable by all network participants. -This RFC describes how to create, update and resolve the data structures required to achieve that goal. - -## 2. Terminology - -* **Bolt**: a use case built on top of the functionality Nuts provides. -* **JWS**: JSON Web Signature as specified by [RFC004](rfc004-distributed-document-format.md). -* **Organization**: a care organization exchanging data with other care organizations over a Nuts network. - By giving other DIDs control over its DID Document organizations can delegate data exchange to another party, - e.g. a care software vendor or SaaS provider. -* **Endpoint**: a URI or URL exposed by a network participant which can be used by other participants to pull data. -* **Service**: a group of endpoints implementing a service required by a Bolt. - -## 3. Nuts DID Method - -The Nuts DID URI scheme is defined as follows: -``` -did = "did:nuts:" idstring -idstring = 21*22(base58char) -base58char = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "A" / "B" / "C" - / "D" / "E" / "F" / "G" / "H" / "J" / "K" / "L" / "M" / "N" / "P" / "Q" - / "R" / "S" / "T" / "U" / "V" / "W" / "X" / "Y" / "Z" / "a" / "b" / "c" - / "d" / "e" / "f" / "g" / "h" / "i" / "j" / "k" / "m" / "n" / "o" / "p" - / "q" / "r" / "s" / "t" / "u" / "v" / "w" / "x" / "y" / "z" - -``` - -Where the `idstring` is derived from the public key: - -`idstring = BASE-58(SHA-256(raw-public-key-bytes))` - -For example, consider the following Ed25519 key (as JWK): - -```json -{ - "kty" : "OKP", - "crv" : "Ed25519", - "x" : "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", - "use" : "sig", - "kid" : "FdFYFzERwC2uCBB46pZQi4GG85LujR8obt-KWRBICVQ" -} -``` - -For this key type the `x` parameter is used to derive `idstring`: -`idstring = BASE-59(SHA-256(BASE64URL-DECODE(key.x)))` - -Outputs: -```json -{ - "id": "did:nuts:e3cacd5c2d931295a64f6c3bb3f6ea58c3a9b253b990e32c5abce43c2f94c564" -} -``` - -### 3.1 Namespace Specific Identifier (NSI) - -Identifiers are derived from public keys that are valid at the moment of creating the DID document. -It MUST be the public key that corresponds to the private key that was used to sign the Nuts registry document ([RFC004](rfc004-distributed-document-format.md)). -The public key MUST also be present in the `verificationMethods`. When multiple keys are present, one MUST verify in this matter. - -### 3.2 Method operations - -DID documents are enclosed in a message envelope to ensure consistency in the network. -The envelope is in the form of a JWS as described in [RFC004](rfc004-distributed-document-format.md). -Once the network layer has confirmed the signature of the JWS, the registry MUST validate if the submitter is authorized to create, update or delete the document. -If the authorization fails, the document should be ignored. - -The `controller` field MAY be present. If no `controller` field is present, the DID subject itself is the controller. -If the `controller` field is present, only the DID subjects from the `controller` field can change the DID document. - -#### 3.2.1 Create (Register) - -A Create operation for a DID Document puts the following additional requirements on the JWS header parameters: - -- `jwk` MUST be present -- `cty` MUST contain the value `application/json+did-document` -- `tiv` MUST be absent or `0` -- `tid` MUST be absent - -The `kid` field of the `jwk` header parameter MUST be prefixed by the `id` of the DID document. -In order for the contents to be accepted in the Nuts registry, the JWK MUST match the `authentication` key in the DID document with the same identifier. -The `kid` field from the JWK MUST match the `id` from the verification key in the DID document. - -Example JWS header - -```json -{ - "alg": "PS256", - "cty": "application/json+did-document", - "jwk": { - "crv": "P-256", - "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", - "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", - "kty": "EC", - "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" - }, - "crit": [ - "sigt", - "ver", - "prevs" - ], - "sigt": "", - "ver": "1", - "prevs": [ - "148b3f9b46787220b1eeb0fc483776beef0c2b3e" - ] -} -``` - -The DID document has the following basic requirements: - -- the `id` MUST be generated according to the method specified at the beginning of §3 -- at least 1 key MUST be present in the `verificationMethod` and `authentication` -- all key references in `authentication` MUST refer to keys listed under `verificationMethods` - -Each key listed in `verificationMethod` MUST have an `id` equal to the DID followed by a `#` followed by XXXXX???? -Each key MUST be of type `JsonWebKey2020` (TODO: follow that spec) -TODO limit curve - -The `controller` field MAY be present. This RFC follows the [did-core-spec](https://www.w3.org/TR/did-core/#did-controller). - -TODO: `assertion` field - -Example DID document: - -```json -{ - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "did:nuts:123", - "controller": [ - "did:nuts:123", - "did:nuts:7368245" - ], - "verificationMethod": [{ - "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", - "controller": "did:nuts:123", - "type": "JsonWebKey2020", - "publicKeyJwk": { - "crv": "P-256", - "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", - "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", - "kty": "EC" - } - }], - "authentication": ["did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"], - "service": [] -} -``` - -#### 3.2.2 Read (Resolve) -A Nuts DID can only be resolved locally. The concept of the Nuts registry is the state based upon all Create, Update and Delete operations received through the Nuts Network. -Therefore, any DID document SHOULD already be present in local storage. - -##### 3.2.2.1 Resolution Input Metadata -All historic versions of a DID Document SHOULD be stored and queryable. This allows clients to resolve the document -for a specific moment in time (e.g. a previous version) instead of the last one. For this the resolution input metadata -MAY contain the `timestamp` field indicating this moment in time. This field MUST be formatted according to [RFC3339](https://tools.iets.org/html/rfc3339). - -Example: -```json -{ - "timestamp": "2020-01-06T15:00:00Z" -} -``` - -If `timestamp` is not present the current date/time MUST be assumed. - -##### 3.2.2.2 Document Metadata -The resolved DID Document Metadata contains the `created` and `updated` fields, in accordance with the [did-core-spec](https://www.w3.org/TR/did-core/#did-document-metadata-properties). They are -derived from the underlying Nuts Documents. `created` MUST contain the `sigt` timestamp from the first version of the -document. `updated` MUST contain the `sigt` timestamp of the last version of the DID Document. - -#### 3.2.3 Update (Replace) -The complete document gets replaced with a newer version. - -Changes to DID documents can only be accepted if the update is signed with current controller authentication key: - -- a key referenced from the `authentication` section of the latest DID document version. -- a key referenced from the `authentication` section of a controller. One of the entries in the `controller` field MAY refer to a different DID Document. - The `authentication` keys of the latest version of that DID Document can be used as authorized key. -- a key referenced from the `authentication` section of the given DID document if it is a `Create` action. - -The following requirements on the JWS header parameter apply: - -- `kid` MUST hold the reference to the correct key. -- `tid` and `tiv` MUST be filled according to [RFC004](rfc004-distributed-document-format.md). - -Example JWS header: -```json -{ - "alg": "PS256", - "cty": "application/json+did-document", - "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", - "crit": ["sigt", "ver","prevs"], - "sigt": "2020-01-06T15:00:00Z", - "ver": "1", - "prevs": ["148b3f9b46787220b1eeb0fc483776beef0c2b3e"], - "tid": "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", - "tiv": "1" -} -``` - -#### 3.2.4 Delete (Revoke) - -DID Documents cannot be deleted as in being "erased", only its keys can be removed as to prevent future changes (revocation). -To revoke the keys to prevent future updates; - -1. Remove all keys (specified by `verificationMethod`) and references (specified by e.g. `authentication`) to - these keys from the document. -2. Remove all controllers from the document. - -Deletion can not be undone. - -Example DID document: - -```json -{ - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "did:nuts:123", - "controller": [], - "verificationMethod": [], - "authentication": [] -} -``` - -### 3.3 Security Considerations - -Almost all security considerations are covered by the mechanisms described in [RFC004](rfc004-distributed-document-format.md). An overview of countermeasures: - -- **eavesdropping** - All communications is sent over two-way TLS. All data is public anyway. -- **replay** - DID documents are identified and published by their hash (SHA-256). Replaying will result in replaying the exact same content. -- **message insertion** - [RFC004](rfc004-distributed-document-format.md) defines hashing and signing of published documents. -- **deletion** - All DID documents are published and copied on a mesh network. Deletion of a single document will only occur locally and will not damage other nodes. -- **modification** - DID documents can only be modified if they are published with a signature from one of the `authentication` keys. -- **man-in-the-middle** - All communications is sent over two-way TLS and all documents are signed. A DID can not be hijacked since it is derived from the public key. -- **denial of service** - This is out of scope and handled by [RFC004](rfc004-distributed-document-format.md). - -#### 3.3.1 Protection against DID hijacking - -The Nuts network is a mesh network without central authority. This means that any party can generate a DID. -This DID must be protected against forgery and hijacking since duplicates are accepted in the Nuts network. -The duplicates are sorted and one will eventually be accepted (consistency rules of [RFC004](rfc004-distributed-document-format.md)). This would open up a DID to hijacking. -Therefore, the DID MUST be a derivative of the public key used to sign the document as described in chapter 2. - -#### 3.3.2 Protection against loss of private key - -The loss of a single private key can be countered by registering multiple keys. Keys can be kept offline, in a vault for example. -Such a key can later be used to register new keys when needed. Another option is to add a second controller that acts as an emergency backup. -The keys of that controller can be kept offline. - -#### 3.3.3 Protection against theft of private key - -A stolen key can alter the DID document in such a way that the attacker can get full control with a new key and can exclude the previous owner from making changes. -Appropriate measures MUST be taken to keep authentication keys secure. - -When control over a DID document has been lost, the DID subject will have to have all Verifiable Credentials revoked. -Without Verifiable Credentials linked to the DID document, the DID document no longer has any value. -The DID subject will have to go through the process of reacquiring all Verifiable Credentials for a new DID document. - -TODO Is this acceptable? A SaaS provider will have to re-add all care organizations as DID documents (including services). Then all care organizations must also re-add the VC that proves their name/address to the new DID document! - -### 3.4 Privacy considerations - -All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. - -## 4. Services -It is to be expected that each DID subject will add services to the DID Document. Specific services will be specified in their own RFC. -A service can define an absolute endpoint URI or be a compound service, referring to a set of services. This is often the case -when a SaaS provider defines endpoints to be used for all clients. - -For an absolute endpoint URI the `serviceEndpoint` MUST be a string containing the URI. For a compound service the -`serviceEndpoint` MUST contain a map containing references to absolute endpoint URI services. - -The service identifier MUST be constructed from the DID followed by a `#`, the service type, a `-` and an identifier unique to the DID document. - -Below is an example of a service registered by a care organization that uses the endpoints from a SaaS provider: - -The SaaS provider defines the actual URL: -```json -{ - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "did:nuts:123", - "service": [ - { - "id": "did:nuts:123#NutsOAuth-1", - "type": "NutsOAuth", - "serviceEndpoint": "https://example.com/oauth" - }, - { - "id": "did:nuts:123#NutsFHIR-1", - "type": "NutsFHIR", - "serviceEndpoint": "https://example.com/fhir" - } - ] -} -``` - -The care organisation refers to it: -```json -{ - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "did:nuts:abc", - "service": [ - { - "id": "did:nuts:abc#NutsCompoundService-1", - "type": "NutsCompoundService", - "serviceEndpoint": { - "oauthEndpoint": "did:nuts:123#NutsOAuth-1", - "fhirEndpoint": "did:nuts:123#NutsFHIR-1" - } - } - ] -} -``` - -## 5. Deployment scenarios - -The definition of the Nuts DID method enables a wide variety of usages. -To better understand the usages, this chapter illustrates some example scenarios. - -This section is non-normative. - -### 5.1 SaaS provider - -This example consists of a SaaS provider that acts as enabler, controller and node operator for all of its customers. The SaaS provider has access to all the key material, while the care organizations hasn't. - -The SaaS provider registers itself with: - -```json -{ - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "did:nuts:1", - "verificationMethod": [ - { - "id": "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", - "controller": "did:nuts:1", - "type": "JsonWebKey2020", - "publicKeyJwk": { - "crv": "P-256", - "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", - "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", - "kty": "EC" - } - }, - { - "id": "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA", - "controller": "did:nuts:1", - "type": "JsonWebKey2020", - "publicKeyJwk": { - "crv": "P-256", - "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", - "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", - "kty": "EC" - } - }], - "authentication": [ - "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", - "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA" - ], - "service": [ - { - "id": "did:nuts:123#NutsOAuth-1", - "type": "NutsOAuth", - "serviceEndpoint": "https://example.com/oauth" - }, - { - "id": "did:nuts:123#NutsFHIR-1", - "type": "NutsFHIR", - "serviceEndpoint": "https://example.com/fhir" - } - ] -} -``` - -It registers two keys: one if kept offline as backup, and the other is available in the software of the SaaS provider. - -The SaaS provider registers a care organization as: - -```json -{ - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": "did:nuts:2", - "verificationMethod": [ - { - "id": "did:nuts:2#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", - "controller": "did:nuts:2", - "type": "JsonWebKey2020", - "publicKeyJwk": { - "crv": "P-256", - "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", - "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", - "kty": "EC" - } - }], - "authentication": [ - "did:nuts:2#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" - ], - "controller": [ - "did:nuts:1" - ], - "service": [ - { - "id": "did:nuts:abc#NutsCompoundService-1", - "type": "NutsCompoundService", - "serviceEndpoint": { - "oauthEndpoint": "did:nuts:1#NutsOAuth-1", - "fhirEndpoint": "did:nuts:1#NutsFHIR-1" - } - } - ] -} -``` - -The care organization does have an `authentication` key, this is required for the generation of the `id`. The SaaS provider will most likely not store the key since that key is not in control of the DID document. -Since this key isn't after initial creation of the document the SaaS provider SHOULD remove it from the authentication document afterwards to improve security and clarity. -The DID document of the SaaS provider is the controller of the DID document. - -### 5.2 Hospital - -### 5.3 Single person deployment - - -## Current issues - -### Key management and mitigating impact of key loss -Considering the case a care provider has outsourced its key management to a service provider. -When discussing deployment scenarios, we should consider the different roles at the service provider like: -* Sales and support department who can create and delete DID documents -* System administrators who alter serviceEndpoints - -It might not be desirable for these roles have access to the same key material. We can suggest configurations with different DID documents with different keys for services and for controller. - -### Management of VCs by a trusted service provider -Considering the case a care provider has outsourced it key management to a service provider. -When obtaining a VC from a trusted party, how does the care provider prove that it is the party represented by the DID without being able to provide private key material? - -### Resolvability of the DID document -The fundamental idea of a DID document is that it should be resolvable by other parties. Section [7.2.2 of the did-core spec](https://w3c.github.io/did-core/#read-verify) requires a specification how a DID resolver could resolve and verify a DID document from the registry. Since the Nuts registry will be a local registry this is not yet a consideration but when federation with other registries will become relevant, a proper specification should be written. \ No newline at end of file From bb4ec24cc59d26f1ad79634f8ef78590a78459ba Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 7 Jan 2021 16:10:08 +0100 Subject: [PATCH 10/21] Described supported cryptographic and key types --- rfc/rfc006-distributed-registry.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index 871bb01..eb5218a 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -349,14 +349,24 @@ The care organisation refers to it: } ``` -## 5. Deployment scenarios +## 5. Supported Cryptographic Algorithms and Key Types + +Since RSA algorithms are deemed to be insecure for medium to long term, only elliptic curve-type algorithms are supported. +The library support for newer algorithms (e.g. `Ed25519`) and curves (`X25519`) however is limited, so for now only +the `secp256r1` NIST curve is supported. This curve is considered to provide enough security for the next 10 years, +according to the (Dutch Cyber Security Council)[https://www.ncsc.nl/]. + +It is expected however, that as library support improves more (stronger) algorithms and key types will be supported, +which should be taken in account by implementors. + +## 6. Deployment scenarios The definition of the Nuts DID method enables a wide variety of usages. To better understand the usages, this chapter illustrates some example scenarios. This section is non-normative. -### 5.1 SaaS provider +### 6.1 SaaS provider This example consists of a SaaS provider that acts as enabler, controller and node operator for all of its customers. The SaaS provider has access to all the key material, while the care organizations hasn't. @@ -451,9 +461,9 @@ The care organization does have an `authentication` key, this is required for th Since this key isn't after initial creation of the document the SaaS provider SHOULD remove it from the authentication document afterwards to improve security and clarity. The DID document of the SaaS provider is the controller of the DID document. -### 5.2 Hospital +### 6.2 Hospital -### 5.3 Single person deployment +### 6.3 Single person deployment ## Current issues From 662544ea789969de9987426e54ae938caeca0413 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 7 Jan 2021 16:22:37 +0100 Subject: [PATCH 11/21] VC example --- examples/care-organization-vc.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/care-organization-vc.md diff --git a/examples/care-organization-vc.md b/examples/care-organization-vc.md new file mode 100644 index 0000000..9875750 --- /dev/null +++ b/examples/care-organization-vc.md @@ -0,0 +1,27 @@ +```json +{ + "@context": ["https://www.w3.org/2018/credentials/v1"], + // specify the identifier for the credential + "id": "did:nuts:123/credentials/1", + "type": ["VerifiableCredential", "NutsNameCredential"], + "issuer": "did:nuts:123", + "issuanceDate": "2010-01-01T19:73:24Z", + "credentialSubject": { + // identifier for the only subject of the credential + "id": "did:nuts:123", + "name": "Verpleegtehuis de nootjes", + "locality": "Groenlo" + }, + "proof": { + "type": "RsaSignature2018", + "created": "2017-06-18T21:19:10Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:nuts:1#key-1", + // the digital signature value containing all of the above + "jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..TCYt5X + sITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5WEuts01mq-pQy7UJiN5mgRxD-WUc + X16dUEMGlv50aqzpqh4Qktb3rk-BuQy72IFLOqV0G_zS245-kronKb78cPN25DGlcTwLtj + PAYuNzVBAh4vGHSrQyHUdBBPM" + } +} +``` \ No newline at end of file From 8f4a5238e66e74a1f62ee03af2c902730be2b4ad Mon Sep 17 00:00:00 2001 From: stevenvegt Date: Thu, 7 Jan 2021 16:30:22 +0100 Subject: [PATCH 12/21] Update oauth spec with new DID changes --- rfc/rfc003-oauth2-authorization.md | 82 ++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/rfc/rfc003-oauth2-authorization.md b/rfc/rfc003-oauth2-authorization.md index f96a863..51cf9ef 100644 --- a/rfc/rfc003-oauth2-authorization.md +++ b/rfc/rfc003-oauth2-authorization.md @@ -65,11 +65,61 @@ When requesting data, the client application MUST add the access token to the Au ### 4.1. Registration -In common OAuth2 flows a client application must be registered by an authorization server with a client id and client secret. In a network of trust with many OAuth servers, this approach is difficult because it would mean every node needs to exchange secrets with every other node. Instead, the JWT signing public key needs to be approved by the client applications vendor. A client application needs to generate a key pair. The vendor should sign a certificate for the client application with its vendor CA certificate. The vendor CA certificate MUST be known by both client application and authorization server. The resulting certificate and the vendor CA MUST be added to the x5c header field. The certificate MUST not be valid for longer than 4 days. A vendor SHOULD generate a key-pair and certificate per deployment to reduce the exposure of the private key. The vendor is left with the choice to generate a certificate per actor, this is not required. +#### 4.1.1 Client registration +In common OAuth2 flows an OAuth client must be registered with the authorization server with its client id and client secret. This way the authorization server knows which requests are made by which party. The registration normally involves manual steps of registering and approving. +In a network of trust with countless combinations of authorization servers and clients, this approach does not scale well. -To protect the access token endpoint better, a client certificate is required to establish the TLS connection. This allows for vendors to use proven technologies such as reverse proxies. The client certificate to use will be self issued by the vendor and signed with the Vendor CA \[[Certificate structure RFC](rfc008-certificate-structure.md)\]. +So instead of client secrets, the Nuts OAuth flow binds the request via the JWT using its siganture to a known care provider. The key used to sign the JWT is identified by a provided key identifier (`kid`) which can be resolved from the Nuts registry as defined in [RFC006]. +The key should be listed in the `assertion` section of the actors DID document. -Every service requiring authentication MUST refer to an OAuth endpoint in the registry. The OAuth endpoint MUST have the type: `urn:oid:1.3.6.1.4.1.54851.2:oauth`. Its **loc** MUST point to the complete URL of the authorization server. The [Distributed Registry RFC](rfc006-distributed-registry.md) describes the registration format of an endpoint and service. + +Example of the actors DID document: +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:123", + "verificationMethod": [ + { + "id": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:123", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + } + ], + "assertion": ["did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw"] +} +``` + +#### 4.1.2 Server registration + +In order for the client to resolve the server endpoint it should look up the services in the custodians DID document under the `service` section. Endpoints there can be URLs or DIDs which resolve to other DID documents which the correct URL. A service COULD contain multiple named endpoints and MUST contain a single endpoint listed as `auth` . + +Example of the custodians DID document: +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:456", + "service": [ + { + "id": "did:nuts:456#oauth-1", + "type": "OAuthService", + "serviceEndpoint": "https://example.com/oauth" + },{ + "id": "did:nuts:456#ExampleService-1", + "type": "ExampleService", + "serviceEndpoint": { + "auth": "did:nuts:456#oauth-1", + "service": "https://example.com/fhir" + } + } + ] +} +``` ### 4.2. Constructing the JWT @@ -77,14 +127,14 @@ Every service requiring authentication MUST refer to an OAuth endpoint in the re * **typ**: MUST be `JWT` * **alg**: one of `PS256`, `PS384`, `PS512`, `ES256`, `ES384` or `PS512` \([RFC7518](https://tools.ietf.org/html/rfc7518)\) -* **x5c**: MUST contain the signing certificate. \([RFC7515](https://tools.ietf.org/html/rfc7515)\) +* **kid**: MUST contain the identifier of a key published in the care providers DID document, listed in the `assertion` section. #### 4.2.2. Payload -* **iss**: The issuer in the JWT is always the actor, thus the care organization doing the request. -* **sub**: The subject contains the urn of the custodian. The custodian information could be used to find the relevant consent \(together with actor and subject\). +* **iss**: The issuer in the JWT is always the DID of the actor, thus the care organization making the request. +* **sub**: The subject contains the DID of the custodian. The custodian information could be used to find the relevant consent \(together with actor and subject\). * **sid**: The Nuts subject id, patient identifier in the form of an oid encoded BSN. Optional -* **aud**: As per [RFC7523](https://tools.ietf.org/html/rfc7523), the aud MUST be the token endpoint reference. This can be taken from the Nuts registry. This is very important to prevent relay attacks. +* **aud**: As per [RFC7523](https://tools.ietf.org/html/rfc7523), the aud MUST be the DID listed under the `auth` key of the services serviceEndpoint. * **usi**: User identity signature. The token container according to the [Authentication token RFC](rfc002-authentication-token.md). Base64 encoded. Optional * **osi**: Ops signature, optional, reserved for future use. * **exp**: Expiration, MUST NOT be later than 5 seconds after issueing since this call is only used to get an access token. It MUST NOT be after the validity of the Nuts signature validity. @@ -94,20 +144,20 @@ All other claims may be ignored. #### 4.2.3. Example JWT -```yaml +```json { "alg": "RS256", "typ": "JWT", - "X5c": ["MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIh...abbrevated...9saWNkr09VZw="] + "kid": "did:nuts:123#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" } ``` ```yaml { - "iss": "urn:oid:2.16.840.1.113883.2.4.6.1:48000000", - "sub": "urn:oid:2.16.840.1.113883.2.4.6.1:12481248", + "iss": "did:nuts:123", + "sub": "did:nuts:456", "sid": "urn:oid:2.16.840.1.113883.2.4.6.3:9999990", - "aud": "8agAwIBAgICAwEwDQYJKoZIh", + "aud": "did:nuts:456#ExampleService-1", "usi": {...Base64 encoded token container...}, "osi": {...hardware token sig...}, "exp": 1578915481, @@ -176,15 +226,15 @@ The following steps MUST all succeed. The order of execution is not relevant alt **5.2.1.1. JWT signature validation** -The first step is to validate the JWT, the **x5c** field in the JWT header holds the public key that is used to sign the JWT. If the signature is invalid, an **invalid\_signature** error is returned. +The first step is to validate the JWT, the DID in the **kid** field in the JWT header refers to the public key that is used to sign the JWT. If the signature is invalid, an **invalid\_signature** error is returned. -**5.2.1.2. Client certificate validation** +**5.2.1.2. TLS Client certificate validation** -The client certificate used in the TLS connection must come from the same Vendor CA as the certificate present in the **x5c** header. This can be checked by comparing the public keys. +The client certificate used in the TLS connection must conform the requirements as stated in [RFC008]. **5.2.1.3. Issuer validation** -The actor from the **iss** field must be known to the authorization server, a vendor must have registered it using a signing certificate signed by the same vendor CA as the CA that signed the certificate in the **x5c** field. It MAY be the case that the vendor CA has been renewed, in that case a previous valid certificate from the same vendor MAY have been used to register the actor. It that case the vendor CA MUST have been valid at the time the signing certificate had been signed. +To validate the identity of the issuer, the signature of the JWT must be signed with a key present in the actors DID document under the `assertion` section. **5.2.1.4. JWT validity** From 92097fbed8a3b703d8b218058398e9655207ad16 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Thu, 7 Jan 2021 17:23:21 +0100 Subject: [PATCH 13/21] minor stuff --- rfc/rfc003-oauth2-authorization.md | 27 +++++++++++++-------------- rfc/rfc006-distributed-registry.md | 20 +++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/rfc/rfc003-oauth2-authorization.md b/rfc/rfc003-oauth2-authorization.md index 51cf9ef..4fbec4e 100644 --- a/rfc/rfc003-oauth2-authorization.md +++ b/rfc/rfc003-oauth2-authorization.md @@ -69,9 +69,8 @@ When requesting data, the client application MUST add the access token to the Au In common OAuth2 flows an OAuth client must be registered with the authorization server with its client id and client secret. This way the authorization server knows which requests are made by which party. The registration normally involves manual steps of registering and approving. In a network of trust with countless combinations of authorization servers and clients, this approach does not scale well. -So instead of client secrets, the Nuts OAuth flow binds the request via the JWT using its siganture to a known care provider. The key used to sign the JWT is identified by a provided key identifier (`kid`) which can be resolved from the Nuts registry as defined in [RFC006]. -The key should be listed in the `assertion` section of the actors DID document. - +So instead of client secrets, the Nuts OAuth flow binds the request via the JWT using its signature to a known care provider. The key used to sign the JWT is identified by a key identifier (`kid`) which can be resolved from the Nuts registry as defined in [RFC006]. +The key MUST be listed in the `assertion` section of the actor DID document. The actor is identified by the `iss` field. Example of the actors DID document: ```json @@ -97,7 +96,7 @@ Example of the actors DID document: #### 4.1.2 Server registration -In order for the client to resolve the server endpoint it should look up the services in the custodians DID document under the `service` section. Endpoints there can be URLs or DIDs which resolve to other DID documents which the correct URL. A service COULD contain multiple named endpoints and MUST contain a single endpoint listed as `auth` . +In order for the client to resolve the server endpoint it should look up the services in the custodians DID document under the `service` section. Endpoints there can be URLs or DID identifiers which resolve to other DID documents which the correct URL. A service COULD contain multiple named endpoints and MUST contain a single endpoint that refers to a service with type `auth`. Example of the custodians DID document: ```json @@ -107,7 +106,7 @@ Example of the custodians DID document: "service": [ { "id": "did:nuts:456#oauth-1", - "type": "OAuthService", + "type": "auth", "serviceEndpoint": "https://example.com/oauth" },{ "id": "did:nuts:456#ExampleService-1", @@ -126,8 +125,8 @@ Example of the custodians DID document: #### 4.2.1. Header * **typ**: MUST be `JWT` -* **alg**: one of `PS256`, `PS384`, `PS512`, `ES256`, `ES384` or `PS512` \([RFC7518](https://tools.ietf.org/html/rfc7518)\) -* **kid**: MUST contain the identifier of a key published in the care providers DID document, listed in the `assertion` section. +* **alg**: one of `PS256`, `PS384`, `PS512`, `ES256`, `ES384` or `ES512` \([RFC7518](https://tools.ietf.org/html/rfc7518)\) +* **kid**: MUST contain the identifier of a key published in the actors DID document, listed in the `assertion` section. #### 4.2.2. Payload @@ -137,7 +136,7 @@ Example of the custodians DID document: * **aud**: As per [RFC7523](https://tools.ietf.org/html/rfc7523), the aud MUST be the DID listed under the `auth` key of the services serviceEndpoint. * **usi**: User identity signature. The token container according to the [Authentication token RFC](rfc002-authentication-token.md). Base64 encoded. Optional * **osi**: Ops signature, optional, reserved for future use. -* **exp**: Expiration, MUST NOT be later than 5 seconds after issueing since this call is only used to get an access token. It MUST NOT be after the validity of the Nuts signature validity. +* **exp**: Expiration, MUST NOT be later than 5 seconds after issuing since this call is only used to get an access token. It MUST NOT be after the validity of the Nuts signature validity. * **iat**: Issued at. NumericDate value of the time at which the JWT was issued. All other claims may be ignored. @@ -157,7 +156,7 @@ All other claims may be ignored. "iss": "did:nuts:123", "sub": "did:nuts:456", "sid": "urn:oid:2.16.840.1.113883.2.4.6.3:9999990", - "aud": "did:nuts:456#ExampleService-1", + "aud": "did:nuts:456#oauth-1", "usi": {...Base64 encoded token container...}, "osi": {...hardware token sig...}, "exp": 1578915481, @@ -216,7 +215,7 @@ HTTP/1.1 200 OK ### 5.1. Registration -The authorization server endpoint needs to be registered for each vendor/care organisation combination. +The authorization server endpoint needs to be registered for each service in the care organisation DID document. ### 5.2. Validation @@ -234,7 +233,7 @@ The client certificate used in the TLS connection must conform the requirements **5.2.1.3. Issuer validation** -To validate the identity of the issuer, the signature of the JWT must be signed with a key present in the actors DID document under the `assertion` section. +To validate the identity of the issuer, the signature of the JWT must be signed with a key present in the issuers DID document under the `assertion` section. **5.2.1.4. JWT validity** @@ -242,7 +241,7 @@ The JWT **iat** and **exp** fields MUST be validated. The timestamp of validatio **5.2.1.5. Login contract validation** -The **usi** field in the JWT contains the signed login contract. If present it MUST validate according to the [Authentication Token RFC](rfc002-authentication-token.md). The login contract MUST contain the name of the actor. This name MUST match the name in the registry identified by the **iss** field. +The **usi** field in the JWT contains the signed login contract. If present it MUST validate according to the [Authentication Token RFC](rfc002-authentication-token.md). The login contract MUST contain the name of the actor. TODO: match with VC issued for `iss`. **5.2.1.6. Endpoint validation** @@ -254,7 +253,7 @@ The **iss** fields contains the identifier of the actor, the **sub** field conta **5.2.1.8. Subject validation** -The **sub** field in the JWT MUST be a known organisation. It MUST have been registered by the vendor of the authorization server and it MUST be valid at the time indicated by the **iat** field. +The **sub** field in the JWT MUST be a known organisation. It MUST have been registered by the node operator of the authorization server and it MUST be valid at the time indicated by the **iat** field. #### 5.2.2. Error responses @@ -306,7 +305,7 @@ The resource server MUST validate the validity of the access token. It MAY conta 1. **The requested resource does not contain patient information.** Certain resources do not contain patient information and may therefore be exchanged without user context. Resources that fall in this category MUST be marked as such in the specific use case specification. 2. **The requested resource belongs to a patient.** In this case the resource server MUST validate that user context is present, e.g. an access token has been requested with the _usi_ field. The resource server MUST also verify if a known legal base is present for the combination of custodian, actor, subject and resource. -3. **The actor and custodian are the same.** It may be the case that a care organisation is using multiple service providers. In that case each service provider acts on behalf of the care organisation. Therefore it's not needed to provide user context. It's up to the service providers to provide the correct enforcement of roles and any auditing duties. Each of the service providers \(actor and custodian\) MAY use different identifiers for the same care organisation. To match the actor and custodian, the resource server MUST check if the proof in the registry that has been provided by the care organisation is the same. See RFC00X for the details. In short: A care organisation can only be published if it signs a challenge from the service provider. +3. **The actor and custodian are the same.** It may be the case that a care organisation is using multiple service providers. In that case each service provider acts on behalf of the care organisation. Therefore it's not needed to provide user context. It's up to the service providers to provide the correct enforcement of roles and any auditing duties. Each of the service providers \(actor and custodian\) MAY use different identifiers for the same care organisation. To match the actor and custodian, the resource server MUST check if the proof in the registry that has been provided by the care organisation is the same. See RFC00X for the details. ### 6.3. Error codes diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index eb5218a..8a9401a 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -86,13 +86,14 @@ Outputs: ``` Nuts DID Documents are wrapped in a JWS (JSON Web Signature) to ensure cryptographic authenticity and integrity through -([RFC004](rfc004-distributed-document-format.md)). Please refer to that RFC for how specifically create the JWS. +([RFC004](rfc004-distributed-document-format.md)). Please refer to that RFC on how to create the JWS. ### 3.1 Namespace Specific Identifier (NSI) Identifiers are derived from public keys that are valid at the moment of creating the DID document. It MUST be the public key that corresponds to the private key that was used to sign the JWS. -The public key MUST also be present in the `verificationMethods`. When multiple keys are present, one MUST verify in this matter. +The public key MUST also be present in the `verificationMethods` and referenced by the `authentication` field. +When multiple keys are present, one MUST verify in this matter. ### 3.2 Method operations @@ -151,11 +152,11 @@ The DID document has the following basic requirements: Each key listed in `verificationMethod` MUST have an `id` equal to the DID followed by a `#` followed by XXXXX???? Each key MUST be of type `JsonWebKey2020` (TODO: follow that spec) -TODO limit curve The `controller` field MAY be present. This RFC follows the [did-core-spec](https://www.w3.org/TR/did-core/#did-controller). -TODO: `assertion` field +The `assertion` field MAY be present. +Keys referenced from this field are used for signing Verifiable Credentials/Presentations and for signing JWTs in the OAuth flow. Example DID document: @@ -209,7 +210,7 @@ document. `updated` MUST contain the `sigt` timestamp of the last version of the #### 3.2.3 Update (Replace) The complete document gets replaced with a newer version. -Changes to DID documents can only be accepted if the update is signed with current controller authentication key: +Changes to DID documents can only be accepted if the update is signed with a current controller authentication key: - a key referenced from the `authentication` section of the latest DID document version. - a key referenced from the `authentication` section of a controller. One of the entries in the `controller` field MAY refer to a different DID Document. @@ -276,7 +277,7 @@ Almost all security considerations are covered by the mechanisms described in [R The Nuts network is a mesh network without central authority. This means that any party can generate a DID. This DID must be protected against forgery and hijacking since duplicates are accepted in the Nuts network. The duplicates are sorted and one will eventually be accepted (consistency rules of [RFC004](rfc004-distributed-document-format.md)). This would open up a DID to hijacking. -Therefore, the DID MUST be a derivative of the public key used to sign the document as described in chapter 2. +Therefore, the DID MUST be a derivative of the public key used to sign the document as described in §3. #### 3.3.2 Protection against loss of private key @@ -293,8 +294,6 @@ When control over a DID document has been lost, the DID subject will have to hav Without Verifiable Credentials linked to the DID document, the DID document no longer has any value. The DID subject will have to go through the process of reacquiring all Verifiable Credentials for a new DID document. -TODO Is this acceptable? A SaaS provider will have to re-add all care organizations as DID documents (including services). Then all care organizations must also re-add the VC that proves their name/address to the new DID document! - ### 3.4 Privacy considerations All data is public knowledge. All considerations from [§10 of did-core](https://www.w3.org/TR/did-core/#privacy-considerations) apply. @@ -353,7 +352,7 @@ The care organisation refers to it: Since RSA algorithms are deemed to be insecure for medium to long term, only elliptic curve-type algorithms are supported. The library support for newer algorithms (e.g. `Ed25519`) and curves (`X25519`) however is limited, so for now only -the `secp256r1` NIST curve is supported. This curve is considered to provide enough security for the next 10 years, +the `secp256r1`, `secp384r1` and `secp521r1` NIST curves MUST be supported. This curve is considered to provide enough security for the next 10 years, according to the (Dutch Cyber Security Council)[https://www.ncsc.nl/]. It is expected however, that as library support improves more (stronger) algorithms and key types will be supported, @@ -473,12 +472,15 @@ Considering the case a care provider has outsourced its key management to a serv When discussing deployment scenarios, we should consider the different roles at the service provider like: * Sales and support department who can create and delete DID documents * System administrators who alter serviceEndpoints +> how is this an issue if they all use the same software that selects the key? It might not be desirable for these roles have access to the same key material. We can suggest configurations with different DID documents with different keys for services and for controller. ### Management of VCs by a trusted service provider Considering the case a care provider has outsourced it key management to a service provider. When obtaining a VC from a trusted party, how does the care provider prove that it is the party represented by the DID without being able to provide private key material? +> They must initiate a session from the portal of the software vendor using the protocol specified to obtain a VC +> A mobile only VC won't suffice, a server has to be authorized not a single device ### Resolvability of the DID document The fundamental idea of a DID document is that it should be resolvable by other parties. Section [7.2.2 of the did-core spec](https://w3c.github.io/did-core/#read-verify) requires a specification how a DID resolver could resolve and verify a DID document from the registry. Since the Nuts registry will be a local registry this is not yet a consideration but when federation with other registries will become relevant, a proper specification should be written. \ No newline at end of file From 3565d26dcb236895f74446c8f75a7e826f996925 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Fri, 8 Jan 2021 08:28:38 +0100 Subject: [PATCH 14/21] remove latest todo's --- rfc/rfc006-distributed-registry.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index 8a9401a..9a79d44 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -150,8 +150,8 @@ The DID document has the following basic requirements: - at least 1 key MUST be present in the `verificationMethod` and `authentication` - all key references in `authentication` MUST refer to keys listed under `verificationMethods` -Each key listed in `verificationMethod` MUST have an `id` equal to the DID followed by a `#` followed by XXXXX???? -Each key MUST be of type `JsonWebKey2020` (TODO: follow that spec) +Each key listed in `verificationMethod` MUST have an `id` equal to the DID followed by a `#` and the public key fingerprint according to [rfc7638](https://tools.ietf.org/html/rfc7638) +Each key MUST be of type `JsonWebKey2020` according to §5.3.1 of the [did-core-spec](https://www.w3.org/TR/did-core/#key-types-and-formats) The `controller` field MAY be present. This RFC follows the [did-core-spec](https://www.w3.org/TR/did-core/#did-controller). From cf3fbf212a5615a0d63e031b5a9786d44a71b7a1 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Fri, 8 Jan 2021 09:14:34 +0100 Subject: [PATCH 15/21] added examples --- rfc/rfc006-distributed-registry.md | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index 9a79d44..2b4badb 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -462,8 +462,104 @@ The DID document of the SaaS provider is the controller of the DID document. ### 6.2 Hospital +We assume that a hospital has its own data centre and therefore, runs its own node. +This means that the DID document of the hospital doesn't need an additional controller. The hospital is in control of its own private keys. It does however, need to take precautions for private key loss/theft. + +The hospital would be able to register a single DID document: + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:1", + "verificationMethod": [ + { + "id": "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:1", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }, + { + "id": "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA", + "controller": "did:nuts:1", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }], + "authentication": [ + "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + ], + "assertion": [ + "did:nuts:1#_kalsjdyurtnAa4895akljnjghl584B9lkEJHNLJKFGA" + ], + "service": [ + { + "id": "did:nuts:1#NutsOAuth-1", + "type": "NutsOAuth", + "serviceEndpoint": "https://example.com/oauth" + }, + { + "id": "did:nuts:1#NutsFHIR-1", + "type": "NutsFHIR", + "serviceEndpoint": "https://example.com/fhir" + }, + { + "id": "did:nuts:abc#NutsCompoundService-1", + "type": "NutsCompoundService", + "serviceEndpoint": { + "oauthEndpoint": "did:nuts:1#NutsOAuth-1", + "fhirEndpoint": "did:nuts:1#NutsFHIR-1" + } + } + ] +} +``` + +The hospital registered 2 keys, one if used for assertions and one for authentication. +The authentication key is kept offline, meaning that any change to the DID document will require an administrator to sign the changes manually. +The assertion key is available online and used within the defined services. +All services are registered directly on the DID document. + ### 6.3 Single person deployment +It is possible to deploy a node as a person. You'll probably not offer any services, but you'll still be able to consume them. +Also losing key material is less of a problem since you only have to restore it for yourself. + +This example is the most simple, there's one key and it's used for all cases. + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:1", + "verificationMethod": [ + { + "id": "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw", + "controller": "did:nuts:1", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "crv": "P-256", + "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8", + "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4", + "kty": "EC" + } + }], + "authentication": [ + "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + ], + "assertion": [ + "did:nuts:1#_TKzHv2jFIyvdTGF1Dsgwngfdg3SH6TpDv0Ta1aOEkw" + ], + "service": [] +} +``` ## Current issues From 1fdf1c5db46e1f1f71986134578a385e5c0788ec Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Fri, 8 Jan 2021 14:15:30 +0100 Subject: [PATCH 16/21] first draft for rfc010 --- rfc/rfc010-multiple-operators.md | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 rfc/rfc010-multiple-operators.md diff --git a/rfc/rfc010-multiple-operators.md b/rfc/rfc010-multiple-operators.md new file mode 100644 index 0000000..1c58af3 --- /dev/null +++ b/rfc/rfc010-multiple-operators.md @@ -0,0 +1,64 @@ +# RFC010 Multiple operator service access + +| | | +| :--- | :--- | +| Nuts foundation | W.M. Slakhorst | +| Request for Comments: 010 | Nedap | +| | January 2021 | + +## Multiple operator service access +### Abstract + +This RFC describes an addition to [RFC003](rfc003-oauth2-auithorization.md) and [RFC006](rfc006-distributed-registry.md) on how to handle resource access when a legal party has multiple node operators. This is the case when a care organization uses multiple pieces of software from different SaaS providers. A SaaS provider can alter the care organization DID document so the DID document of the other provider is added as synonym. This is done by using the *also-known-as* relation. + +### Status + +This document is currently a draft. + +### Copyright Notice +![](../.gitbook/assets/license.png) + +This document is released under the [Attribution-ShareAlike 4.0 International \(CC BY-SA 4.0\) license](https://creativecommons.org/licenses/by-sa/4.0/). + +## 1. Introduction + +Care organizations rarely use one piece of software. Larger organizations can use up to a hundred different pieces of software. Every software vendor that has signed a **Data Processing Agreement** with the care organization is allowed to transfer data to any other software vendor within the limits of the **Data Processing Agreement**. + +To support this functionality, some registration and extended validation is required throughout the process of data transfer. + +## 2. Terminology + +* **Bolt**: a use case built on top of the functionality Nuts provides. +* **DID**: a decentralized identifier according to the [core-did-spec](https://www.w3.org/TR/did-core). +* **DPA**: Data Processing Agreement as defined by the GDPR. + +Other terminology is taken from the [Nuts Start Architecture](rfc001-nuts-start-architecture.md#nuts-start-architecture). + +## 3. Registration + +Each care organization that is registered at a node by a SaaS provider will have its own DID document. If a care organization uses 2 SaaS providers, it'll have two different DID documents. Since identification within the OAuth flow is done by DID, the DID subject need to be aware of each other. This can be done by adding the DID of one document and add it to the other. This is done by using the `alsoKnownAs` field defined in the [core-did-spec](https://www.w3.org/TR/did-core/#also-known-as). + +Example: + +```json +{ + "@context": [ "https://www.w3.org/ns/did/v1" ], + "id": "did:nuts:1", + "alsoKnownAs": [ + "did:nuts:2" + ] +} +``` + +This is a unary relation. In the above example, `did:nuts:2` does not know anything about `did:nuts:1`. +The controller of the DID document MUST verify that it added the correct DID in the `alsoKnownAs` field. + +## 4. Authentication + +As defined in point 3 in [§6.2 of RFC003](rfc003-oauth2-auithorization.md#6-2-authorization), if the actor and custodian are the same, access is granted. If a custodian had added an actor in their DID document under the `alsoKnownAs` field, it MUST grant access as defined by point 3 in §6.2 of RFC003. Bolts MUST describe what resources may be accessed in this way and if user context is required. + +## 5. Hijacked DID documents + +A DID subject that is added under the `alsoKnownAs` field is granted access to resources from the custodian. +In the case when the private key of the actor is compromised and the attacker is changing keys, the custodian SHOULD take appropriate action. +The node operator MUST remove a DID from the `alsoKnownAs` field when the `authentication` or `controller` field changes in the referenced DID document. \ No newline at end of file From cab704af3c33283d1ef9d4c78fbd138b1bc1cfdc Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Wed, 13 Jan 2021 09:51:05 +0100 Subject: [PATCH 17/21] leftover garbage due to master merge --- examples/care-organization-vc.md | 27 --------- examples/nuts-did.md | 89 ------------------------------ examples/organisation-did.md | 26 --------- examples/vendor-did.md | 37 ------------- rfc/rfc003-oauth2-authorization.md | 7 --- rfc/rfc006-distributed-registry.md | 3 - 6 files changed, 189 deletions(-) delete mode 100644 examples/care-organization-vc.md delete mode 100644 examples/nuts-did.md delete mode 100644 examples/organisation-did.md delete mode 100644 examples/vendor-did.md diff --git a/examples/care-organization-vc.md b/examples/care-organization-vc.md deleted file mode 100644 index 9875750..0000000 --- a/examples/care-organization-vc.md +++ /dev/null @@ -1,27 +0,0 @@ -```json -{ - "@context": ["https://www.w3.org/2018/credentials/v1"], - // specify the identifier for the credential - "id": "did:nuts:123/credentials/1", - "type": ["VerifiableCredential", "NutsNameCredential"], - "issuer": "did:nuts:123", - "issuanceDate": "2010-01-01T19:73:24Z", - "credentialSubject": { - // identifier for the only subject of the credential - "id": "did:nuts:123", - "name": "Verpleegtehuis de nootjes", - "locality": "Groenlo" - }, - "proof": { - "type": "RsaSignature2018", - "created": "2017-06-18T21:19:10Z", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:nuts:1#key-1", - // the digital signature value containing all of the above - "jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..TCYt5X - sITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5WEuts01mq-pQy7UJiN5mgRxD-WUc - X16dUEMGlv50aqzpqh4Qktb3rk-BuQy72IFLOqV0G_zS245-kronKb78cPN25DGlcTwLtj - PAYuNzVBAh4vGHSrQyHUdBBPM" - } -} -``` \ No newline at end of file diff --git a/examples/nuts-did.md b/examples/nuts-did.md deleted file mode 100644 index 11341a5..0000000 --- a/examples/nuts-did.md +++ /dev/null @@ -1,89 +0,0 @@ -The example below describes a generic Nuts DID to be used in the Nuts network: - -```json -{ - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - // The ID of the DID. Notice the ID doesn't indicate the entity type (vendor/care organization), - // that should be derived from the entity's credentials. - // MUST start with `did` - // MUST be a `nuts` method - // Should be a UUID (type 4) without meaning (in contrary to e.g. a public key like in DIDKey) to decouple resolving from presentation. - // How to make sure someone does not try to recreate a DID with same id? -> TODO: fix in network layer? - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", - // Who may create/update/delete this document? - // OPTIONAL: - // If not present DID subject is the only controller of the DID. - // If present and lists another DID, that subject can also control the DID - // If present but the DID subject itself is not listed, the DID subject DOES NOT have control over this document. - "controller": [ - // First controller equals this document's DID, meaning it controls its own document - "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", - // This entity is allowed to make changes to this document as well - // example usages are: - // - a trusted third party (e.g. nuts foundation or a vendor). - // - another document for the same legal care organization (when organizations merge). - // - parent document of this document which holds all key material (allows nesting for larger or complex organizations). - "did:nuts:f03a00f1-9615-4060-bd00-bd282e150c46" - ], - // `verificationMethod` contains all cryptographic keys associated with this DID. They are referenced by the - // verification relationships (e.g. `authentication` or `assertionMethod`) - "verificationMethod": [ - { - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1", - "type": "RsaVerificationKey2018", - "controller": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", - "publicKeyJwk": { - "crv": "Ed25519", - "x": "VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ", - "kty": "OKP", - "kid": "_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A" - } - }, - // This could be a recovery key for when the party loses its private key, - // residing on a hardtoken (e.g. a Yubikey in a safe). - { - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-2", - "type": "JsonWebKey2020", - "controller": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", - "publicKeyJwk": { - "kty": "OKP", - "crv": "Ed25519", - "x": "VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ" - } - } - ], - // Keys specified in the section below are used to authenticate as DID controller. In other words; - // keys specified below can alter this DID document. - // Entries MUST NOT contain embedded key material and all MUST reference keys containing in the verificationMethod - "authentication": [ - // Key used by the party to control this document (e.g. alter services) - "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1", - // Recovery key (e.g. hardtoken) - "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-2" - ], - // `assertionMethod` indicates the keys used when signing Verifiable Credentials (VC). Examples use cases: - // - Vendor issuing a VC to care organization stating "this is my client" - // - Care organization issuing a VC stating "this is my software vendor" - // TODO: discuss these use cases and specify - "assertionMethod": [ - "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#key-1" - ], - // `service` indicate high-level - "service": [ - { - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-1", - // must be the same type as the type in the vendor service - "type": "nuts:bolt:eoverdracht", - "serviceEndpoint": "did:nuts:#service-76" - }, - { - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-2", - // must be the same type as the type in the vendor service - "type": "nuts:core:consent", - "serviceEndpoint": "did:nuts:#service-2" - } - ] -} -``` \ No newline at end of file diff --git a/examples/organisation-did.md b/examples/organisation-did.md deleted file mode 100644 index 588ae74..0000000 --- a/examples/organisation-did.md +++ /dev/null @@ -1,26 +0,0 @@ -The example below expands on the generic Nuts DID and describes a DID Document for a care organization: - -```json -{ - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff", - "service": [ - { - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-1", - // must be the same type as the type in the vendor service - "type": "nuts:bolt:eoverdracht", - "serviceEndpoint": "did:nuts:#service-76" - }, - { - "id": "did:nuts:04cf1e20-378a-4e38-ab1b-401a5018c9ff#service-2", - // must be the same type as the type in the vendor service - "type": "nuts:core:consent", - "serviceEndpoint": "did:nuts:#service-2" - } - ], - "created": "2019-03-23T06:35:22Z", - "updated": "2020-08-10T13:40:06Z" -} -``` \ No newline at end of file diff --git a/examples/vendor-did.md b/examples/vendor-did.md deleted file mode 100644 index 7642385..0000000 --- a/examples/vendor-did.md +++ /dev/null @@ -1,37 +0,0 @@ -The example below expands on the generic Nuts DID and describes a DID Document for a vendor: - -```json -{ - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266", - "service": [ - { - "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-1", - "type": "nuts:core:oauth", - "version": "1.0", - "serviceEndpoint": "https://api.example.org/oauth" - }, - { - "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-2", - "type": "nuts:core:consent", - "version": "1.0", - "serviceEndpoint": "https://corda.example.org/" - }, - { - "id": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-76", - // Specifies the type of the service, generally a Nuts Bolt. If a care organization refers to this service, - // it must specifiy the same type (`nuts:bolt:eoverdracht` in this case). - "type": "nuts:bolt:eoverdracht", - "version": "1.0", - "serviceEndpoint": { - "data": "https://api.example.org/fhir/", - "auth": "did:nuts:6181aab9-549b-4143-b215-5d77bf9eb266#service-1" - } - } - ], - "created": "2019-03-23T06:35:22Z", - "updated": "2020-08-10T13:40:06Z" -} -``` \ No newline at end of file diff --git a/rfc/rfc003-oauth2-authorization.md b/rfc/rfc003-oauth2-authorization.md index e345977..634549b 100644 --- a/rfc/rfc003-oauth2-authorization.md +++ b/rfc/rfc003-oauth2-authorization.md @@ -69,17 +69,10 @@ When requesting data, the client application MUST add the access token to the Au In common OAuth2 flows an OAuth client must be registered with the authorization server with its client id and client secret. This way the authorization server knows which requests are made by which party. The registration normally involves manual steps of registering and approving. In a network of trust with countless combinations of authorization servers and clients, this approach does not scale well. -<<<<<<< HEAD -So instead of client secrets, the Nuts OAuth flow binds the request via the JWT using its signature to a known care provider. The key used to sign the JWT is identified by a key identifier (`kid`) which can be resolved from the Nuts registry as defined in [RFC006]. -The key MUST be listed in the `assertion` section of the actor DID document. The actor is identified by the `iss` field. - -Example of the actors DID document: -======= So instead of client secrets, the Nuts OAuth flow binds the request via the JWT using its signature to a known care provider. The key used to sign the JWT is identified by a key identifier (`kid`) which can be resolved through the Nuts registry as defined in [RFC006](rfc006-distributed-registry.md). The key MUST be listed in the `assertionMethod` section of the actor's DID document. The actor is identified by the `iss` field of the JWT. Example of the actor's DID document: ->>>>>>> master ```json { "@context": [ "https://www.w3.org/ns/did/v1" ], diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index 35a3aeb..aa07be9 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -545,6 +545,3 @@ This example is the most simple, there's one key and it's used for all cases. "service": [] } ``` - -### Resolvability of the DID document -The fundamental idea of a DID document is that it should be resolvable by other parties. Section [7.2.2 of the did-core spec](https://w3c.github.io/did-core/#read-verify) requires a specification how a DID resolver could resolve and verify a DID document from the registry. Since the Nuts registry will be a local registry this is not yet a consideration but when federation with other registries will become relevant, a proper specification should be written. \ No newline at end of file From c9847533e1381f48ac103b16fef081b13a5b427f Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Wed, 13 Jan 2021 09:52:33 +0100 Subject: [PATCH 18/21] removed too much --- examples/care-organization-vc.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/care-organization-vc.md diff --git a/examples/care-organization-vc.md b/examples/care-organization-vc.md new file mode 100644 index 0000000..9875750 --- /dev/null +++ b/examples/care-organization-vc.md @@ -0,0 +1,27 @@ +```json +{ + "@context": ["https://www.w3.org/2018/credentials/v1"], + // specify the identifier for the credential + "id": "did:nuts:123/credentials/1", + "type": ["VerifiableCredential", "NutsNameCredential"], + "issuer": "did:nuts:123", + "issuanceDate": "2010-01-01T19:73:24Z", + "credentialSubject": { + // identifier for the only subject of the credential + "id": "did:nuts:123", + "name": "Verpleegtehuis de nootjes", + "locality": "Groenlo" + }, + "proof": { + "type": "RsaSignature2018", + "created": "2017-06-18T21:19:10Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:nuts:1#key-1", + // the digital signature value containing all of the above + "jws": "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..TCYt5X + sITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5WEuts01mq-pQy7UJiN5mgRxD-WUc + X16dUEMGlv50aqzpqh4Qktb3rk-BuQy72IFLOqV0G_zS245-kronKb78cPN25DGlcTwLtj + PAYuNzVBAh4vGHSrQyHUdBBPM" + } +} +``` \ No newline at end of file From 88a523f5567170a45893944cfdb5b216afdfeb49 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Wed, 13 Jan 2021 09:53:15 +0100 Subject: [PATCH 19/21] unneeded change --- rfc/rfc006-distributed-registry.md | 1 + 1 file changed, 1 insertion(+) diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index aa07be9..315add5 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -545,3 +545,4 @@ This example is the most simple, there's one key and it's used for all cases. "service": [] } ``` + From 8c408d0901723ef5d7b40beaf2c9a1468d6e5cd6 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Fri, 29 Jan 2021 10:46:56 +0100 Subject: [PATCH 20/21] PR feedback --- rfc/rfc006-distributed-registry.md | 1 - rfc/rfc010-multiple-operators.md | 19 ++++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/rfc/rfc006-distributed-registry.md b/rfc/rfc006-distributed-registry.md index 315add5..aa07be9 100644 --- a/rfc/rfc006-distributed-registry.md +++ b/rfc/rfc006-distributed-registry.md @@ -545,4 +545,3 @@ This example is the most simple, there's one key and it's used for all cases. "service": [] } ``` - diff --git a/rfc/rfc010-multiple-operators.md b/rfc/rfc010-multiple-operators.md index 1c58af3..eb3835f 100644 --- a/rfc/rfc010-multiple-operators.md +++ b/rfc/rfc010-multiple-operators.md @@ -9,7 +9,7 @@ ## Multiple operator service access ### Abstract -This RFC describes an addition to [RFC003](rfc003-oauth2-auithorization.md) and [RFC006](rfc006-distributed-registry.md) on how to handle resource access when a legal party has multiple node operators. This is the case when a care organization uses multiple pieces of software from different SaaS providers. A SaaS provider can alter the care organization DID document so the DID document of the other provider is added as synonym. This is done by using the *also-known-as* relation. +This RFC describes an addition to [RFC003](rfc003-oauth2-auithorization.md) and [RFC006](rfc006-distributed-registry.md) on how to handle resource access when a legal party has multiple SaaS providers. A SaaS provider can alter the care organization DID document so the DID document of the other provider is added as synonym. This is done by using the *also-known-as* property. ### Status @@ -22,7 +22,7 @@ This document is released under the [Attribution-ShareAlike 4.0 International \( ## 1. Introduction -Care organizations rarely use one piece of software. Larger organizations can use up to a hundred different pieces of software. Every software vendor that has signed a **Data Processing Agreement** with the care organization is allowed to transfer data to any other software vendor within the limits of the **Data Processing Agreement**. +Care organizations rarely rely on the services of one software vendor. Every software vendor that has signed a **Data Processing Agreement** with the care organization is allowed to transfer data to any other software vendor within the limits of the **Data Processing Agreement**. To support this functionality, some registration and extended validation is required throughout the process of data transfer. @@ -31,12 +31,21 @@ To support this functionality, some registration and extended validation is requ * **Bolt**: a use case built on top of the functionality Nuts provides. * **DID**: a decentralized identifier according to the [core-did-spec](https://www.w3.org/TR/did-core). * **DPA**: Data Processing Agreement as defined by the GDPR. +* **GDPR**: General Data Protection Regulation (https://eur-lex.europa.eu/eli/reg/2016/679/oj). +* **SaaS provider**: Party operating a Nuts node as a service on behalf of their clients (care organizations). + +The term *subject* in the context of a SaaS provider can be substituted for *Care organization*. Other terminology is taken from the [Nuts Start Architecture](rfc001-nuts-start-architecture.md#nuts-start-architecture). ## 3. Registration -Each care organization that is registered at a node by a SaaS provider will have its own DID document. If a care organization uses 2 SaaS providers, it'll have two different DID documents. Since identification within the OAuth flow is done by DID, the DID subject need to be aware of each other. This can be done by adding the DID of one document and add it to the other. This is done by using the `alsoKnownAs` field defined in the [core-did-spec](https://www.w3.org/TR/did-core/#also-known-as). +DID Documents define public keys which the SaaS provider controls. SaaS providers must not share private keys, +thus each subject that is registered at a node by a SaaS provider will have its own DID document. +If a subject uses 2 SaaS providers, it'll have two different DID documents. +Since identification of the subject within the OAuth flow is done via DID, the subjects need to be aware of each other. +This can be done by having the DID documents of the SaaS providers refer to each other. +This is done by using the `alsoKnownAs` field defined in the [core-did-spec](https://www.w3.org/TR/did-core/#also-known-as). Example: @@ -55,10 +64,10 @@ The controller of the DID document MUST verify that it added the correct DID in ## 4. Authentication -As defined in point 3 in [§6.2 of RFC003](rfc003-oauth2-auithorization.md#6-2-authorization), if the actor and custodian are the same, access is granted. If a custodian had added an actor in their DID document under the `alsoKnownAs` field, it MUST grant access as defined by point 3 in §6.2 of RFC003. Bolts MUST describe what resources may be accessed in this way and if user context is required. +As defined in point 3 in [§6.2 of RFC003](rfc003-oauth2-auithorization.md#6-2-authorization), if the actor and custodian are the same, access is granted. If a custodian has added an actor in their DID document under the `alsoKnownAs` field, it MUST grant access as defined by point 3 in §6.2 of RFC003. Bolts MUST describe what resources may be accessed in this way and if user context is required. If nothing is described, resources SHOULD NOT be accessible. ## 5. Hijacked DID documents A DID subject that is added under the `alsoKnownAs` field is granted access to resources from the custodian. In the case when the private key of the actor is compromised and the attacker is changing keys, the custodian SHOULD take appropriate action. -The node operator MUST remove a DID from the `alsoKnownAs` field when the `authentication` or `controller` field changes in the referenced DID document. \ No newline at end of file +The node MUST remove a DID from the `alsoKnownAs` field when the `authentication` or `controller` field changes in the referenced DID document. \ No newline at end of file From bc5c2c377ddc7553d2c2d72b6005fedc1a0adf65 Mon Sep 17 00:00:00 2001 From: Wout Slakhorst Date: Fri, 29 Jan 2021 10:58:59 +0100 Subject: [PATCH 21/21] altered abstract --- rfc/rfc010-multiple-operators.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/rfc/rfc010-multiple-operators.md b/rfc/rfc010-multiple-operators.md index eb3835f..649bd62 100644 --- a/rfc/rfc010-multiple-operators.md +++ b/rfc/rfc010-multiple-operators.md @@ -9,7 +9,15 @@ ## Multiple operator service access ### Abstract -This RFC describes an addition to [RFC003](rfc003-oauth2-auithorization.md) and [RFC006](rfc006-distributed-registry.md) on how to handle resource access when a legal party has multiple SaaS providers. A SaaS provider can alter the care organization DID document so the DID document of the other provider is added as synonym. This is done by using the *also-known-as* property. +This RFC describes an addition to [RFC003](rfc003-oauth2-auithorization.md) and [RFC006](rfc006-distributed-registry.md) on how to handle resource access when a DID Subject has multiple DID Documents. +A controller of the DID Document can add DIDs as synonyms. This is done by using the *also-known-as* property. +DIDs under the *also-known-as* property represent the same DID Subject. +When DID Subjects define the same legal entity, they should be able to transfer data freely. + +For example: a care organization may use the services of two different SaaS providers. +Both SaaS providers have signed a data processing agreement with the care organization. +Both SaaS providers are allowed to process data for the care organization within the DPA context. +The DPA forms the legal base on which data may be transfered between the SaaS providers. ### Status