Fork of github.com/did-method-plc/did-method-plc
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

more README tweaks (#24)

* lib: fix typo

* README: more tweaks

* README: tweaks from review

authored by

bnewbold and committed by
GitHub
ee4e5f53 449dd1b5

+68 -30
+67 -29
README.md
··· 1 - # DID Placeholder (did:plc) 1 + # DID Placeholder Method (did:plc) 2 2 3 3 DID Placeholder is a cryptographic, strongly-consistent, and recoverable [DID](https://www.w3.org/TR/did-core/) method. 4 4 5 + Control over a `did:plc` identity rests in configurable keys pairs. These keys can sign update "operations" to mutate the identity (including key rotation), with each operation referencing a prior version of the identity state. A central server collects and validates operations, and maintains a transparent log of operations for each DID. Each identity starts from an initial "genesis" operation, and the hash of this initial object is what defines the DID itself (that is, the DID URI "identifier" string). 6 + 5 7 ## Motivation 6 8 7 - We introduced DID Placeholder because we weren't totally satisfied with any of the existing DID methods. 8 - We wanted a strongly consistent, highly available, recoverable, and cryptographically secure method with cheap and fast propagation of updates. 9 + We introduced DID Placeholder when designing the AT Protocol ("atproto") because we were not satisfied with any of the existing DID methods. 10 + We wanted a strongly consistent, highly available, recoverable, and cryptographically secure method with fast and cheap propagation of updates. 9 11 10 - We titled the method "Placeholder", because we _don't_ want it to stick around in its current form. We're actively hoping to replace it with or evolve it into something less centralized - likely a permissioned DID consortium. 12 + We titled the method "Placeholder", because we _don't_ want it to stick around forever in its current form. We are actively hoping to replace it with or evolve it into something less centralized - likely a permissioned DID consortium. 11 13 12 14 ## How it works 13 - Each DID document can be described by a JSON object of the following format: 15 + 16 + The core information required to render a `did:plc` DID document is summarized by a JSON object with the following format: 17 + 14 18 ```ts 15 19 type DocumentData = { 16 20 did: string ··· 26 30 } 27 31 ``` 28 32 29 - Keys are notated using [did:key](https://w3c-ccg.github.io/did-method-key/) and only secp256k1 and NIST P-256 are currently supported. 33 + The keys specified in the `verificationMethods` object are the "signing keys" used in atproto. The "rotation keys" are used only for control of the DID identity itself. It is permitted to include a key as both a rotation key and a signing key. 30 34 31 - Each operation fully attests the current state of the document data. It also includes a reference to the previous operation in the log using a sha256 [CID](https://github.com/multiformats/cid). Each operation also includes a `base64url` encoded signature of the cbor-encoded operation from a valid rotation key. 35 + An "operation" object has the following format: 32 36 33 - An operation is of the shape: 34 37 ```ts 35 38 type Operation = { 36 39 type: 'plc_operation', ··· 43 46 } 44 47 ``` 45 48 46 - The DID itself is derived from the sha256 hash of the first operation in the log. It is then base32 encoded and truncated to 24 chars. 49 + Each operation fully attests the current state of the document data. It also includes a content reference (hash) to the previous operation in the log, and is signed by a valid rotation key. 47 50 48 - To illustrate: 49 - `did:plc:${base32Encode(sha256(createOp)).slice(0,24)}` 51 + The process for signing and hashing operation objects is to first encode them in the DAG-CBOR binary serialization format. [DAG-CBOR](https://ipld.io/specs/codecs/dag-cbor/spec/) is a restricted subset of the Concise Binary Object Representation (CBOR), an IETF standard (RFC 8949), with semantics and value types similar to JSON. 50 52 51 - Operations are verified, ordered and made available by the PLC server. 53 + For signatures, the DAG-CBOR bytes are signed, and then the signature bytes are encoded in to a string using `base64url` encoding. 52 54 53 - The operation logs are fully self-certifying construction of the current state of the DID document, with the exception of their ordering. 55 + For `prev` references, the SHA-256 of the previous operation's bytes are encoded as a "[CID](https://github.com/multiformats/cid)", using the relevant multibase code (for `dag-cbor`), and CIDv1 format. 54 56 55 - Therefore, the PLC server's attacks are limited to: 56 - - Denial of service: rejecting valid operations, or refusing to serve some information about the DID 57 - - Misordering: In the event of a fork in DID document history, the server could choose to serve the "wrong" fork 57 + Rotation keys are serialized as strings using [did:key](https://w3c-ccg.github.io/did-method-key/), and only `secp256k1` ("k256") and NIST P-256 ("p256") are currently supported. 58 + 59 + The signing keys (`verificationMethods`) are also serialized using `did:key` in operations (and the DocumentData object). When rendered in a DID document, signing keys are represented as objects, with the actual keys in multibase encoding, as required by the DID Core specification. 60 + 61 + The DID itself is derived from the hash of the first operation in the log, call the "genesis" operation. The object is encoded in DAG-CBOR; the bytes are hashed with SHA-256; the hash bytes are `base32`-encoded (not hex encoded) as a string; and that string is truncated to 24 chars to yield the "identifier" segment of the DID. 62 + 63 + In pseudo-code: 64 + `did:plc:${base32Encode(sha256(createOp)).slice(0,24)}` 65 + 58 66 59 67 ### DID Rotation & Account Recovery 60 68 61 69 Any key specified in `rotationKeys` has the ability to sign operations for the DID document. 62 70 63 - These keys are solely a PLC concept and are _not_ included in the DID document. 71 + The set of rotation keys for a DID is not included in the DID document. They are an internal detail of PLC, and are stored in the operation log. 64 72 65 - Keys are listed in the document data in order of descending authority. 73 + Keys are listed in the `rotationKeys` field of operations in order of descending authority. 66 74 67 - The PLC server provides a 72hr window during which a higher authority key can "rewrite" history. 75 + The PLC server provides a 72hr window during which a higher authority rotation key can "rewrite" history, clobbering any operations (or chain of operations) signed by a lower-authority rotation key. 68 76 69 - To do so, that key must sign a new operation that points to the CID of the last "valid" operation - ie the fork point. This operation will be accepted as long as it was within 72hrs of the pointed to operation & the key that signed it is at a lower index in the `rotationKeys` array than the key that signed the to-be-invalidated operation 77 + To do so, that key must sign a new operation that points to the CID of the last "valid" operation - ie the fork point. 78 + The PLC server will accept this recovery operation as long as: 70 79 80 + - it is submitted within 72hrs of the referenced operation 81 + - the key used for the signature has a lower index in the `rotationKeys` array than the key that signed the to-be-invalidated operation 71 82 72 - ### Resolution 73 83 74 - Dids are resolved by making a GET request to `https://plc.directory/:did` 84 + ### PLC Server Trust Model 75 85 76 - In addition, you may resolve the constituent data by making a request to `https://plc.directory/:did/data` 86 + The PLC server has a public endpoint to receive operation objects from any client (without authentication). The server verifies operations, orders them according to recovery rules, and makes the log of operations publicly available. 87 + 88 + The operation log is self-certifying, and contains all the information needed to construct (or verify) the the current state of the DID document. 89 + 90 + Some trust is required in the PLC server. Its attacks are limited to: 91 + 92 + - Denial of service: rejecting valid operations, or refusing to serve some information about the DID 93 + - Misordering: In the event of a fork in DID document history, the server could choose to serve the "wrong" fork 94 + 95 + 96 + ### DID Resolution 97 + 98 + PLC DIDs are resolved by making a GET request to the PLC server. The default resulution endpoint is: `https://plc.directory/:did` 99 + 100 + In addition, you can fetch the constituent data by making a request to: `https://plc.directory/:did/data` 101 + 77 102 78 103 ### Auditability 79 104 80 - As an additional check against the PLC server and to promote resiliency, the entire database of PLC is auditable. 105 + As an additional check against the PLC server, and to promote resiliency, the entire operation log is auditable. 81 106 82 107 The audit history of a given DID (complete with timestamps & invalidated forked histories) can be found at: `https://plc.directory/:did/log/audit` 83 108 84 - The entire history of PLC operations may be downloaded as a paginated series of jsonlines at `https://plc.directory/export` 109 + The entire history of PLC operations may be downloaded as a paginated series of JSON lines: `https://plc.directory/export` 85 110 86 111 ## Example 87 112 ··· 92 117 const genesisOp = { 93 118 type: 'plc_operation', 94 119 verificationMethods: { 95 - atproto:"did:key:zSigningKey" 120 + atproto: "did:key:zSigningKey" 96 121 }, 97 122 rotationKeys: [ 98 123 "did:key:zRecoveryKey", ··· 115 140 const updateKeys = { 116 141 type: 'plc_operation', 117 142 verificationMethods: { 118 - atproto:"did:key:zSigningKey" 143 + atproto: "did:key:zSigningKey" 119 144 }, 120 145 rotationKeys: [ 121 146 "did:key:zNewRecoveryKey", ··· 139 164 const invalidUpdate = { 140 165 type: 'plc_operation', 141 166 verificationMethods: { 142 - atproto:"did:key:zAttackerKey" 167 + atproto: "did:key:zAttackerKey" 143 168 }, 144 169 rotationKeys: [ 145 170 "did:key:zAttackerKey" ··· 161 186 const recoveryOp = { 162 187 type: 'plc_operation', 163 188 verificationMethods: { 164 - atproto:"did:key:zSigningKey" 189 + atproto: "did:key:zSigningKey" 165 190 }, 166 191 rotationKeys: [ 167 192 "did:key:zRecoveryKey" ··· 233 258 ] 234 259 } 235 260 ``` 261 + 262 + ## Possible Future Changes 263 + 264 + The set of allowed ("blessed") public key cryptographic curves may expanded over time, slowly. 265 + 266 + Support for "DID Controllers" might be useful in the context of atproto. 267 + 268 + Support for multiple "handles" for the same DID is being considered, but no final decision has been made yet. 269 + 270 + We welcome proposals for small additions to make `did:plc` more generic and reusable for applications other than atproto. But no promises: atproto will remain the focus for the near future. 271 + 272 + Moving governance of the `did:plc` method, and operation of registry servers, out of the sole control of Bluesky PBLLC is something we are enthusiastic about. 273 +
+1 -1
packages/lib/src/error.ts
··· 26 26 export class LateRecoveryError extends PlcError { 27 27 constructor(public timeLapsed: number) { 28 28 super( 29 - `Recovery operation occured outside of the allowed 72 hr recovery window. Time lapsed: ${timeLapsed}`, 29 + `Recovery operation occurred outside of the allowed 72 hr recovery window. Time lapsed: ${timeLapsed}`, 30 30 ) 31 31 } 32 32 }