From 8df91e5437b923f10c8a27d7d9562ccf37e15a4b Mon Sep 17 00:00:00 2001 From: Eric Scouten Date: Tue, 5 Mar 2024 18:33:32 -0800 Subject: [PATCH 1/2] npm install spec-up --- package-lock.json | 75 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 76 insertions(+) diff --git a/package-lock.json b/package-lock.json index 94525a2..59d82dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "merge-stream": "2.0.0", "pkg-dir": "4.2.0", "prismjs": ">=1.24.0", + "spec-up": "^0.10.6", "yargs": "16.2.0" } }, @@ -3567,6 +3568,43 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" }, + "node_modules/spec-up": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/spec-up/-/spec-up-0.10.6.tgz", + "integrity": "sha512-lut8YJXdL1vcpU/BCZO1oBNbj07Lf3bfwXQ2xUsqQ/ihY5dJqSerBxIUjoXkMRVujLW0vnAp56LCAv8xaEer2Q==", + "dependencies": { + "@traptitech/markdown-it-katex": "3.3.0", + "axios": "0.21.2", + "find-pkg-dir": "2.0.0", + "fs-extra": "8.1.0", + "gulp": "4.0.2", + "gulp-clean-css": "4.3.0", + "gulp-concat": "2.6.1", + "gulp-terser": "1.2.0", + "markdown-it": "13.0.1", + "markdown-it-anchor": "5.2.5", + "markdown-it-attrs": "4.1.4", + "markdown-it-chart": "^0.2.0", + "markdown-it-container": "^2.0.0", + "markdown-it-deflist": "^2.1.0", + "markdown-it-icons": "^0.4.1", + "markdown-it-ins": "^2.0.0", + "markdown-it-mark": "^2.0.0", + "markdown-it-modify-token": "1.0.2", + "markdown-it-multimd-table": "^4.1.3", + "markdown-it-prism": "^2.2.0", + "markdown-it-references": "1.0.0-alpha.10", + "markdown-it-sub": "^1.0.0", + "markdown-it-sup": "^1.0.0", + "markdown-it-task-lists": "2.1.1", + "markdown-it-textual-uml": "0.1.3", + "markdown-it-toc-and-anchor": "4.2.0", + "merge-stream": "2.0.0", + "pkg-dir": "4.2.0", + "prismjs": ">=1.24.0", + "yargs": "16.2.0" + } + }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -7094,6 +7132,43 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" }, + "spec-up": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/spec-up/-/spec-up-0.10.6.tgz", + "integrity": "sha512-lut8YJXdL1vcpU/BCZO1oBNbj07Lf3bfwXQ2xUsqQ/ihY5dJqSerBxIUjoXkMRVujLW0vnAp56LCAv8xaEer2Q==", + "requires": { + "@traptitech/markdown-it-katex": "3.3.0", + "axios": "0.21.2", + "find-pkg-dir": "2.0.0", + "fs-extra": "8.1.0", + "gulp": "4.0.2", + "gulp-clean-css": "4.3.0", + "gulp-concat": "2.6.1", + "gulp-terser": "1.2.0", + "markdown-it": "13.0.1", + "markdown-it-anchor": "5.2.5", + "markdown-it-attrs": "4.1.4", + "markdown-it-chart": "^0.2.0", + "markdown-it-container": "^2.0.0", + "markdown-it-deflist": "^2.1.0", + "markdown-it-icons": "^0.4.1", + "markdown-it-ins": "^2.0.0", + "markdown-it-mark": "^2.0.0", + "markdown-it-modify-token": "1.0.2", + "markdown-it-multimd-table": "^4.1.3", + "markdown-it-prism": "^2.2.0", + "markdown-it-references": "1.0.0-alpha.10", + "markdown-it-sub": "^1.0.0", + "markdown-it-sup": "^1.0.0", + "markdown-it-task-lists": "2.1.1", + "markdown-it-textual-uml": "0.1.3", + "markdown-it-toc-and-anchor": "4.2.0", + "merge-stream": "2.0.0", + "pkg-dir": "4.2.0", + "prismjs": ">=1.24.0", + "yargs": "16.2.0" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", diff --git a/package.json b/package.json index f3d8561..9481f22 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "merge-stream": "2.0.0", "pkg-dir": "4.2.0", "prismjs": ">=1.24.0", + "spec-up": "^0.10.6", "yargs": "16.2.0" } } From 14c973f20b9b8297cf4b033f8f40f99e0eb89b7b Mon Sep 17 00:00:00 2001 From: Eric Scouten Date: Tue, 5 Mar 2024 19:11:19 -0800 Subject: [PATCH 2/2] Convert MSFT draft did:x509 specification to Spec-Up format Compare to https://github.com/microsoft/did-x509/blob/main/specification.md --- spec/annex.md | 14 --- spec/biblio.md | 6 - spec/clauses.md | 86 --------------- spec/did_resolution_options.md | 13 +++ spec/example.md | 5 + spec/header.md | 9 +- spec/identifier_syntax.md | 193 +++++++++++++++++++++++++++++++++ spec/introduction.md | 9 +- spec/json_data_model.md | 57 ++++++++++ spec/normative_references.md | 11 -- spec/operations.md | 84 ++++++++++++++ spec/references.md | 29 +++++ spec/security_privacy.md | 15 +++ spec/terms_and_definitions.md | 8 -- spec/title.md | 12 +- specs.json | 12 +- 16 files changed, 425 insertions(+), 138 deletions(-) delete mode 100644 spec/annex.md delete mode 100644 spec/biblio.md delete mode 100644 spec/clauses.md create mode 100644 spec/did_resolution_options.md create mode 100644 spec/example.md create mode 100644 spec/identifier_syntax.md create mode 100644 spec/json_data_model.md delete mode 100644 spec/normative_references.md create mode 100644 spec/operations.md create mode 100644 spec/references.md create mode 100644 spec/security_privacy.md delete mode 100644 spec/terms_and_definitions.md diff --git a/spec/annex.md b/spec/annex.md deleted file mode 100644 index f948cfe..0000000 --- a/spec/annex.md +++ /dev/null @@ -1,14 +0,0 @@ - -[//]: # (Pandoc Formatting Macros) - -[//]: # (# This is an annex {#sec:annexA .normative}) - -[//]: # (With some text) - -[//]: # (# This is another annex {#sec:annexB .informative}) - -[//]: # (With some more text) - -## Annex - -Annex content \ No newline at end of file diff --git a/spec/biblio.md b/spec/biblio.md deleted file mode 100644 index 0a03540..0000000 --- a/spec/biblio.md +++ /dev/null @@ -1,6 +0,0 @@ - -[//]: # (Pandoc Formatting Macros) - -[//]: # (\newpage) - -[//]: # (\makebibliography) diff --git a/spec/clauses.md b/spec/clauses.md deleted file mode 100644 index 3f0a849..0000000 --- a/spec/clauses.md +++ /dev/null @@ -1,86 +0,0 @@ - - -[//]: # (Pandoc Formatting Macros) - -[//]: # (Main content {#sec:content}) - -## Executive Summary -CoLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Scelerisque fermentum dui faucibus in ornare quam viverra orci. Maecenas ultricies mi eget mauris pharetra. Tempor nec feugiat nisl pretium fusce id. In ante metus dictum at tempor commodo ullamcorper a. Nulla at volutpat diam ut venenatis tellus in. - -Quis hendrerit dolor magna eget est lorem ipsum dolor. Cursus metus aliquam eleifend mi in. Volutpat commodo sed egestas egestas fringilla phasellus. Viverra adipiscing at in tellus integer feugiat scelerisque varius. Arcu bibendum at varius vel pharetra. Dictum at tempor commodo ullamcorper. Eu consequat ac felis donec et odio pellentesque diam volutpat. Pretium quam vulputate dignissim suspendisse in est. Et pharetra pharetra massa massa ultricies mi quis hendrerit dolor. Dolor morbi non arcu risus quis varius. - -Maecenas volutpat blandit aliquam etiam erat velit. Quis imperdiet massa tincidunt nunc pulvinar. Placerat vestibulum lectus mauris ultrices eros in cursus turpis massa. Sodales ut etiam sit amet. Orci nulla pellentesque dignissim enim sit amet venenatis. Fusce ut placerat orci nulla pellentesque dignissim enim sit. Sollicitudin ac orci phasellus egestas tellus rutrum tellus. Enim eu turpis egestas pretium aenean pharetra magna ac placerat. Et malesuada fames ac turpis egestas. Integer quis auctor elit sed vulputate. Massa tempor nec feugiat nisl pretium. - ------------------------------------- - -## Heading 1 - -CoLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Scelerisque fermentum - -### Heading 2 - -CoLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Scelerisque fermentum dui faucibus in ornare quam viverra orci. Maecenas ultricies mi eget mauris pharetra. Tempor nec feugiat nisl pretium fusce id. In ante metus dictum at tempor commodo ullamcorper a. Nulla at volutpat diam ut venenatis tellus in. - -Quis hendrerit dolor magna eget est lorem ipsum dolor. Cursus metus aliquam eleifend mi in. Volutpat commodo sed egestas egestas fringilla phasellus. Viverra adipiscing at in tellus integer feugiat scelerisque varius. Arcu bibendum at varius vel pharetra. Dictum at tempor commodo ullamcorper. Eu consequat ac felis donec et odio pellentesque diam volutpat. Pretium quam vulputate dignissim suspendisse in est. Et pharetra pharetra massa massa ultricies mi quis hendrerit dolor. Dolor morbi non arcu risus quis varius. - - -### Heading 2 - -This section describes key concepts used in the content of the document. If the concept requires a footnote, one should be inserted as follows: Any defined term should be hyperlinked to its glossary definition (or at least bolded). - -## Heading 1 - -Quis hendrerit dolor magna eget est lorem ipsum dolor. Cursus metus aliquam eleifend mi in. Volutpat commodo sed egestas egestas fringilla phasellus. Viverra adipiscing at in tellus integer feugiat scelerisque varius. Arcu bibendum at varius vel pharetra. Dictum at tempor commodo ullamcorper. Eu consequat ac felis donec et odio pellentesque diam volutpat. Pretium quam vulputate dignissim suspendisse in est. Et pharetra pharetra massa massa ultricies mi quis hendrerit dolor. Dolor morbi non arcu risus quis varius. - -### Heading 2 - -Eu consequat ac felis donec et odio pellentesque diam volutpat. Pretium quam vulputate dignissim suspendisse in est. Et pharetra pharetra massa massa ultricies mi quis hendrerit dolor. Dolor morbi non arcu risus quis varius. - - -#### Heading 3 - -CoLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Scelerisque fermentum dui faucibus in ornare quam viverra orci. Maecenas ultricies mi eget mauris pharetra. Tempor nec feugiat nisl pretium fusce id. In ante metus dictum at tempor commodo ullamcorper a. Nulla at volutpat diam ut venenatis tellus in. - -##### Heading 4 - -Sodales ut etiam sit amet. Orci nulla pellentesque dignissim enim sit amet venenatis. Fusce ut placerat orci nulla pellentesque dignissim enim sit. Sollicitudin ac orci phasellus egestas tellus rutrum tellus. Enim eu turpis egestas pretium aenean pharetra magna ac placerat. Et malesuada fames ac turpis egestas. Integer quis auctor elit sed vulputate. Massa tempor nec feugiat nisl pretium. - -## Figures, Bullets and Numbered Lists - -### Figure - -Arcu bibendum at varius vel pharetra. Dictum at tempor commodo ullamcorper. Eu consequat ac felis donec et odio pellentesque diam volutpat. Pretium quam vulputate dignissim suspendisse in est. Et pharetra pharetra massa massa ultricies mi quis hendrerit dolor. Dolor morbi non arcu risus quis varius - - -[image]: image.png "Image Title" -![Alt text][image] -A reference to the [image](#image). - -### Figure 1. Mi ipsum faucibus vitae - - -### Lists - -Eu consequat ac felis donec et odio pellentesque diam volutpat: - -1. Establish Magna - 1. Dictum at tempor commodo - 1. Volutpat commodo sed, - 1. Cursus metus aliquam eleifend. - - -- Identify Bibendum, - - Analyze Donec, - - Treat Fringilla, - -### Quote - -The following is a quote from a referenced source: - -> This is a quote from an author in a paper that provides invaluable insight into the subject of this ToIP document. Be sure to include a reference to the source. - -### Conclusion - -CoLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Scelerisque fermentum dui faucibus in ornare quam viverra orci. Maecenas ultricies mi eget mauris pharetra. Tempor nec feugiat nisl pretium fusce id. In ante metus dictum at tempor commodo ullamcorper a. Nulla at volutpat diam ut venenatis tellus in. - -- This section seems incorrectly indented: https://github.com/trustoverip/tswg-did-x509-method-specification/issues/1 diff --git a/spec/did_resolution_options.md b/spec/did_resolution_options.md new file mode 100644 index 0000000..604b00e --- /dev/null +++ b/spec/did_resolution_options.md @@ -0,0 +1,13 @@ +## DID resolution options + +This DID method introduces a new DID resolution option called `x509chain`: + +Name: `x509chain` + +Value type: string + +The value is constructed as follows: + +1. Encode each certificate `C` that is part of the chain as the string `b64url(DER(C))`. + +2. Concatenate the resulting strings in order, separated by comma `","`. diff --git a/spec/example.md b/spec/example.md new file mode 100644 index 0000000..cea0eeb --- /dev/null +++ b/spec/example.md @@ -0,0 +1,5 @@ +## Example + +`did:x509:0:sha256:WE4P5dd8DnLHSkyHaIjhp4udlkF9LqoKwCvu9gl38jk::subject:C:US:ST:California:O:My%20Organisation` + +In this example, the identifier pins to a certificate authority using the SHA-256 certificate hash and uses the `subject` policy to express criteria which a leaf certificate's subject must fulfill. This identifier will match any certificate chains with matching leaf certificate subject fields and a matching intermediate or root CA certificate. diff --git a/spec/header.md b/spec/header.md index a0141e4..e620a19 100644 --- a/spec/header.md +++ b/spec/header.md @@ -1,6 +1,6 @@ ## Status of This Memo -This document contains a template specification for `ToIP`!. +This document contains a working draft for the specification for the `did:x509` DID method. Information about the current status of this document, any errata, and how to provide feedback on it, may be obtained at @@ -19,7 +19,6 @@ and the designated source code license, the terms of the OWF Contributor License These terms are inherited from the Technical Stack Working Group at the Trust over IP Foundation. [Working Group Charter](https://trustoverip.org/wp-content/uploads/TSWG-2-Charter-Revision.pdf) - ## Terms of Use These materials are made available under and are subject to the [OWF CLA 1.0 - Copyright & Patent license](https://www.openwebfoundation.org/the-agreements/the-owf-1-0-agreements-granted-claims/owf-contributor-license-agreement-1-0-copyright-and-patent). Any source code is made available under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt). @@ -28,12 +27,14 @@ THESE MATERIALS ARE PROVIDED “AS IS.” The Trust Over IP Foundation, establis IN NO EVENT WILL ANY ToIP PARTY BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THESE MATERIALS, ANY DELIVERABLE OR THE ToIP GOVERNING AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## RFC 2119 + The Internet Engineering Task Force (IETF) is a large open international community of network designers, operators, vendors, and researchers concerned with the evolution of the Internet architecture and to ensure maximal efficiency in operation. IETF has been operating since the advent of the Internet using a Request for Comments (RFC) to convey “current best practice” to those organizations seeking its guidance for conformance purposes. -The IETF uses RFC 2119 to define keywords for use in RFC documents; these keywords are used to signify applicability requirements. ToIP has adapted the IETF RFC 2119 for use in the , and therefore its applicable use in ToIP-compliant governance frameworks. +The IETF uses RFC 2119 to define keywords for use in RFC documents; these keywords are used to signify applicability requirements. ToIP has adapted the IETF RFC 2119 for use in the `did:x509` Method Specification, and therefore its applicable use in ToIP-compliant governance frameworks. The RFC 2119 keyword definitions and interpretation have been adopted. Those users who follow these guidelines SHOULD incorporate the following phrase near the beginning of their document: - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. + +> The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. RFC 2119 defines these keywords as follows: diff --git a/spec/identifier_syntax.md b/spec/identifier_syntax.md new file mode 100644 index 0000000..ca90e66 --- /dev/null +++ b/spec/identifier_syntax.md @@ -0,0 +1,193 @@ +## Identifier Syntax + +The `did:x509` ABNF definition can be found below, which uses the syntax in [RFC 5234](https://www.rfc-editor.org/rfc/rfc5234.html) and the corresponding definitions for `ALPHA` and `DIGIT`. The [W3C DID v1.0 specification](https://www.w3.org/TR/2022/REC-did-core-20220719/) contains the definition for `idchar`. + +```abnf +did-x509 = "did:" method-name ":" method-specific-id +method-name = "x509" +method-specific-id = version ":" ca-fingerprint-alg ":" ca-fingerprint 1*("::" policy-name ":" policy-value) +version = 1*DIGIT +ca-fingerprint-alg = "sha256" / "sha384" / "sha512" +ca-fingerprint = base64url +policy-name = 1*ALPHA +policy-value = *(1*idchar ":") 1*idchar +base64url = 1*(ALPHA / DIGIT / "-" / "_") +``` + +In this draft, version is `0`. + +`ca-fingerprint-alg` is one of `sha256`, `sha384`, or `sha512`. + +`ca-fingerprint` is `chain[i].fingerprint[ca-fingerprint-alg]` with i > 0, that is, either an intermediate or root CA certificate. + +`policy-name` is a policy name and `policy-value` is a policy-specific value. + +`::` is used to separate multiple policies from each other. + +The following sections define the policies and their policy-specific syntax. + +Validation of policies is formally defined using [Rego policies](https://www.openpolicyagent.org/docs/latest/policy-language/), though there is no expectation that implementations use Rego. + +The input to the Rego engine is the JSON document `{"did": "", "chain": }`. + +Core Rego policy: + +```rego +import future.keywords.if +import future.keywords.in + +parse_did(did) := [ca_fingerprint_alg, ca_fingerprint, policies] if { + prefix := "did:x509:0:" + startswith(did, prefix) == true + rest := trim_prefix(did, prefix) + parts := split(rest, "::") + [ca_fingerprint_alg, ca_fingerprint] := split(parts[0], ":") + policies_raw := array.slice(parts, 1, count(parts)) + policies := [y | + some i + s := policies_raw[i] + j := indexof(s, ":") + y := [substring(s, 0, j), substring(s, j+1, -1)] + ] +} + +valid if { + [ca_fingerprint_alg, ca_fingerprint, policies] := parse_did(input.did) + ca := [c | some i; i != 0; c := input.chain[i]] + ca[_].fingerprint[ca_fingerprint_alg] == ca_fingerprint + valid_policies := [i | + some i + [name, value] := policies[i] + validate_policy(name, value) + ] + count(valid_policies) == count(policies) +} +``` + +The overall Rego policy is assembled by concatenating the core Rego policy with the Rego policy fragments in the following sections, each one defining a `validate_policy` function. + +### Percent-encoding + +Some of the policies that are defined in subsequent sections require values to be percent-encoded. Percent-encoding is specified in [RFC 3986 Section 2.1](https://www.rfc-editor.org/rfc/rfc3986#section-2.1). All characters that are not in the allowed set defined below must be percent-encoded: + +```abnf +allowed = ALPHA / DIGIT / "-" / "." / "_" +``` + +Note that most libraries implement percent-encoding in the context of URLs and do NOT encode `~` (`%7E`). + +### `subject` policy + +```abnf +policy-name = "subject" +policy-value = key ":" value *(":" key ":" value) +key = label / oid +value = 1*idchar +label = "CN" / "L" / "ST" / "O" / "OU" / "C" / "STREET" +oid = 1*DIGIT *("." 1*DIGIT) +``` + +`:` are the subject name fields in `chain[0].subject` in any order. Field repetitions are not allowed. Values must be percent-encoded. + +Example: + +`did:x509:0:sha256:WE4P5dd8DnLHSkyHaIjhp4udlkF9LqoKwCvu9gl38jk::subject:C:US:ST:California:L:San%20Francisco:O:GitHub%2C%20Inc.` + +Rego policy: +```rego +validate_policy(name, value) := true if { + name == "subject" + items := split(value, ":") + count(items) % 2 == 0 + subject := {k: v | + some i + i % 2 == 0 + k := items[i] + v := urlquery.decode(items[i+1]) + } + count(subject) >= 1 + object.subset(input.chain[0].subject, subject) == true +} +``` + +### `san` policy + +```abnf +policy-name = "san" +policy-value = san-type ":" san-value +san-type = "email" / "dns" / "uri" +san-value = 1*idchar +``` + +`san-type` is the SAN type and must be one of `email`, `dns`, or `uri`. Note that `dn` is not supported. + +`san-value` is the SAN value, percent-encoded. + +The pair [``, ``] is one of the items in `chain[0].extensions.san`. + +Example: + +`did:x509:0:sha256:WE4P5dd8DnLHSkyHaIjhp4udlkF9LqoKwCvu9gl38jk::san:email:bob%40example.com` + +Rego policy: + +```rego +validate_policy(name, value) := true if { + name == "san" + [san_type, san_value_encoded] := split(value, ":") + san_value := urlquery.decode(san_value_encoded) + [san_type, san_value] == input.chain[0].extensions.san[_] +} +``` + +### `eku` policy + +```abnf +policy-name = "eku" +policy-value = eku +eku = oid +oid = 1*DIGIT *("." 1*DIGIT) +``` + +`eku` is one of the OIDs within `chain[0].extensions.eku`. + +Example: + +`did:x509:0:sha256:WE4P5dd8DnLHSkyHaIjhp4udlkF9LqoKwCvu9gl38jk::eku:1.3.6.1.4.1.311.10.3.13` + +Rego policy: + +```rego +validate_policy(name, value) := true if { + name == "eku" + value == input.chain[0].extensions.eku[_] +} +``` + +### `fulcio-issuer` policy + +```abnf +policy-name = "fulcio-issuer" +policy-value = fulcio-issuer +fulcio-issuer = 1*idchar +``` + +`fulcio-issuer` is `chain[0].extensions.fulcio_issuer` without leading `https://`, percent-encoded. + +Example: + +`did:x509:0:sha256:WE4P5dd8DnLHSkyHaIjhp4udlkF9LqoKwCvu9gl38jk::fulcio-issuer:accounts.google.com::san:email:bob%40example.com` + +Example 2: + +`did:x509:0:sha256:WE4P5dd8DnLHSkyHaIjhp4udlkF9LqoKwCvu9gl38jk::fulcio-issuer:token.actions.githubusercontent.com::san:uri:https%3A%2F%2Fgithub.com%2Focto-org%2Focto-automation%2F.github%2Fworkflows%2Foidc.yml%40refs%2Fheads%2Fmain` + +Rego policy: + +```rego +validate_policy(name, value) := true if { + name == "fulcio-issuer" + suffix := urlquery.decode(value) + concat("", ["https://", suffix]) == input.chain[0].extensions.fulcio_issuer +} +``` diff --git a/spec/introduction.md b/spec/introduction.md index 9fc282f..0ecfdd2 100644 --- a/spec/introduction.md +++ b/spec/introduction.md @@ -1,4 +1,3 @@ - [//]: # (Pandoc Formatting Macros) [//]: # (::: introtitle) @@ -9,4 +8,10 @@ ## Introduction -Fancy introduction! \ No newline at end of file +The RWOT11 workshop outlined the need for hybrid solutions that combine X.509 certificates with DIDs: ["Analysis of hybrid wallet solutions - Implementation options for combining x509 certificates with DIDs and VCs"](https://github.com/WebOfTrustInfo/rwot11-the-hague/blob/master/advance-readings/hybrid_wallet_solutions_x509_DIDs_VCs.md). + +The `did:x509` method takes a simple approach that does not introduce additional infrastructure. Creating and resolving a `did:x509` is a local operation. It relies on X.509 chain validation and matches elements contained in the DID to certificate properties within the chain. + +The main difference to other DID methods is that `did:x509` requires a certificate chain to be passed using a new [DID resolution option](https://www.w3.org/TR/did-core/#did-resolution-options) `x509chain` while resolving a DID. This certificate chain is typically embedded in the signing envelope, for example within the `x5c` header parameter of JWS/JWT documents. + +This work is derived from a draft `did:x509` method specification published by Maik Riechert and Antoine Delignat-Lavaud of Microsoft which is published here: https://github.com/microsoft/did-x509. diff --git a/spec/json_data_model.md b/spec/json_data_model.md new file mode 100644 index 0000000..e599f90 --- /dev/null +++ b/spec/json_data_model.md @@ -0,0 +1,57 @@ +## JSON data model for X.509 certificate chains + +This section defines a JSON data model for X.509 certificate chains that is the basis for evaluating whether a certificate chain matches a given `did:x509` identifier. The language used for defining the JSON data model is CDDL ([RFC 8610](https://www.rfc-editor.org/rfc/rfc8610)). + +```cddl +CertificateChain = [2*Certificate] ; leaf is first + +Certificate = { + fingerprint: { + ; base64url-encoded hashes of the DER-encoded certificate + sha256: base64url, ; FIPS 180-4, SHA-256 + sha384: base64url, ; FIPS 180-4, SHA-384 + sha512: base64url ; FIPS 180-4, SHA-512 + }, + issuer: Name, ; RFC 5280, Section 4.1.2.4 + subject: Name, ; RFC 5280, Section 4.1.2.6 + extensions: { + ? eku: [+OID], ; RFC 5280, Section 4.2.1.12 + ? san: [+SAN], ; RFC 5280, Section 4.2.1.6 + ? fulcio_issuer: tstr ; http://oid-info.com/get/1.3.6.1.4.1.57264.1.1 + } +} + +; X.509 Name as an object of attributes +; Repeated attribute types are not supported +; Common attribute types have human-readable labels (see below) +; Other attribute types use dotted OIDs +; Values are converted to UTF-8 +Name = { + ; See RFC 4514, Section 3, for meaning of common attribute types + ? CN: tstr, + ? L: tstr, + ? ST: tstr, + ? O: tstr, + ? OU: tstr, + ? C: tstr, + ? STREET: tstr, + * OID => tstr +} + +; base64url-encoded data, see RFC 4648, Section 5 +base64url = tstr + +; ASN.1 Object Identifier +; Dotted string, for example "1.2.3" +OID = tstr + +; X.509 Subject Alternative Name +; Strings are converted to UTF-8 +SAN = rfc822Name / DNSName / URI / DirectoryName +rfc822Name = ["email", tstr] ; Example: ["email", "bill@microsoft.com"] +DNSName = ["dns", tstr] ; Example: ["dns", "microsoft.com"] +URI = ["uri", tstr] ; Example: ["uri", "https://microsoft.com"] +DirectoryName = ["dn", Name] ; Example: ["dn", {CN: "Microsoft"}] +``` + +In the rest of this document, `chain` refers to the certificate chain mapped to the above JSON data model. diff --git a/spec/normative_references.md b/spec/normative_references.md deleted file mode 100644 index 0cb334d..0000000 --- a/spec/normative_references.md +++ /dev/null @@ -1,11 +0,0 @@ -## Normative references - -[//]: # (Pandoc Formatting Macros) - -[//]: # (# Normative references) - -[//]: # (::: { #nrm:pdf2 .normref label="ISO 32000-2" }) - -[//]: # (ISO 32000-2, *Document management --- Portable Document Format --- Part 2: PDF 2.0*) - -[//]: # (:::) diff --git a/spec/operations.md b/spec/operations.md new file mode 100644 index 0000000..6ae3157 --- /dev/null +++ b/spec/operations.md @@ -0,0 +1,84 @@ +## Operations + +### Create + +Creating a `did:x509` identifier is a local operation. The DID must be constructed according to the syntax rules in the previous sections. No other actions are required. + +When constructing a `did:x509`, the first step is to determine what constitutes a logical identity within a given certificate authority. Concretely, which certificate fields does an authority use to uniquely represent an identity. After that, one or more matching policies must be chosen that allow to express such an identity as faithfully as possible. + +As an example, a certificate authority may exclusively use email addresses as a way to separate identities, and it may use the SAN extension to store the email address. In that case, the `did:x509` identifier should be constructed using the `san` policy, for example, `did:x509:0:sha256:::san:email:bob%40example.com`. The certificate may contain other information about the identity, like full name and address, but the primary field that uniquely identifies the identity in this case is just the email address. + +In other cases, an authority may not include email addresses at all and instead rely on a specific set of subject fields to separate identities. In that case, the `subject` policy should be used. + +In yet other cases, authorities may assign unique numbers or other types of stable identifiers to logical identities. Typically, this is done to have a stable reference even if a person changes their name or email address. + +In all cases, the goal is to craft a `did:x509` that is both stable yet not too loose in its policies. An example of a loose `did:x509` may be to use the `subject` policy and only include the `O` field without location fields like country (`C`) or state/locality (`ST`). See also the Security and Privacy Considerations section. + +Finally, whether a `did:x509` should pin to an intermediate CA instead of a root CA (via the certificate fingerprint) depends on whether there is value in distinguishing between them. Pinning to an intermediate CA typically means that the lifetime of the `did:x509` will be shorter, since intermediate CA certificates typically have a shorter validity period than root CA certificates. + +### Read + +The Read operation takes as input a DID to resolve, together with the `x509chain` DID resolution option. + +The following steps must be used to generate a corresponding DID document: + +1. Decode the `x509chain` resolution option value into individual certificates by splitting the string on `","` and base64url-decoding each resulting string. The result is a list of DER-encoded certificates that can be loaded in standard libraries. Fail if the list contains fewer than two certificates. + +2. Check whether the list of certificates form a valid certificate chain using the [RFC 5280 certification path validation](https://www.rfc-editor.org/rfc/rfc5280#section-6) procedures with the last certificate in the chain as trust anchor. If any extension, excluding the basic constraints and key usage extensions, is marked critical but is not part of the JSON data model, fail. + +3. If required by the application, check whether any certificate in the chain is revoked (using CRL, OCSP, or other mechanisms). + +4. Apply any further application-specific checks, for example disallowing insecure certificate signature algorithms. + +5. Map the certificate chain to the JSON data model. + +6. Check whether the DID is valid against the certificate chain in the JSON data model according to the Rego policy (or equivalent rules) defined in this document. + +7. Extract the public key of the first certificate in the chain. + +8. Convert the public key to a JSON Web Key. + +9. Create the following partial DID document: + +```json +{ + "@context": "https://www.w3.org/ns/did/v1", + "id": "", + "verificationMethod": [{ + "id": "#key-1", + "type": "JsonWebKey2020", + "controller": "", + "publicKeyJwk": { + // JSON Web Key + } + }] +} +``` + +10. If the first certificate in the chain has the key usage bit position for `digitalSignature` set or is missing the key usage extension, add the following to the DID document: + +```json +{ + "assertionMethod": ["#key-1"] +} +``` + +11. If the first certificate in the chain has the key usage bit position for `keyAgreement` set or is missing the key usage extension, add the following to the DID document: + +```json +{ + "keyAgreement": ["#key-1"] +} +``` + +12. If the first certificate in the chain includes the key usage extension but has neither `digitalSignature` nor `keyAgreement` set as key usage bits, fail. + +13. Return the complete DID document. + +### Update + +This DID Method does not support updating the DID Document, assuming a fixed certificate chain. However, the public key included in the DID Document varies depending on the certificate chain that was used as input to the DID resolution process. Typically, multiple chains, in particular leaf certificates, are valid for a given `did:x509`. + +### Deactivate + +This DID Method does not support deactivating the DID. However, if the certificate authority revokes all certificates for the matching DID (or they expire) and does not issue new certificates matching the same DID, then this can be considered equivalent to deactivation of the DID, though there is no technical guarantee in this case and the certificate authority can revert its decision. diff --git a/spec/references.md b/spec/references.md new file mode 100644 index 0000000..0142512 --- /dev/null +++ b/spec/references.md @@ -0,0 +1,29 @@ +## References + +### Normative references + +[Decentralized Identifiers (DIDs) v1.0](https://www.w3.org/TR/2022/REC-did-core-20220719/). Manu Sporny, Amy Guy, Markus Sabadello, Drummond Reed. W3C. 19 July 2022. W3C Recommendation. + +[RFC 8610 - Concise Data Definition Language (CDDL)](https://www.rfc-editor.org/rfc/rfc8610). H. Birkholz, C. Vigano, C. Bormann. IETF. June 2019. Proposed Standard. + +[RFC 5280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile](https://www.rfc-editor.org/rfc/rfc5280). D. Cooper, S. Santesson, S. Farrell, S. Boeyen, R. Housley, W. Polk. IETF. May 2008. Proposed Standard. + +[RFC 4514 - Lightweight Directory Access Protocol (LDAP): String Representation of Distinguished Names](https://www.rfc-editor.org/rfc/rfc4514). K. Zeilenga. IETF. June 2006. Proposed Standard. + +[RFC 4648 - The Base16, Base32, and Base64 Data Encodings](https://www.rfc-editor.org/rfc/rfc4648). S. Josefsson. IETF. October 2006. Proposed Standard. + +[RFC 5234 - Augmented BNF for Syntax Specifications: ABNF](https://www.rfc-editor.org/rfc/rfc5234.html). D. Crocker, P. Overell. IETF. January 2008. Internet Standard. + +[RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax](https://www.rfc-editor.org/rfc/rfc3986). T. Berners-Lee, R. Fielding, L. Masinter. IETF. January 2005. Internet Standard. + +[FIPS 180-4 - Secure Hash Standard](https://csrc.nist.gov/publications/detail/fips/180/4/final). NIST. August 2015. FIPS Publication. + +### Informative references + +[Analysis of hybrid wallet solutions - Implementation options for combining x509 certificates with DIDs and VCs](https://github.com/WebOfTrustInfo/rwot11-the-hague/blob/master/advance-readings/hybrid_wallet_solutions_x509_DIDs_VCs.md). Carsten Stöcker (Spherity) and Christiane Wirrig (Spherity) with support of Paul Bastian (Bundesdruckerei) and Steffen Schwalm (msg Group) in the IDunion Project. 20 July 2022. RWOT11 topic paper. + +[Verifiable Credentials Data Model v1.1](https://www.w3.org/TR/2022/REC-vc-data-model-20220303/). Manu Sporny, Dave Longley, David Chadwick. W3C. 03 March 2022. W3C Recommendation. + +[Rego Policy Language](https://www.openpolicyagent.org/docs/latest/policy-language/). Open Policy Agent contributors. + +[Fulcio](https://github.com/sigstore/fulcio). Fulcio contributors. diff --git a/spec/security_privacy.md b/spec/security_privacy.md new file mode 100644 index 0000000..e478e42 --- /dev/null +++ b/spec/security_privacy.md @@ -0,0 +1,15 @@ +## Security and privacy considerations + +### Identifier ambiguity + +This DID method maps characteristics of X.509 certificate chains to identifiers. It allows a single identifier to map to multiple certificate chains, giving the identifier stability across the expiry of individual chains. However, if the policies used in the identifier are chosen too loosely, the identifier may match too wide a set of certificate chains. This may have security implications as it may authorize an identity for actions it was not meant to be authorized for. + +To mitigate this issue, the certificate authority should publish their expected usage of certificate fields and indicate which ones constitute a unique identity, versus any additional fields that may be of an informational nature. This will help users create an appropriate `did:x509` as well as consumers of signed content to decide whether it is appropriate to trust a given `did:x509`. + +### X.509 trust stores + +Typically, a verifier trusts an X.509 certificate by applying [chain validation](https://www.rfc-editor.org/rfc/rfc5280#section-6) (RFC 5280) using a set of certificate authority (CA) certificates as trust store, together with additional application-specific policies. + +This DID method does not require an X.509 trust store but rather relies on verifiers either trusting an individual DID directly or using third-party endorsements for a given DID, like [W3C Verifiable Credentials](https://www.w3.org/TR/vc-data-model/), to establish trust. + +By layering this DID method on top of X.509, verifiers are free to use traditional chain validation (for example, verifiers unaware of DID), or rely on DID as an ecosystem to establish trust. diff --git a/spec/terms_and_definitions.md b/spec/terms_and_definitions.md deleted file mode 100644 index de4822d..0000000 --- a/spec/terms_and_definitions.md +++ /dev/null @@ -1,8 +0,0 @@ - -[//]: # (Pandoc Formatting Macros) - -[//]: # (Portable Document Format) - -[//]: # (blank) - -[//]: # (: file format defined by ISO 32000-2) diff --git a/spec/title.md b/spec/title.md index d6ddfb4..68d1602 100644 --- a/spec/title.md +++ b/spec/title.md @@ -1,4 +1,4 @@ -ToIP Template Specification +did:x509 Method Specification ================== **Specification Status**: v1.0 Draft @@ -7,12 +7,20 @@ ToIP Template Specification [https://github.com/trustoverip/tswg-did-x509-method-specification](https://github.com/trustoverip/tswg-did-x509-method-specification) +**Abstract:** + +The `did:x509` method aims to achieve interoperability between existing X.509 solutions and Decentralized Identifiers (DIDs) to support operational models in which a full transition to DIDs is not achievable or desired yet. It supports X.509-only verifiers as well as DID-based verifiers supporting this DID method. + **Editors:** -- [Kevin Griffin](https://github.com/m00sey), [GLEIF](https://gleif.org) +- [Eric Scouten](https://github.com/scouten-adobe), [Adobe](https://adobe.com) +- Wenjing Chu, Futurewei **Contributors:** +- [Maik Riechert](https://github.com/letmaik), [Microsoft](https://microsoft.com) +- [Antoine Delignat-Lavaud](https://github.com/ad-l), [Microsoft](https://microsoft.com) + **Participate:** ~ [GitHub repo](https://github.com/trustoverip/tswg-did-x509-method-specification) diff --git a/specs.json b/specs.json index 588b540..e6f7a96 100644 --- a/specs.json +++ b/specs.json @@ -12,11 +12,13 @@ "foreword.md", "introduction.md", "scope.md", - "normative_references.md", - "terms_and_definitions.md", - "clauses.md", - "annex.md", - "biblio.md" + "example.md", + "json_data_model.md", + "identifier_syntax.md", + "did_resolution_options.md", + "operations.md", + "security_privacy.md", + "references.md" ], "logo": "https://raw.githubusercontent.com/trustoverip/logo-assets/master/logos/ToIP-Logo-Color-SolidDimensional-Horizontal-LightOnDark.svg", "logo_link": "https://github.com/trustoverip/tswg-did-x509-method-specification",