w3c-ccg / did-method-web

DRAFT: did:web Decentralized Identifier Method Specification
https://w3c-ccg.github.io/did-method-web/
Other
32 stars 17 forks source link

Decide what to do about 'proof' section and other DID Doc Metadata #20

Open dmitrizagidulin opened 3 years ago

dmitrizagidulin commented 3 years ago

Signing the DID Document itself (adding an OPTIONAL/recommended proof section, for example) would offer integrity protection / move towards the did docs being self-certifying.

Since the proof property (as well as other metadata fields such as created and updated) were removed from the DID Core spec, we need to make a decision on how to handle these in the did:web method.

Our options:

  1. Put the metadata fields (proof, created etc) into the DID Document itself.
  2. Store not the DID Document in the .json file on the web server, but instead embed it in a structure similar to the DID Resolution Result.

Example structure for option 1:

{
    "@context": "https://www.w3.org/ns/did/v1",
    "id": "did:web:example:com",
    "authentication": [{
        "id": "did:web:example:com#keys-1",
        "type": "Ed25519VerificationKey2018",
        "controller": "did:web:example:com",
        "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }],
    "service": [{
        "id": "did:web:example:com#vcs",
        "type": "VerifiableCredentialService",
        "serviceEndpoint": "https://example.com/vc/"
    }],
    "proof": {
        // signature over the whole DID document would go here.
    },
    "created": "2019-03-23T06:35:22Z",
    "updated": "2023-08-10T13:40:06Z"
}

Example structure for option 2:

{
    "@context": "https://w3id.org/did-resolution/v1",
    "didDocument": {
        "@context": "https://www.w3.org/ns/did/v1",
        "id": "did:web:example:com",
        "authentication": [{
            "id": "did:web:example:com#keys-1",
            "type": "Ed25519VerificationKey2018",
            "controller": "did:web:example:com",
            "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
        }],
        "service": [{
            "id": "did:web:example:com#vcs",
            "type": "VerifiableCredentialService",
            "serviceEndpoint": "https://example.com/vc/"
        }],
                "proof": {
                    // signature over the whole DID document would go here.
                }
    },
    "didDocumentMetadata": {
        "created": "2019-03-23T06:35:22Z",
        "updated": "2023-08-10T13:40:06Z"
    }
}
gribneau commented 2 years ago

I'd say this fits way better within the context of did-resolution

I am afraid I simply cannot agree.

We have, in the not too far distant past, refused to handle content negotiation within did:web based on the complexity it would introduce, despite content negotiation being quite well understood for some years now in http.

Just recently, we've declined to implement the common parameters in section 3.2.1 on the same basis. #61

Adding cryptographic signatures in metadata rather than the content of a JSON document, on a webserver, is considerably more complex than either content negotiation or dynamically handling parameters.

We should be consistent in our treatment of these issues to avoid the appearance that the standards process is arbitrary.

Trying to stuff this into a data model spec seems wrong

In the context of did:web, given our strong and unyielding preference to avoid complexity, we've left ourselves no alternative. If the proof isn't in the document, and we won't approve extensions involving even the simplest of logic on the webserver, we are affirmatively and proactively limiting this method.

that security consideration was likely just because we've always known this was a problem

Yes, we have always known this is a problem. Now @vitorpamplona is asking for a resolution, and the request is sane and practical.

vitorpamplona commented 2 years ago

Ok, we have a few issues to solve.

1. Where is the DID Document Metadata stored for DID:WEB?

Option 1.1: Single json file: the did.json MUST be a combination of didDocument and didDocumentMetadata Option 1.2: Multiple json files: did.json is the didDocument itself, didMetadata.json stores the didDocumentMetadata.

In the case of 1.2, the resolver makes 2 GET requests and merges them into their result.

2. How are different representations (JSON-LD, XML, CBOR) resolved?

Option 2.1: The Web Server calculates the representation on-demand based on the "accept" header. Option 2.2: Multiple files with predefined names are pre-loaded (did.json, did.jsonld, did.cbor, did.xml).

Option 2.1 requires a dynamic server with capabilities to map the original DID Document into different representations by itself and assumes the original DID Document can be mapped without additional information (e.g. contexts for JSON-LD).

Option 2.2 requires prescriptive conversion from the DID URI to the GET request based on the "accept" parameter of the resolve function. If Option 1.2 is chosen, similar conversions must be available for the DID Document Metadata. This option allows for the use of CDNs and static servers.

3. Is security run at DID Document or DID Document Representation level?

The DID Document map doesn't offer security but a JSON-LD of that document might.

Option 3.1. Security is based on a representation, not the original DID Document. Option 3.2. Security must be based on and calculated from the original DID Document.

Option 3.1 requires prescribing of security steps for each representation and the appropriate processing in the resolver side. Option 3.2 forces everyone to use the same security procedure independent of representation. The method can force everyone to use a JWT for instance. LD-Proofs/CBOR-Proofs/XML proofs are not accepted. It simplifies implementations but reduces options.

4. Is the resolver's job to verify proofs or not?

Option 4.1 the resolver must run the verification Option 4.2 the application must run the verification.

Option 4.1 requires the resolver library to depend on cryptographic tools for the forced security (3.1) or the many possible representations (3.2) plus forces the resolver to have contextual knowledge to verify (trusted keys, authorized signatures suites, etc).

Option 4.2 concedes that the DID:WEB method is unsecured by design.

5. If 3.1, how do creators/resolvers declare compliance with security stacks?

5.1. Through DID:WEB profiles: "I am implementing DID:WEB:JSONLD" 5.2. Through an overarching DID-CORE representation choice? "I only resolve DIDs that return JSONLD"

OR13 commented 2 years ago

1. Where is the DID Document Metadata stored for DID:WEB?

Option 1.1: Single json file: the did.json MUST be a combination of didDocument and didDocumentMetadata Option 1.2: Multiple json files: did.json is the didDocument itself, didMetadata.json stores the didDocumentMetadata.

In the case of 1.2, the resolver makes 2 GET requests and merges them into their result.

Or you can read the http headers from the "did.json" and make your own didDocumentMetadata... the later is not required to be implemented by did core or did web today.

The short answer to your question is that did:web does not define a place to store didDocumentMetadata, or a way to expose it too resolvers... http headers seem like the natural answer to this question though.

2. How are different representations (JSON-LD, XML, CBOR) resolved?

Option 2.1: The Web Server calculates the representation on-demand based on the "accept" header. Option 2.2: Multiple files with predefined names are pre-loaded (did.json, did.jsonld, did.cbor, did.xml).

Option 2.1 requires a dynamic server with capabilities to map the original DID Document into different representations by itself and assumes the original DID Document can be mapped without additional information (e.g. contexts for JSON-LD).

Option 2.2 requires prescriptive conversion from the DID URI to the GET request based on the "accept" parameter of the resolve function. If Option 1.2 is chosen, similar conversions must be available for the DID Document Metadata. This option allows for the use of CDNs and static servers.

Today, only a single JSON representation is supported.

I am not in favor of changing this, as it harms interoperability.

However, we might introduce content negotiation to resolve this.. I suggest creating a separate issue to discuss.

3. Is security run at DID Document or DID Document Representation level?

The DID Document map doesn't offer security but a JSON-LD of that document might.

Option 3.1. Security is based on a representation, not the original DID Document. Option 3.2. Security must be based on and calculated from the original DID Document.

Option 3.1 requires prescribing of security steps for each representation and the appropriate processing in the resolver side. Option 3.2 forces everyone to use the same security procedure independent of representation. The method can force everyone to use a JWT for instance. LD-Proofs/CBOR-Proofs/XML proofs are not accepted. It simplifies implementations but reduces options.

In DID Web, the DID Document is JSON... how you store that internally is not really the concern of the method spec... you could pull the content from a blockchain, or from a raspberry pi sd card :)

Here is a similar example:

https://idp.int.identitysandbox.gov/.well-known/openid-configuration

^ notice this JSON document is also not "signed".

4. Is the resolver's job to verify proofs or not?

Option 4.1 the resolver must run the verification Option 4.2 the application must run the verification.

Option 4.1 requires the resolver library to depend on cryptographic tools for the forced security (3.1) or the many possible representations (3.2) plus forces the resolver to have contextual knowledge to verify (trusted keys, authorized signatures suites, etc).

Option 4.2 concedes that the DID:WEB method is unsecured by design.

This is the repository for a method specification, this is not the place to discuss the "resolver's job"...

However... All resolvers trust the "did method specification" and some "software implementation" of it.

Specific resolvers might make additional security decisions, like not resolving any blockchain did methods, or any did web from certain origins (for example excluding Iran or North Korea), etc.... The resolver is a natural root of trust, even when you implement it yourself... The resolver isn't a place to handle interoperability at the did method layer... thats what the method specification is for.

In general, resolvers are expected to implement the did methods that they support, and not "do extra work" that is not described in the method specification... did web is trivial to implement today, and its security model is equivalent to the OIDC example I shared above.

5. If 3.1, how do creators/resolvers declare compliance with security stacks?

5.1. Through DID:WEB profiles: "I am implementing DID:WEB:JSONLD" 5.2. Through an overarching DID-CORE representation choice? "I only resolve DIDs that return JSONLD"

The DID Core spec is a W3C TR.

There are no "W3C Standard DID Methods" today.

There is also very little guidance regarding "DID Resolution" it was considered out of scope by the DID WG... which caused a number of problems.

Regarding security declarations (not sure exactly what you mean):

DID method specification authors do this by defining the method specification, and detailing concerns in the privacy and security sections.

DID method implementers read the method spec and develop implementations that cover its normative requirements.

In general, any resolver can "claim" to implement a did method, and can in practice lie about or tamper with the results.

You would want to make sure you really trusted the did method, then the resolver, including all its software dependencies, and its operators.

These are all very good questions, but this issue is titled:

"Decide what to do about 'proof' section and other DID Doc Metadata"

There is no normative requirement to include proof... but since the did document is a json object, nobody can stop you from including it... most people will ignore it... which is why you shouldn't try and use it for something important.

Similarly for "DID Doc Metadata"... there is no place to store that in the spec today... headers seem like the logical answer... I would be in favor of discussing that on a more focused issue.

Feel free to spawn fresher / more focused issues for any of these discussion points and cross link.

vitorpamplona commented 2 years ago

The short answer to your question is that did:web does not define a place to store didDocumentMetadata, or a way to expose it too resolvers... http headers seem like the natural answer to this question though.

So, if I want to place the "proof" inside the didDocumentMetadata or as a header, how do generic DID Web resolvers, or universal DID resolvers, out there know where it is and how to pass it on to my application? See, this is not a resolver question. It's a method question. I am asking how to find the didDocumentMetadata for this DID Method, not how to convert it for the resolution.

Do I need to reach out individually to each resolver to get them out of spec and implement my version of the proof method through unspecified metadata fields?

Today, only a single JSON representation is supported.

So... it doesn't support JSON-LD at all?

the DID Document is JSON.

This is absolutely not true. The DID Core spec makes sure to identify the JSON as just one of the possible representations of the properties listed in the DID Document. Don't confuse the examples in the text with the need to use JSON

  1. Representations A concrete serialization of a DID document in this specification is called a representation. A representation is created by serializing the data model through a process called production. A representation is transformed into the data model through a process called consumption. The production and consumption processes enable the conversion of information from one representation to another. This specification defines representations for JSON and JSON-LD, and developers can use any other representation, such as XML or YAML, that is capable of expressing the data model. The following sections define the general rules for production and consumption, as well as the JSON and JSON-LD representations.

On the:

This is the repository for a method specification, this is not the place to discuss the "resolver's job"...

I agree. But the DID Core spec says that the DID Method MUST specify how resolvers can verify the authenticity of the response:

A DID method specification MUST specify how a DID resolver uses a DID to resolve a DID document, including how the DID resolver can verify the authenticity of the response.

OR13 commented 2 years ago

So, if I want to place the "proof" inside the didDocumentMetadata or as a header, how do generic DID Web resolvers, or universal DID resolvers, out there know where it is and how to pass it on to my application?

If the method spec defined where metadata was stored, then you could define a profile to secure it.

Since the method does not currently define where metadata is stored, I think it's a bit premature to consider securing it.

So... it doesn't support JSON-LD at all?

It turns out that all JSON-LD is also JSON.

This is absolutely not true. The DID Core spec makes sure to identify the JSON as just one of the possible representations of the properties listed in the DID Document.

It also says that DID Methods are not required to implement all representations.

https://w3c.github.io/did-spec-registries/#representationnotsupported

And I am referring to the did web method spec, not the did core spec... this is what the did web spec says today:

https://w3c-ccg.github.io/did-method-web/#create-register

If you are arguing that did web should support JSON, JSON-LD, CBOR, CBOR-LD, YAML, YAML-LD, etc... all because the did core spec defines an abstract data model that can support an unbounded number of registered (or not registered) representations... I don't agree... but I would agree that a CBOR representation might be useful to define.

I agree. But the DID Core spec says that the DID Method MUST specify how resolvers can verify the authenticity of the response:

Ahh yes, but define "verify the authenticity of the response."... is it enough to trust TLS and DNS and a library that checks them?

Does the resolver need to verify 100% of the infrastructure powering hosting a JSON file on an https web server?

What about all the network layers between the resolver and the host?

https://w3c-ccg.github.io/did-method-web/#security-and-privacy-considerations

It can be argued the current did web spec language fails to "sufficiently define an ability to verify the authenticity of the response".

I'd be open to more language regarding why DNS + TLS are trusted to secure OIDC / OAuth today.

vitorpamplona commented 2 years ago

It also says that DID Methods are not required to implement all representations.

Correct. You can force it to JSON (and not allow the use of LD Signatures). I don't think that is a good idea.

If you are arguing that did web should support JSON, JSON-LD, CBOR, CBOR-LD, YAML, YAML-LD, etc... all because the did core spec defines an abstract data model that can support an unbounded number of registered (or not registered) representations... I don't agree... but I would agree that a CBOR representation might be useful to define.

The DID:WEB should follow the DID-Core example and define everything in terms of generic properties. It doesn't matter what serialization form people use. Then any representation would automatically work. I don't understand why any spec would define things in JSON (or JSON-LD) only. You don't need to define an XML version. You just need to define the properties that would go in given structures in each file. Super simple.

is it enough to trust TLS and DNS and a library that checks them?

As we said before. No. TLS + DNSSec does not mean the answer is authentic. You need to put both Server and Resolver inside the same VPN, controlled by the resolver, to make that claim.

OR13 commented 2 years ago

Correct. You can force it to JSON (and not allow the use of LD Signatures). I don't think that is a good idea.

JSON, by definition.... supports Data Integrity "proofs", when they are represented in JSON-LD.

The DID:WEB should follow the DID-Core example and define everything in terms of generic properties.

It does, it uses JSON to do this... I challenge you to make this simpler, by adding other representations :)

