Giter VIP home page Giter VIP logo

did-dht's Introduction

godoc did-dht go version 1.22.5 license Apache 2 issues GitHub Actions Workflow Status FOSSA Status

did-dht

The did:dht method. Home to the DID DHT Method Specification, and a reference implementation of a gateway server in Go.

Build & Run

Quickstart

To build and run in a single command ./scripts/quickstart.sh.

Usage: ./scripts/quickstart.sh [options]

Builds and runs the did-dht server

Options
  -h, --help          show this help message and exit
  -c, --commit=<hash> commit hash for `docker build` (default: HEAD)
  -t, --tag=<tag>     tag name for `docker build` (default: did-dht:latest)
  -d, --detach        run the container in the background (default: false)
  -k, --keep          keep the container after it exits (default: false)
  -n, --name=<name>   name to give the container (default: did-dht-server)
  -p, --port=<port>   ports to publish the host/container (default: 8305:8305)
  --skip-run          skip running the container (default: false)

docker

To build and run the gateway server, from the impl directory run:

docker build \
  --build-arg GIT_COMMIT_HASH=$(git rev-parse head) \
  --tag did-dht \
  --file build/Dockerfile .

and then

docker run \
    --publish 8305:8305 \
    --publish 6881:6881/udp \
    did-dht

Implementations

Language Client Server Link
Go Yes Yes did-dht, web5-go
Typescript Yes No web5-js
Kotlin Yes No web5-kt
Swift Yes No web5-swift
Dart Yes No web5-dart
Rust Yes No web5-rs

Project Resources

Resource Description
Specification The DID Method specification
CODEOWNERS Outlines the project lead(s)
CODE_OF_CONDUCT.md Expected behavior for project contributors, promoting a welcoming environment
CONTRIBUTING.md Developer guide to build, test, run, access CI, chat, discuss, file issues
GOVERNANCE.md Project governance
LICENSE Apache License, Version 2.0

License

FOSSA Status

did-dht's People

Contributors

andresuribe87 avatar csuwildcat avatar decentralgabe avatar dependabot[bot] avatar finn-tbd avatar fossabot avatar frankhinek avatar lamchau avatar stuartwdouglas avatar thehenrytsai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

did-dht's Issues

Consider adjustment to TXT RData format

image

context: I'm in the middle of implementing did:dht in dart.

Is there any rationale behind _did.TLD storing all the relationships? parsing a TXT record that into a DID Document could be O(n) if each _kN_did. had a rel (relationships) property e.g. rel=auth,asm vs. having to look up the relationships in the root entry.

Store historical records

If we see the same DID multiple times with different data (higher seq numbers) we should be able to store and query multiple versions of the same record.

Consider adding a version of DHT spec being used in the DNS records for a document

If there is ever a need for another version of the spec, then it would be useful for users to differentiate between them.

DKIMs and SPF do this. See https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/ and https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/

For DHT, I would suggest adding it as an additional property in the _did. TXT record. The first example in https://did-dht.com/#dids-as-dns-records would become the following:

v=1;vm=k0,k1,k2;auth=k0;asm=k1;inv=k2;del=k2;srv=s0,s1,s2

Standardize `RData` delimiter

image

Is there a specific reason as to why the root record's RData delimits fields using ; but _kN and _sN uses ,? i think we should use ; to delimit fields so that we can use , for multiple values for a given field.

If not, there are typos here:

image
  • _s0._did.'s RData value should be t=LinkedDomains,uri=foo.com,… not t=LinkedDomains;uri=foo.com;…
  • _s1._did has the same issue

Clarify `secp256k1` VerificationMethod `k` property mapping

image

For secp256k1 specifically, given that k is is the base64URL [RFC4648] representation of the public key it might be helpful to specify whether k is expected to be the compressed, uncompressed, or either and check for both. a compressed EC key can be inflated. JWK expects both x and y to be present for kty: EC

Update test vectors

I suggest to update the test vectors so that:

  • Did documents have the @context property.
  • When verification relationships reference an existing verification method, use a URL that starts with a did URL.

If that makes sense, the resulting vectors are below.

Vector 1

{
  "@context": [
    "https://www.w3.org/ns/did/v1"
  ],
  "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
  "verificationMethod": [
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
      "type": "JsonWebKey",
      "controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "Ed25519",
        "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE",
        "alg": "EdDSA",
        "kid": "0"
      }
    }
  ],
  "authentication": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "assertionMethod": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "capabilityInvocation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "capabilityDelegation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ]
}

Vector 2

{
  "@context": [
    "https://www.w3.org/ns/did/v1"
  ],
  "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
  "verificationMethod": [
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
      "type": "JsonWebKey",
      "controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "Ed25519",
        "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE",
        "alg": "EdDSA",
        "kid": "0"
      }
    },
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw",
      "type": "JsonWebKey",
      "controller": "",
      "publicKeyJwk": {
        "kty": "EC",
        "crv": "secp256k1",
        "x": "1_o0IKHGNamet8-3VYNUTiKlhVK-LilcKrhJSPHSNP0",
        "y": "qzU8qqh0wKB6JC_9HCu8pHE-ZPkDpw4AdJ-MsV2InVY",
        "alg": "ES256K",
        "kid": "0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw"
      }
    }
  ],
  "authentication": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "assertionMethod": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw"
  ],
  "capabilityInvocation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw"
  ],
  "capabilityDelegation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "service": [
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#service-1",
      "type": "TestService",
      "serviceEndpoint": "https://test-service.com"
    }
  ]
}

Support type indexing

