w3c / did-resolution

RELEASED DRAFT: Decentralized Identifier Resolution (DID Resolution) 0.2 Specification
https://w3c.github.io/did-resolution/
Other
14 stars 9 forks source link

Should we be allowed to multi-reference keys through did documents? #55

Open kdenhartog opened 4 years ago

kdenhartog commented 4 years ago

Original issue was authored here: https://github.com/w3c/did-core/issues/301 Migrating the issue to here because this is where it should be properly addressed.

Imagine we've got the following did document structures:

{
  id: "did:example:conglomerate",
  publicKey: [
  {
    id: "did:example:conglomerate#key1",
    type: "EddsaVerificationKey2018",
    base58: "a-base58-encoded-key",
  }],
  assertionMethod: ["did:example:business-unit#key2", "did:example:conglomerate#key1"]
}

and did:example:business-unit did Document looks like this:

{
  id: "did:example:business-unit",
  publicKey: [
  {
    id: "did:example:business-unit#key1",
    type: "EddsaVerificationKey2018",
    base58: "a-base58-encoded-key",
  },
  {
    id: "did:example:business-unit#key2",
    type: "DidUrlKeyReference"
    reference: "did:example:sub-division#key1"
  }
],
  assertionMethod: [ "did:example:business-unit#key2", "did:example:business-unit#key1"]
}

and did:example:sub-division did doc looks like this:

{
  id: "did:example:sub-division",
  publicKey: [
  {
    id: "did:example:sub-division#key1",
    type: "EddsaVerificationKey2018",
    base58: "a-base58-encoded-key",
  }
],
  assertionMethod: [ "did:example:sub-division#key1"]
}

This is essentially the same as this pseudocode:

global var1 = memoryLocation(0x11111111)

callerFunction() => {
const booleanResult = function1(var1); // should return false because function1 negates it
expect(booleanResult).toBe(false);
}

function1(fnVar1) => {
  !function2(fnVar1);
};

function2(fnVar2) => {
 return fnVar2 === var1; // should return true because the memory locations match
}

The use case where I'm imaging this would be used is did:example:conglomerate is a business conglomerate with did:example:business-unit being a business unit of did:example:conglomerate. And did:example:sub-division is a sub-business division of business unit, did:example:business-unit.

What this means is that did:example:bussiness-unit can sign on behalf of did:example:conglomerate without did:example:conglomerate not needing to directly reference every key managed by it's sub-divisions of it's various business units.

However, there's an implicit trust relationship between did:example:conglomerate and it's reference to did:example:business-unit#key2. For example, an attacker could compromise did:example:business-unit and point #key2 to did:example:malicious-attacker#key1 and now malicious-attacker key1 can be used to sign on behalf of did:example:conglomerate.

This is similar to booleanResults expected function1 contract that it will return false because it's negating the result of function2. If it were to stop negating function2, then the logical expectation in the callerFunction would fail.

Should this be allowed?

I tend to lean towards the answer is "No, it shouldn't be allowed" because the implicit trust relationship will be abused at some point and keys will be able to falsely represent did subjects. If others agree with me, then we don't need to make any changes to the specification and this can be close. However, the flip side is multi referencing keys enables easier management of did-documents which can be a very powerful feature. I'm curious, where do others land on the topic?

@dlongley or @msporny I suspect you guys may have thought through this case already because I see JSON-LD examples that do the direct referencing use cases in the spec.