As we said before. No. TLS + DNSSec does not mean the answer is authentic. You need to put both Server and Resolver inside the same VPN, controlled by the resolver, to make that claim.

Can we eliminate the resolver for a second?

Lets just look at this example:

https://did.actor/supply-chain/manufacturer/carlos/did.json

Screen Shot 2022-08-11 at 7 28 52 PM

How do I know the response is authentic? (and what do you mean by authentic).

You are saying I need to be on a different network?

vitorpamplona commented 2 years ago

It does, it uses JSON to do this... I challenge you to make this simpler, by adding other representations :)

You are wrong here. It USED to use JSON. The text is not bound by the serialization choice it anymore. If you read the text again, you can see that every mention to the DID Document is as an abstract data model represented as a map of properties, not a JSON (a serialization of that map).

Like this:

If the resolution is successful, and if the resolve function was called, this MUST be a DID document abstract data model (a map) as described in 4. Data Model that is capable of being transformed into a conforming DID Document (representation), using the production rules specified by the representation. The value of id in the resolved DID document MUST match the DID that was resolved. If the resolution is unsuccessful, this value MUST be empty.

How do I know the response is authentic? (and what do you mean by authentic).

You don't. You would have no idea if that TLS certificate is the same as the owner of the DID Document bought to resolve in this domain. It might be behind a third-party CDN that has their VALID TLS certificate and is just redirecting you there. The fact that the TLS is valid doesn't mean it's authentic. Google does that all the time with its preview pages.

