Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disclosable DID DHT Documents #147

Open
Tracked by #292
decentralgabe opened this issue Mar 29, 2024 · 4 comments
Open
Tracked by #292

Disclosable DID DHT Documents #147

decentralgabe opened this issue Mar 29, 2024 · 4 comments

Comments

@decentralgabe
Copy link
Member

decentralgabe commented Mar 29, 2024

Overview

tl;dr only publish signed commitments to DID Documents instead of encoded documents

There are two use-cases where this might be useful

  1. Large DID Documents
  2. DID Documents that want to be publicly discoverable (and verifiable) but privately shareable

The latter case is mostly useful for discover in the case of uses with type indexing or alias schemes (#77)

Proposal

The proposal is as follows:

Create a Disclosable DID DHT Document

  1. Create a DID DHT Document
  2. Create a hash of the document - this could optionally be salted if we believe plaintext attacks to be of concern
  3. Encode a minimal DNS packet that contains only the hash value
  4. Publish to the DHT as normal

Resolve a Disclosable DID DHT Document

  1. Resolve the DID Document from the DHT
  2. Verify its signature
    ...
  3. Have the controller of the DID Document send the revealed DID Document and salt if available
  4. Re-compute the hash and compare it to the record from the DHT

Alternate proposal

There is a possible modification to this proposal that reduces the need for a holder to transmit the DID Document to a resolver, which is to rely on a secondary storage mechanism. Alongside the hash DNS record would be a record to a storage system to retrieve and verify the full DID Document. A nice property is that the storage does not need to be trusted as tamper evidence is still provided by the DHT.

Sample Code

This code is a bit contrived. In reality there is no reason to sign the hash separately from the BEP44 packet, unless there is utility in being able to share the document without publishing it to the network.

package main

import (
    "crypto/ed25519"
    "crypto/rand"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
)

// GenerateKeyPair generates a new Ed25519 public/private key pair.
func GenerateKeyPair() (ed25519.PublicKey, ed25519.PrivateKey, error) {
    publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
    if err != nil {
        return nil, nil, err
    }
    return publicKey, privateKey, nil
}

// CommitToDocument creates a "commitment" to the DID Document using a hash function.
func CommitToDocument(doc string) string {
    hasher := sha256.New()
    hasher.Write([]byte(doc))
    return hex.EncodeToString(hasher.Sum(nil))
}

// SignCommitment signs the commitment with the private key.
func SignCommitment(commitment string, privateKey ed25519.PrivateKey) ([]byte, error) {
    sig, err := privateKey.Sign(rand.Reader, []byte(commitment), nil)
    if err != nil {
        return nil, err
    }
    return sig, nil
}

// VerifyCommitmentSignature verifies the signature of the commitment.
func VerifyCommitmentSignature(publicKey ed25519.PublicKey, commitment string, sig []byte) bool {
    return ed25519.Verify(publicKey, []byte(commitment), sig)
}

func main() {
    // Simulating a DID Document
    didDocument := `{"id":"did:example:123","publicKey":"...","authentication":[...]}`
    
    // Generate key pair
    pubKey, privKey, err := GenerateKeyPair()
    if err != nil {
        fmt.Println("Error generating keys:", err)
        return
    }
    
    // Create a commitment to the DID Document
    commitment := CommitToDocument(didDocument)
    fmt.Println("Commitment:", commitment)
    
    // Sign the commitment
    sig, err := SignCommitment(commitment, privKey)
    if err != nil {
        fmt.Println("Error signing commitment:", err)
        return
    }
    fmt.Println("Signature:", hex.EncodeToString(sig))
    
    // Verify the signature
    verified := VerifyCommitmentSignature(pubKey, commitment, sig)
    fmt.Println("Signature verified:", verified)
}
@andresuribe87
Copy link
Contributor

Some general feedback for this thorough proposal (nice work!)

Did you consider using a DID extension to solve the Large DID Documents use-case? If so, what tradeoffs did you find?

I didn't quite understand the second use-case. Would you mind sharing an example?

Re: the section named "Resolve a Disclosable DID DHT Document" has the first step as "Resolve the document from the DHT". In the latter statement, is Document used to mean something different from "DID Document"? If so, I would recommend using different terminology to avoid confusion.

Another question, how would updates work?

@decentralgabe
Copy link
Member Author

DID extension to solve the Large DID Documents use-case

Hmm could you expand on what you mean by this?

I didn't quite understand the second use-case. Would you mind sharing an example?

Yeah, so for example if someone is using type indexing to advertise that they're a PFI they would still want to publish to the DHT so that gateways return their DID when they get queries for "show me all DIDs that have registered as a PFI type". They still might have a large document that's stored elsewhere, but would want to publish to the network.

I updated to the language everywhere to say "DID Document" which was my intent.

Another question, how would updates work?

As they do today, except an update would point to a new commit value.

@andresuribe87
Copy link
Contributor

DID extension to solve the Large DID Documents use-case

Hmm could you expand on what you mean by this?

Something similar to what linkedResource. So if I have a DID Document that's too big, I can move most of the properties and values from the Document and into a linked resource. Can also attach proofs to the linkedResource.

Another similar approach is what subresource integrity does.

@decentralgabe
Copy link
Member Author

yes, both those approaches could work. I suppose it's a question of is this better to handle at the DHT layer or the DID Doc layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants