trustdidweb

package module
v0.3.0-alpha.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2024 License: MIT Imports: 27 Imported by: 0

README

trustdidweb-go

Go Reference

This repository contains a highly experimental and unstable implementation of the Trust DID Web DID-Method specification.

Its purpose now is to get some hands-on experience with the specification. If we find it useful, we might continue to develop it further into a more stable implementation.

Do not use this in production!

Example usage

signer, _ := NewSigner("eddsa-jcs-2022")
// create a new log
log := Create("did:tdw:{SCID}:example.com}", signer, nil)
// get the DID Document
doc, _ := log.Document()

// verify a log
if err := log.Verify(); err != nil {
    panic(err)
}

// update the document with a new service
doc["service"] = []interface{}{
    map[string]interface{}{
        "id":              "did:tdw:example.com:123456789abcdefghi#service-1",
        "type":            "Service",
        "serviceEndpoint": "https://example.com/service/1",
    },
}

// Update the log
log, _ = log.Update(LogParams{}, doc, signer)

// verify the log
if err := log.Verify(); err != nil {
    panic(err)
}

// get the updated document:
doc, err := log.Document()

// Marshal the log to a did-log-file which can be hosted on a n well-known endpoint
logFile, _ := log.MarshalText()

// read a log from a did-log-file
newLog := new(DIDLog)
err := newLog.UnmarshalText(logfile)
if err != nil {
    panic(err)
}

TODO

Following thing are still missing (not in a particular order):

  • Support for DID portability
  • Better test coverage
  • Add a resolver
  • Generation of a did:web document from a log
  • Cleanup of the code
  • Support for witness signatures

Documentation

Index

Examples

Constants

View Source
const CRYPTO_SUITE_ECDSA_JCS_2019 = "ecdsa-jcs-2019"
View Source
const CRYPTO_SUITE_EDDSA_JCS_2022 = "eddsa-jcs-2022"
View Source
const TDWMethodv03 = "did:tdw:0.3"
View Source
const TDWMethodv1 = "did:tdw:1"

Variables

This section is empty.

Functions

func NewSigner

func NewSigner(cryptoSuite string) (crypto.Signer, error)

NewSigner returns the signer of the configured crypto suite

func NewUpdateKey

func NewUpdateKey(pubKey crypto.PublicKey) (string, error)

NewUpdateKey encodes a public key to a multiKey formatted updateKey

Types

type DIDDocument

type DIDDocument map[string]interface{}

func NewMinimalDIDDocument

func NewMinimalDIDDocument(didTemplate string) (DIDDocument, error)

func (*DIDDocument) ReplaceSCIDPlaceholder

func (doc *DIDDocument) ReplaceSCIDPlaceholder(scid string) error

ReplaceSCIDPlaceholder replaces the {SCID} placeholder in the document with the provided SCID

type DIDLog

type DIDLog []LogEntry

func Create

func Create(doc DIDDocument, signer crypto.Signer, nextKeyhashes ...NextKeyHash) (DIDLog, error)

Create creates a new DIDLog with a single log entry It calculates the SCID of the first log entry and replaces the placeholder in the path template It signs the entry with the provided signer

Example
package main

import (
	"fmt"
	"log"

	tdw "github.com/nuts-foundation/trustdidweb-go"
)

func main() {
	// Create a new signer
	signer, err := tdw.NewSigner(tdw.CRYPTO_SUITE_EDDSA_JCS_2022)
	if err != nil {
		log.Fatal(err)
	}

	// Create a new DIDLog
	doc, err := tdw.NewMinimalDIDDocument("did:tdw:{SCID}:example.com")
	if err != nil {
		log.Fatal(err)
	}

	didLog, err := tdw.Create(doc, signer)
	if err != nil {
		log.Fatal(err)
	}

	// Print the log
	logFile, err := didLog.MarshalText()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(logFile))
}

func ParseLog

func ParseLog(b []byte) (DIDLog, error)

func (DIDLog) Deactivate

func (log DIDLog) Deactivate(signer crypto.Signer) (DIDLog, error)
Example
package main

import (
	"fmt"
	"log"

	tdw "github.com/nuts-foundation/trustdidweb-go"
)

func main() {
	// Create a new signer
	signer, err := tdw.NewSigner(tdw.CRYPTO_SUITE_EDDSA_JCS_2022)
	if err != nil {
		log.Fatal(err)
	}

	// Create a new DIDDocument
	doc, err := tdw.NewMinimalDIDDocument("did:tdw:{SCID}:example.com")
	if err != nil {
		log.Fatal(err)
	}

	didLog, err := tdw.Create(doc, signer)
	if err != nil {
		log.Fatal(err)
	}

	// Deactivate the log
	didLog, err = didLog.Deactivate(signer)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Is log deactivated: %t\n", didLog.IsDeactivated())

}
Output:
Is log deactivated: true

func (DIDLog) Document

func (log DIDLog) Document() (DIDDocument, error)

Returns the DID Document created from applying all the log entries

func (DIDLog) IsDeactivated

func (log DIDLog) IsDeactivated() bool

func (DIDLog) MarshalJSON

func (log DIDLog) MarshalJSON() ([]byte, error)