vitorpamplona commented 2 years ago

Let me try a different approach. Because the DID:WEB spec are so open today, I'd like to define the following rules as my DID WEB... extension? I am not sure what to call it.

Anyway...

--

DID Producers MUST support every possible representation DID Resolvers do not need to support every possible representation (heavy pre-computation, thin on-demand resolution - burden is on the issuer)

DID Document Representations MUST be made available in the following files:

All DID Document Representations MUST represent the same DID Document. All DID Document Representations MUST be signed at all times

The didMetadata MUST include a proof section. The didMetadata.proof MUST include a keyID field in the form of a DID The didMetadata.proof MUST include a signature suite field to describe the algorithm used when signing the document. The didMetadata.proof MUST include a signature in the format determined by the signature suite

Resolvers MUST cryptographically verify the proof of the chosen representation. Applications MUST pass a cryptographic stack to the resolve function as a DID Resolution Options

Resolvers MUST pass all available metadata attributes to the application, unchanged.

Since representations MUST be signed at all times, no additional security is required. Calls through an unsecured http and DNS MUST be accepted (The Security section can be deleted)

The application must independently verify the trust status of the keyID

--

Would you folks be ok if somebody went rogue and started requiring DID:WEB resolvers to support all this?

OR13 commented 2 years ago

You are wrong here. It USED to use JSON. The text is not bound by the serialization choice it anymore.

I think you are again, claiming that the DID Core spec is somehow more authoritative for representations than the did method spec.

Thats not my understanding.

But let's assume for a second you are correct.

We would need to rewrite the did web spec to talk about the abstract data model instead of JSON, and then define production and consumption rules for it.

You seem to be arguing thats what we should do, am I correct?

You don't. You would have no idea if that TLS certificate is the same as the owner of the DID Document bought to resolve in this domain.

Who is the "owner of the did document" ?

Which layers of the network are they in control of in your threat model?

OR13 commented 2 years ago

Would you folks be ok if somebody went rogue and started requiring DID:WEB resolvers to support all this?

I'm pretty much ok not trusting anyone to resolve DIDs for me... I don't use 3rd party resolvers... you shouldn't either :)

The rest of your proposal seems to align with either:

  1. a new did method (which you are of course free to create)
  2. a change to the did method in this repo (which will require consensus)

As an editor, I am required to implement the consensus regarding PRs / issues, etc...

As an implementer, I don't like your proposal, and I don't intend to implement it, if your proposal "wins" I would register a new "did:web2" method... that had the same boring behavior that the current one does... I am not attached to the the method name... I like the simplicity.

vitorpamplona commented 2 years ago

We would need to rewrite the did web spec to talk about the abstract data model instead of JSON, and then define production and consumption rules for it.

I don't think you are required to rewrite it. DID Methods can force the use of representations. I just don't think you should force them to use JSON. Especially when the DID:WEB text doesn't need much change to make it an abstract data model.

Which layers of the network are they in control of in your threat model?

I work for the WHO, I have to deal with sensitive health information transfers between medical providers from two countries at war with one another. Country-level attacks/hostilities against individuals and other countries define the threat model. They have literal control over the entire web stack of the country. All I have is a trust chain to identify DID Document providers on each end.

I'm pretty much ok not trusting anyone to resolve DIDs for me... I don't use 3rd party resolvers... you shouldn't either :)

It's not a question of trust. It's a question of a prescriptive/interoperable standard so that there is one less variable to be concerned about when choosing DID Resolvers or when having to reimplement a bunch of ad-hoc variations.

As an editor, I am required to implement the consensus regarding PRs / issues, etc...

So what are the consensus procedures? Who else needs to provide an ok in this? How do we move this forward? I am not pushing for MY idea. This is just a very real example of what can actually happen just because the spec leaves everything up in the air.

I am pushing for ANY idea that defines this metadata spec better. I am happy to spend months navigating consensus to get this done.

gribneau commented 2 years ago

How do we move this forward?

I would recommend a dedicated method.

vitorpamplona commented 2 years ago

How do we move this forward?

I would recommend a dedicated method.

Even if all I need is a definition to where to put the metadata (proof goes inside)?

OR13 commented 2 years ago

I just don't think you should force them to use JSON.

Nobody is forcing anyone to just use JSON, the did core spec allows you to define your own representations and register them... did web could support CBOR-LD and YAML-LD... the method spec gets to define this stuff.... if you want did web to support a new representation you are in the right place to argue for that.

They have literal control over the entire web stack of the country.

Sounds like did:web might not be a best fit... It's built on the assumption that you are not being attacked by nation states... which applies to most use cases... but maybe my/your proposal below will somehow make DID web capable of surviving nation state attacks?

It's not a question of trust. It's a question of a prescriptive/interoperable standard so that there is one less variable to be concerned about when choosing DID Resolvers or when having to reimplement a bunch of ad-hoc variations.

And just so I understand it... if we were to make did:web use a JWT or CWT and then you would verify if, decode it and obtain the did document and meta data, this would work for you?

https://example.com/issuer/123/jwt -> json -> didDocument, didDocumentMetadata https://example.com/issuer/123/cwt -> cbor -> didDocument, didDocumentMetadata https://example.com/issuer/123/proof -> json-ld -> didDocument, didDocumentMetadata

vitorpamplona commented 2 years ago

Nobody is forcing anyone to just use JSON

The spec requires a file called did.json. There are no generalizations of file names for the other representations. A simple change to did.<representation> to make it representation-independent would fix the narrative. Until then, it does force implementers to use JSON.

maybe my/your proposal below will somehow make DID web capable of surviving nation-state attacks?

Yes, an implementation of a signed DID Document provides all the security needed to be resilient even against nation-state attacks. And I think it is a good (optional) feature to have on the DID:WEB spec.

we were to make did:web use a JWT or CWT

You don't need to make implementers use a specific signature style (JWT, LDProof, etc), you just need to define where the signature would go in the style that it needs to be from another spec. LD Proof for instance is extremely well-defined. There is no need to repeat the definitions in the spec.

https://example.com/issuer/123/jwt -> json -> didDocument, didDocumentMetadata https://example.com/issuer/123/cwt -> cbor -> didDocument, didDocumentMetadata https://example.com/issuer/123/proof -> json-ld -> didDocument, didDocumentMetadata

This could definitely work.

Thanks for being open to the idea.

OR13 commented 2 years ago

LD Proof for instance is extremely well-defined.

They are being renamed "Data Integrity Proofs", and are now a Verifiable Credentials WG item:

https://w3c.github.io/data-integrity/ (notice the 404).

vitorpamplona commented 2 years ago

I assume DID Core authors have some thoughts on how to write proofs inside their metadata structure. If so, then DID:WEB should only let people know how to find the metadata file. DID Core/DID Spec Registries should take care of the rest (defining fields for each proof type, in each representation option).

Also, FYI, the current draft of the DID Resolution talks about 3 types of proofs:

In the DID Resolution Metadata:

This is signed by the resolver itself. In the real world, the resolver can take legal liability to assert the DID Document is correct. It's super useful when apps are dependent on third-party resolvers.

In the DID Document Metadata

The former is what I am looking for: an application-layer signature that can be verified by the application itself. The resolver is just a pass-through.

The latter is where the resolver cryptographically verifies the DID Document with the help of a "verifiable data registry". Very useful for blockchain systems. But DID:WEB could also use a version of this.

OR13 commented 2 years ago

DID Core is highly unlikely to provide guidance on "securing meta data"... in a way that will support an abstract data model.

Certainly the registries can help if you plan to use Data Integrity Proofs with JSON-LD and a DID Document (of another method type) as the signer.

If the DID Web Metadata is going to be secured, this repository is the right place to define that... and to limit the potential unbounded number of ways that might happen.

@dmitrizagidulin @msporny @tplooker Where should did:web metadata go?

  1. In headers?
  2. In a document next to the did document?
  3. Inside the did document?
gribneau commented 2 years ago

The DID Core specification is very consistent with existing HTTP content negotiation, using an accept element to specify desired representations and content types to identify those representations. In HTTP, accept is a request header containing one or more content type strings, content-type is a response header, and the process of identifying the best response is referred to as content negotiation.

This should be more efficient than mapping to specific URLs in the resolver, in that server-side logic would be able to identify the best available representation and deliver it in a single request. The explicit .json filename is a challenge in this scenario.

vitorpamplona commented 2 years ago

Pros and cons:

If in the headers then we might need to define a mapping function for each representation to an HTTP header. Maybe a dumb Base64 encoding of the raw DID Document Metadata contents in the chosen representation?

Two documents require two HTTP calls. Not super efficient, but not the end of the world either. Are there any security concerns when the web infra diverts the two calls to two different servers?

If inside the DID Document, then the spec should define that the did.json file is not a DID Document but an incomplete DID Resolution Result.

gribneau commented 2 years ago
  1. in headers?

From a practical perspective, HTTP response headers are often limited in size, with 8k being a common default.

This is not required by the specification, and it is configurable, but it's worth noting.

vitorpamplona commented 2 years ago
  1. in headers?

From a practical perspective, HTTP response headers are often limited in size, with 8k being a common default.

This is not required by the specification, and it is configurable, but it's worth noting.

Here is the limit of the most popular web servers:

@gribneau would the map->HTTP header conversion require a dynamic web server? Are custom HTTP headers per file easy to set up/deal with on static servers and CDNs?

gribneau commented 2 years ago

would the map->HTTP header conversion require a dynamic web server?

It is plausible that one might be able to accomplish this with pre-rendered metadata in files that are then included as headers in the response document, which would not require a scripting engine.

Rendering those files will necessarily be dynamic, but if they don't change they could (plausibly) be served as static files.

Are custom HTTP headers per file easy to set up/deal with on static servers

This would fall squarely into the advanced category. Relatively few people are familiar with the layout of headers vs. content in HTTP responses.

and CDNs?

CDNs cache what the origins send, and this can include headers. Expect an 8k limit.

gribneau commented 2 years ago

Calls through an unsecured http and DNS MUST be accepted (The Security section can be deleted)

This requirement, particularly, is a non-starter for me.

Without TLS / SSL, an HTTP GET, together with any request headers, is visible in the clear to any network device that handles the traffic. The response, together with any headers, is similarly visible.

This change would expose use of did:web to surveillance.

vitorpamplona commented 2 years ago

Calls through an unsecured http and DNS MUST be accepted (The Security section can be deleted)

This requirement, particularly, is a non-starter for me.

Without TLS / SSL, an HTTP GET, together with any request headers, is visible in the clear to any network device that handles the traffic. The response, together with any headers, is similarly visible.

This change would expose use of did:web to surveillance.

I agree. Next time, I am not going to suggest a crazy example :)

vitorpamplona commented 2 years ago

So, looks like idea 3 is the leading contender. Do we all like this option? Please signal with a Like/Dislike reaction.

did.json will look like this: (this snippet is a variation of Option 2 from the first post)

{
    "@context": "https://w3id.org/did-resolution/v1",
    "didDocument": {
        "@context": "https://www.w3.org/ns/did/v1",
        "id": "did:web:example:com",
        "authentication": [{
            "id": "did:web:example:com#keys-1",
            "type": "Ed25519VerificationKey2018",
            "controller": "did:web:example:com",
            "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
        }],
        "service": [{
            "id": "did:web:example:com#vcs",
            "type": "VerifiableCredentialService",
            "serviceEndpoint": "https://example.com/vc/"
        }],
    },
    "didDocumentMetadata": {
        "created": "2019-03-23T06:35:22Z",
        "updated": "2023-08-10T13:40:06Z"
                "proof": {
                    // signature over the "didDocument" would go here.
                }
    }
}
peacekeeper commented 2 years ago

what's the point of downloading a keyset document that an intermediary infrastructure can tweak around

It's one fundamental problem of the did:web method that it is easy for intermediary infrastructure to replace the entire DID document. I mean it's all relative, but a did:web is easier to manipulate than let's say a did:btcr.

Where is the DID Document Metadata stored for DID:WEB

This question is definitely in scope for a DID method spec, and I have been wondering myself how this could work for did:web. I don't have any preference here at all, but the original idea of DID document metadata was that it could originate from the DID controller and/or the DID method, or some combination of the two.

For example, in my mind it would be perfectly legitimate to say that in did:web, some DID document metadata (such as "updated") would be mapped from an HTTP header (such as "Last-Modified"). Note that the DID controller typically doesn't "manually" control such headers, it's the DID method that controls them. Whereas other DID document metadata (such as proofs) could come from a separate file on the webserver that the DID controller can edit however they like.

But again, I don't really have an opinion if and how exactly this should be supported by did:web.

vitorpamplona commented 2 years ago

I just realized that idea 3 breaks backward compatibility since most DID:WEB documents deployed right now have only the didDocument properties in the JSON. Since there is no versioning in the DID:WEB spec, DID:WEB resolvers would have to accept the old method (a direct DID Document in the JSON) and a new method (a JSON structure that includes the DID Document).

Is backward compatibility important at this stage? Or, because this is still a draft spec, we shouldn't care too much about it?

msporny commented 2 years ago

Is backward compatibility important at this stage? Or, because this is still a draft spec, we shouldn't care too much about it?

Backwards compatibility is not important at this stage. Until did:web achieves standardization and significant production deployment, we should be willing to change it. Experimental implementations will have to determine how they might keep backwards compatability if its important to them. For example, you could support both the "old style" and "new style" mechanisms described above by just checking for the existence of a few fields. That said, we shouldn't memorialize that experimental backwards compatibility in the specification in order to keep implementations as simple as we can achieve.

vitorpamplona commented 2 years ago

Hi all,

Please review PR #63.

Following the discussion here, the PR proposes:

  1. Changing the nature of the did.json document to become a DID Resolution Document that contains a DID Document and not the DID Document itself.
  2. Establishing the presence of DID Document Metadata with possibilities of adding cryptographic proofs to verify DID Documents.
  3. Allowing multiple representations (JSON, JSONLD, XML, CBOR, etc) of the DID Resolution Document for the same DID:WEB based on DID Resolution Options
vitorpamplona commented 2 years ago

Hi all,

@msporny requested to move the proposed (#63) proof section from the DID Document Metadata to the DID Document itself.

I am happy to do it either way (in the DID Document or in the DID Document Metadata). But since so many of you have said here that proof should not go in the did document, what do you think? Do we have any consensus on this?

gribneau commented 2 years ago

I am comfortable either way.

I view adding signatures as a net positive, but remain agnostic on the question of placement in the DID document vs the DID metadata.

msporny commented 2 years ago

I am happy to do it either way (in the DID Document or in the DID Document Metadata). But since so many of you have said here that proof should not go in the did document, what do you think? Do we have any consensus on this?

I think the only viable answer here is "both". Implementers will want to secure the DID Document itself (provided by the DID Controller), and they will also want to provide a digital signature on the metadata associated with the DID Document (provided by the Verifiable Data Registry and/or the DID Resolver), and possibly over the entire resolution result (provided by the DID Resolver). All of those are valid use cases, and luckily, Data Integrity allows for all of that to happen. That said, if people want to use JWTs or some other mechanism that requires base64 encoding before signature, it will complicate matters.

Something to keep in mind as people weigh in... this isn't an either/or decision, IMHO.

vitorpamplona commented 2 years ago

Maybe we need a table on what types of proofs are acceptable in what places.

Type DID Document DID Document Metadata DID Resolution Metadata DID Resolution Result
Proof by a DID Controller 🚫 🚫
Proof by a Verifiable Data Registry 🚫 🚫 🚫
Proof by a DID Resolver 🚫 🚫 🚫

Does this make sense?

What's an example of a Verifiable Data Registry for DID WEB?

vitorpamplona commented 2 years ago

For JWTs, do we prefer something like:

{
  "didDocument": {
    "id": "did:web:example:com",
    "authentication": [{
      "id": "did:web:example:com#keys-1",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:web:example:com",
      "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }],
    "service": [{
      "id": "did:web:example:com#vcs",
      "type": "VerifiableCredentialService",
      "serviceEndpoint": "https://example.com/vc/"
    }],
  },
  "didDocumentMetadata": {
    "created": "2019-03-23T06:35:22Z",
    "updated": "2023-08-10T13:40:06Z",
    "proof": {
      "type": "JwtProof2020",
      "jwt": "xxxx.yyyyy.zzzz"
    }
  }
}

or like this:

{
  "didDocument": {
    "id": "did:web:example:com",
    "authentication": [{
      "id": "did:web:example:com#keys-1",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:web:example:com",
      "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }],
    "service": [{
      "id": "did:web:example:com#vcs",
      "type": "VerifiableCredentialService",
      "serviceEndpoint": "https://example.com/vc/"
    }],
    "proof": {
      "type": "JwtProof2020",
      "jwt": "xxxx.yyyyy.zzzz"
    }
  },
  "didDocumentMetadata": {
    "created": "2019-03-23T06:35:22Z",
    "updated": "2023-08-10T13:40:06Z",
  }
}

and since the JWT has a copy of the payload within itself, do we allow this? This is the equivalent to the LD-Signatures proof format, but for native JWT, where the didDocument is verifiably found in the yyyy section. In the previous method, the verifier needs to manually check if the yyyy section of the JWT matches the didDocument copy.

{
  "didDocument": "xxxx.yyyyy.zzzz"
  "didDocumentMetadata": {
    "created": "2019-03-23T06:35:22Z",
    "updated": "2023-08-10T13:40:06Z",
  }
}

This is important because there is also a CWT (using CBOR), where the same questions have to be asked.

gribneau commented 2 years ago

the JWT has a copy of the payload within itself

I generally prefer detached signatures to avoid duplicating data.

vitorpamplona commented 2 years ago

I don't like the confusion of the proof in the DID Document being a signature about the DID Document while the proof in the DID Document Metadata being about the DID Document as well and not the DID Document Metadata itself.

Maybe we need a different field name when the proof of the DID Document is placed inside the Metadata? didDocumentProof?

msporny commented 2 years ago

I don't like the confusion of the proof in the DID Document being a signature about the DID Document while the proof in the DID Document Metadata being about the DID Document as well and not the DID Document Metadata itself.

-1 to "the proof in the DID Document Metadata being about the DID Document".

Maybe we need a different field name when the proof of the DID Document is placed inside the Metadata? didDocumentProof?

-1 to this as well.

This conversation is reviving all that is terrible about how JWS and JWTs are used in practice. If you want to use proof, that is about signing the object that it's a part of, full stop. Don't do anything else with it, you'll confuse things greatly.

You could add things like didDocumentProof, but again, now you're doing that because JWTs are not capable of being natively embedded... they are external proofs and thus they require you to either wrap your entire data structure you're signing, or contort your data structures to fit into the JWTs-are-the-center-of-the-world data model (by inventing some sort of referencing "the data really lives over there and you must process it in this bespoke special way" solution). You're effectively defining a specific type of digital signature that is only valid in a DID Document Metadata section and making application-layer logic more complex as a result. JWTs are not fit for purpose for this kind of use case (where you are trying to achieve multiple signatures from multiple parties over subsets of data in the same document).

If you're going to use proof, use it in the way it was intended -- embed it in the objects you wanted to sign and you're good. No complex cross-referencing of subparts of a document.

If you want to try and shoe-horn non-embedded signatures into these responses, you're going to have to standardize something to do that, or create a one-off special purpose signature for DID Document Metadata. If you are going to do the latter, I expect there will be strong push-back due to the application layer complexity introduced with those type of half-baked approaches.

The only other alternative for JWT-based signatures that feels possibly workable is embedding the entire object being signed in the metadata, which results in duplication of content.

OR13 commented 2 years ago

This conversation is reviving all that is terrible about how JWS and JWTs are used in practice.

It's also reminding us that VC WG has not yet defined proof.

You could make the entire resolution response be a JWS for JSON + JSON-LD and a CWS for CBOR.

vitorpamplona commented 2 years ago

This conversation is reviving all that is terrible about how JWS and JWTs are used in practice.

I agree, but we can either say that JWS and JWT MUST NOT be used OR we MUST provide the right way for people to use them. Not addressing the issue with finality is terrible for interoperability.

There is also SAML2 Assertions to deal with when the representation is XML

Of course, Linked proofs can be written in XML-LD and CBOR-LD as well. But that would simply follow the same solution for JSON-LD.

msporny commented 2 years ago

You could make the entire resolution response be a JWS for JSON + JSON-LD and a CWS for CBOR.

Please provide a complete proposal so that we can evaluate it. Note the requirements, there are three pieces of information that need to be digitally signed by three different parties, and then carried in the DID Resolution Response.

That proposal exists for Data Integrity (just add a proof to each sub-part of the response you want to have covered).

Of course, Linked proofs can be written in XML-LD and CBOR-LD as well. But that would simply follow the same solution for JSON-LD.

Yep, exactly. So we have at least one solution that is serialization format agnostic (granted, XML-LD doesn't exist yet... but the JSON and CBOR serializations certainly do exist). I suggest we don't try to support XML at this point in time unless we get large customer demand for it.

There is also SAML2 Assertions to deal with when the representation is XML

Who is currently planning to return SAML2 Assertions in XML format in a DID Resolution response?

vitorpamplona commented 2 years ago

Who is currently planning to return SAML2 Assertions in XML format in a DID Resolution response?

I don't want to diverge the discussion, but the XML-loving community is as big as the JSON-loving community. Anyone working with verifiable schema definitions (i.e. XSD) and data transformations (i.e. XSLT) is probably running XML-based services and wouldn't want to change it. JSON just doesn't provide the same level of tooling yet. Personally, I have two customers in that mindset. Since these are just representations of the common data model we are trying to spec out, I would argue the idea here is to be inclusive of people's needs.

peacekeeper commented 2 years ago

That proposal exists for Data Integrity (just add a proof to each sub-part of the response you want to have covered).

It's also reminding us that VC WG has not yet defined proof.

Once VC WG defines proof, it could make sense to register it as an extension property in the DID spec registries, which of course would also serve to show that Data Integrity can be used for other things than VCs :)

vitorpamplona commented 2 years ago

You could make the entire resolution response be a JWS for JSON + JSON-LD and a CWS for CBOR.

Maybe we segment the spec into Data Integrity proofs and other proof packaging needs? (Independent from the representation choice)

OR13 commented 2 years ago

Once VC WG defines proof, it could make sense to register it as an extension property in the DID spec registries, which of course would also serve to show that Data Integrity can be used for other things than VCs :)

Assuming proof is not scoped to "only mean VCs"... 💯