Allow an additional record for a type index. Create a type index registry. Create indexes for types & queryability.

Consider returning signature from `GET /dids/:did`

Currently, in order to independently verify that a DID Document was indeed produced and published by the controller of a did:dht, implementers have to resolve using pkarr relays as noted here:

image

Are there any technical reasons preventing us from being able to return the signature from GET /dids/:did? It would be nice to leverage the simplicity of resolving a did:dht using the gateway endpoint while also being able to independently verify that the resolved document hasn't been tampered with.

This would also be beneficial for historical resolution.

Personally feel like providing a means to perform an integrity check is important as it prevents folks from falling victim to a bad actor gateway

Include rationale behind using DNS Packet as wire protocol

is the primary reason behind using DNS packets as the wire protocol because did:dht leverages pkarr relays?

I did notice the gateway /did/:did endpoint which is nice, but i wanted sig verification. found it a bit strange that i was making HTTP requests to get back a DNS packet.

I had to handroll DNS packet decoding because there wasn't a third party lib available to do so.

Not complaining since the work is done, and I imagine most languages to have dns packet decoding libs. Just more-so wondering if there's specific reasons for having selected it. If compression is the sole reason, is there a comparison available between DNS packet sizes for this usecase vs. say CBOR?

I would think KRPC protocol mentioned in bep005 would even make more sense because thats the protocol used to communicate with Mainline DHT nodes over UDP. This way relays wouldn't have to transform DNS records into KRPC payloads.

Anyway, wondering if it'd be helpful to include rationale behind using DNS packets or simply defer to rationale behind using pkarr.

Suggestion: add additional index type "undeclared" for cases you want to be discoverable but do not feel available types are sufficient to represent how you should be indexed.

We have a predetermined set of types here: https://tbd54566975.github.io/did-dht-method/#type-index is an example of such. I generally struggle with pre-determined finite sets for a decentralized ecosystem, as it imposes certain restrictions around expression, but alas I do not have a better solution to solve the indexing problem (yet).

I suggest adding an index type 8 or 0, to express that "I want to be discoverable, but not express my type": for various reasons. I may index 0 or 8 because I do not find the typings available that will satisfy my category.

"Indexing is optional. You can just omit it!" -- This doesn't allow one to delineate between those that just didn't include the indexing vs. those that specifically do not want to categorize themselves against the available index categories. So, no, this doesn't accomplish the same.

Add Test Vectors

Add test vectors for different DID Documents and encoding results.

Handle publishing old data

If the same DID is published to multiple nodes, there is a chance our records will be rejected with older seq numbers. We should be able to detect this and stop re-publishing until we get a later sequence number for these records.

Add to registry for extension properties

E.g. DWNs need properties "sig" and "enc" inside of a service such as:

{
  "id": "#dwn",
  "type": "DecentralizedWebNode",
  "serviceEndpoint": ["https://dwn.tbddev.org/dwn0", "https://dwn.tbddev.org/dwn1"],
  "sig": ['#1'],
  "enc": ['#2']
}

We will include a section in the registry to note supported additional properties.

Clarify the problem that BTC-anchored Gateways are solving

After multiple reads, I am not sure what problem the gateways are aiming to solve. I think that the problem is "BEP044 establishes that blobs stored in Mainline DHT may expire. This implies that the data backing the DID Document of a did:dht may expire."

And I think a gateway solves it by "Gateways do this work on behalf of DID Controllers, by charging a fee for republishing for a certain amount of time."

Is the above correct?

It would be very useful to readers to understand the motivation behind it.

Some questions below that caused confusion:

  • Where is republishing hasn't been defined?
  • What does it mean to "act as a gateway"? The definition of "Gateway" is circular.
  • What does "retention" mean? (I think it means republishing).
  • Why does the fee need to be timelocked?
  • Why does the fee need to be in BTC?
  • What happens when the Gateway doesn't re-publish?

Support for optional user-hashed names

Consider an additional DNS property for an aka field in the DID Document. This could be a user-hashed name.

The user could 'mine' for a hash that extends their did (e.g. did:dht:example becomes did:dht:example:name). To add this property to their DID document they would find an associated nonce value that hashes to did:dht:example:name and include it in the DNS packet record.

Implement caching

If a DID is fetched multiple times within a given time window (e.g. 5 min) return the cached DID

Consider changing some of our HTTP codes in the API section

Describe the bug
We use 404s for unimplemented features where we should probably be using 501s (hashing for POW spam prevention), and are using 404s on no results when we should probably return a 200 with an empty response (searching for types, probably should be an empty array).

Update did:key registry section...

          We'll want to modify this slightly to:
  1. Use the different prefix for a did:dht Ed25519 key (that just makes sure we bind the Ed25519 key to a resolution network -- did:dht). We can register the Multikey prefix pretty quickly to do that.
  2. did:key can take an argument and you can get your keys back as either Multikey or JsonWebKey, so no need to be specific here. JsonWebKey2020 is definitely out of date and is not going to survive standardization. We should be using JsonWebKey anywhere that we were using JsonWebKey2020 before.
  3. If you wanted the did:key to be encoded in z-base-32, we could do that... though I don't think there's a Multibase encoding for that yet? If there is interest there, we could look into that (this is one of the reasons Multibase exists -- because the base-encoding you use is largely driven by what the protocols are optimized for -- humans, ASCII, glyph compression, or some combination of the previous).

None of the feedback above is blocking for now, but wanted to just make sure it was registered as feedback so we can adjust going forward.

Originally posted by @msporny in #56 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.