func (DIDLog) MarshalText

func (log DIDLog) MarshalText() ([]byte, error)

func (*DIDLog) UnmarshalText

func (log *DIDLog) UnmarshalText(b []byte) error

func (DIDLog) Update

func (log DIDLog) Update(params LogParams, modifiedDoc map[string]interface{}, signer crypto.Signer) (DIDLog, error)
Example
package main

import (
	"fmt"
	"log"

	tdw "github.com/nuts-foundation/trustdidweb-go"
)

func main() {
	// Create a new signer
	signer, err := tdw.NewSigner(tdw.CRYPTO_SUITE_EDDSA_JCS_2022)
	if err != nil {
		log.Fatal(err)
	}

	// Create a new DIDDocument
	doc, err := tdw.NewMinimalDIDDocument("did:tdw:{SCID}:example.com")
	if err != nil {
		log.Fatal(err)
	}

	// Create a new DIDLog
	didLog, err := tdw.Create(doc, signer)
	if err != nil {
		log.Fatal(err)
	}

	// Get the document from the log
	doc, err = didLog.Document()
	if err != nil {
		log.Fatal(err)
	}

	// Add a service
	doc["service"] = []interface{}{
		map[string]interface{}{
			"id":              fmt.Sprintf("%s#service-1", doc["id"]),
			"type":            "Service",
			"serviceEndpoint": "https://example.com/service/1",
		},
	}

	// Update the log with a new entry containing the updated document
	didLog, err = didLog.Update(tdw.LogParams{}, doc, signer)
	if err != nil {
		log.Fatal(err)
	}

	// Print the log
	logFile, err := didLog.MarshalText()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(logFile))
}

func (DIDLog) Verify

func (log DIDLog) Verify() error
Example
package main

import (
	"fmt"
	"log"

	tdw "github.com/nuts-foundation/trustdidweb-go"
)

func main() {
	// Create a new signer
	signer, err := tdw.NewSigner(tdw.CRYPTO_SUITE_EDDSA_JCS_2022)
	if err != nil {
		log.Fatal(err)
	}

	// Create a new DIDDocument
	doc, err := tdw.NewMinimalDIDDocument("did:tdw:{SCID}:example.com")
	if err != nil {
		log.Fatal(err)
	}

	didLog, err := tdw.Create(doc, signer)
	if err != nil {
		log.Fatal(err)
	}

	if err := didLog.Verify(); err != nil {
		log.Fatal(err)
	}

	fmt.Println("Log is valid")

}
Output:
Log is valid

type LogEntry

type LogEntry struct {
	VersionId   versionId `json:"versionId"`
	VersionTime time.Time `json:"versionTime"`
	Params      LogParams `json:"params"`
	DocState    docState  `json:"docState,omitempty"`
	Proof       []Proof   `json:"proof,omitempty"`
}

func (LogEntry) MarshalJSONL

func (l LogEntry) MarshalJSONL() ([]byte, error)

MarshalJSONL returns the JSON-line representation of the log entry

func (*LogEntry) UnmarshalJSONL

func (l *LogEntry) UnmarshalJSONL(b []byte) error

type LogParams

type LogParams struct {
	Method        string        `json:"method,omitzero"`
	Scid          string        `json:"scid,omitzero"`
	UpdateKeys    []string      `json:"updateKeys,omitzero"`
	Portable      bool          `json:"portable,omitzero"`
	Cryptosuite   string        `json:"cryptosuite,omitempty"`
	Prerotation   bool          `json:"prerotation,omitzero"`
	NextKeyHashes []NextKeyHash `json:"nextKeyHashes,omitzero"`
	// Witness       Witness
	Deactivated bool `json:"deactivated,omitzero"`
	TTL         int  `json:"ttl,omitzero"`
}

LogParams represents the parameters of a log entry

func NewInitialParams

func NewInitialParams(pubKeys []crypto.PublicKey, nextKeyHashes []NextKeyHash) (LogParams, error)

NewInitialParams returns the parameters for the first log entry https://bcgov.github.io/trustdidweb/#didtdw-did-method-parameters

type NextKeyHash

type NextKeyHash string

func NewNextKeyHash

func NewNextKeyHash(pubKey crypto.PublicKey) (NextKeyHash, error)

NewNextKeyHash takes a public key and generates the coresponding nextKeyHash

func (NextKeyHash) VerifyPublicKey

func (keyHash NextKeyHash) VerifyPublicKey(pubKey crypto.PublicKey) error

VerifyPublicKey takes a public key and verifies if it matches with the nextKeyHash

func (NextKeyHash) VerifyUpdateKey

func (keyHash NextKeyHash) VerifyUpdateKey(updateKey string) error

type Proof

type Proof struct {
	Type               string             `json:"type"`
	Cryptosuite        string             `json:"cryptosuite"`
	VerificationMethod verificationMethod `json:"verificationMethod"`
	Created            string             `json:"created"`
	ProofPurpose       string             `json:"proofPurpose"`
	Challenge          string             `json:"challenge"`
	ProofValue         string             `json:"proofValue,omitempty"`
}

func (Proof) Verify

func (proof Proof) Verify(challenge string, updateKeys []string, doc DIDDocument) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL