TBD54566975 / web5-go

Apache License 2.0
10 stars 6 forks source link

`did:web` creation #22

Closed mistermoe closed 7 months ago

mistermoe commented 7 months ago

Overview

This PR is a speed-run implementation of did:web creation with the primary motivation of unblocking KCC issuance prototype while we wait for did:dht creation to land

[!WARNING] the current implementation is not nearly as defensive as it could be (e.g. checking for zero values). Primarily looking to unblock our KCC issuance prototype efforts and coming back around to finish this out

Usage

At a minimum, the domain for which a did should be created is required.

[!IMPORTANT] If no options are provided, a default key manager will be used to generate a single Ed25519 key pair. The resulting public key will be added to the DID Document as a Verification Method.

Create with no options

package main

import (
    "encoding/json"
    "fmt"

    "github.com/tbd54566975/web5-go/dids/didweb"
)

func main() {
    bearerDID, err := didweb.Create("localhost:8080")
    if err != nil {
        panic(err)
    }

    fmt.Printf("DID: %+v\n", bearerDID)

    bytes, err := json.MarshalIndent(bearerDID.Document, "", "  ")
    if err != nil {
        panic(err)
    }

    fmt.Printf("DID Document: %+v\n", string(bytes))
}

Output

DID: did:web:localhost%3A8080
DID Document: {
  "id": "did:web:localhost%3A8080",
  "verificationMethod": [
    {
      "id": "#0",
      "type": "JsonWebKey2020",
      "controller": "did:web:localhost%3A8080",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "Ed25519",
        "x": "I9XaZmu8cifzvj0Zj7cxSWpzx5E_VhSEldXQrDexTqQ"
      }
    }
  ]
}

Create With Options

Options can be provided to Create in order to add/set additional properties on the resulting DID Method

package main

import (
    "encoding/json"
    "fmt"

    "github.com/tbd54566975/web5-go/dids/didweb"
)

func main() {
    bearerDID, err := didweb.Create(
        "localhost:8080",
        didweb.Service("pfi", "PFI", "http://localhost:8080/tbdex"),
        didweb.Service("idv", "IDV", "http://localhost:8080/idv"),
    )

    if err != nil {
        panic(err)
    }

    fmt.Printf("DID: %+v\n", bearerDID)

    bytes, err := json.MarshalIndent(bearerDID.Document, "", "  ")
    if err != nil {
        panic(err)
    }

    fmt.Printf("DID Document: %+v\n", string(bytes))
}

[!IMPORTANT] The Service and PrivateKey option can be provided multiple times to add multiple services or verification methods respectively

Output

DID: did:web:localhost%3A8080
DID Document: {
  "id": "did:web:localhost%3A8080",
  "verificationMethod": [
    {
      "id": "#0",
      "type": "JsonWebKey2020",
      "controller": "did:web:localhost%3A8080",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "Ed25519",
        "x": "5z5OVpmIJ5gmDtJcgXiRGpgQARhwUxx0mnCAAq_mZgc"
      }
    }
  ],
  "service": [
    {
      "id": "#idv",
      "type": "IDV",
      "serviceEndpoint": "http://localhost:8080/idv"
    },
    {
      "id": "#idv",
      "type": "IDV",
      "serviceEndpoint": "http://localhost:8080/idv"
    }
  ]
}

Notes

Create does not publish the DID anywhere.

"registering" or "publishing" a did:web is done by hosting the resulting DID document at ${domain}/.well-known/did.json. An example of this is linkedin's DID: did:web:www.linkedin.com

Requesting feedback for the options approach used

Let me know what y'all think! there's a bit of an inconsistency here in that multiple Service arguments need to be provided whereas the Controllers option allows any number of strings to be provided using variadic args.

[!NOTE] i believe web5-js uses verificationMethods instead of privateKey in its did method create methods. Just wanted to see what it would look like. lmk what you think @frankhinek @amika-sq

[!NOTE] It's likely that many of these options can be reused for other did method creation functions e.g. did:dht. I didn't want to jump the gun though because the options don't apply to all did methods e.g. did:jwk