Skip to content

Commit

Permalink
For DID, always use the public key of the address as authentication, …
Browse files Browse the repository at this point in the history
…assertionMethod, and capabilityInvocation.

It can be reconfigured by a self-association (requires Titanium).
Fix indexing assertion method.
  • Loading branch information
jasny committed Sep 5, 2022
1 parent 4090c09 commit 28dedce
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 23 deletions.
69 changes: 65 additions & 4 deletions src/identity/identity.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe('IdentityService', () => {
chainId: 'T',
address: '3N6mZMgGqYn9EVAR2Vbf637iej4fFipECq8',
ed25519PublicKey: '6wx5nshSAkF7GEgxZRet86XnqSog3k3DzkyCaBKStiUd',
x25519PublicKey: '8mKEv5qc9WV6vdBFyrFcHW7Jhdz89ypzB9bp7m7Sx3Dx',
};

const recipient = {
Expand Down Expand Up @@ -175,8 +176,17 @@ describe('IdentityService', () => {
blockchainAccountId: `${recipient.address}@lto:${recipient.chainId}`,
},
],
authentication: [`did:lto:${recipient.address}#sign`],
assertionMethod: [`did:lto:${recipient.address}#sign`],
authentication: [
`did:lto:${sender.address}#sign`,
`did:lto:${recipient.address}#sign`,
],
assertionMethod: [
`did:lto:${sender.address}#sign`,
`did:lto:${recipient.address}#sign`,
],
capabilityInvocation: [
`did:lto:${sender.address}#sign`,
],
keyAgreement: [
{
id: `did:lto:${recipient.address}#encrypt`,
Expand All @@ -189,6 +199,49 @@ describe('IdentityService', () => {
});
});

test('should resolve the identity with reconfigured default verification method', async () => {
const spies = spy();

spies.verificationMethod.getMethodsFor = jest
.spyOn(verificationMethodService, 'getMethodsFor')
.mockImplementation(async (address: string) => {
const relationships = 0x0105; // authentication, key agreement

return [new VerificationMethod(relationships, address, sender.address, 123456)];
});

const did = await identityService.resolve(sender.address);

expect(spies.storage.getPublicKey.mock.calls.length).toBe(2);
expect(spies.verificationMethod.getMethodsFor.mock.calls.length).toBe(1);

expect(did).toEqual({
'@context': 'https://www.w3.org/ns/did/v1',
id: `did:lto:${sender.address}`,
verificationMethod: [
{
id: `did:lto:${sender.address}#sign`,
type: 'Ed25519VerificationKey2018',
controller: `did:lto:${sender.address}`,
publicKeyBase58: sender.ed25519PublicKey,
blockchainAccountId: `${sender.address}@lto:${sender.chainId}`,
},
],
authentication: [
`did:lto:${sender.address}#sign`,
],
keyAgreement: [
{
id: `did:lto:${sender.address}#encrypt`,
type: 'X25519KeyAgreementKey2019',
controller: `did:lto:${sender.address}`,
publicKeyBase58: sender.x25519PublicKey,
blockchainAccountId: `${sender.address}@lto:${sender.chainId}`,
},
],
});
});

test('should resolve the identity with MULTIPLE additional verification methods', async () => {
const spies = spy();

Expand Down Expand Up @@ -235,8 +288,15 @@ describe('IdentityService', () => {
blockchainAccountId: `${secondRecipient.address}@lto:${secondRecipient.chainId}`,
},
],
authentication: [`did:lto:${recipient.address}#sign`, `did:lto:${secondRecipient.address}#sign`],
assertionMethod: [`did:lto:${recipient.address}#sign`, `did:lto:${secondRecipient.address}#sign`],
authentication: [
`did:lto:${sender.address}#sign`,
`did:lto:${recipient.address}#sign`,
`did:lto:${secondRecipient.address}#sign`,
],
assertionMethod: [
`did:lto:${sender.address}#sign`,
`did:lto:${recipient.address}#sign`,
],
keyAgreement: [
{
id: `did:lto:${recipient.address}#encrypt`,
Expand All @@ -253,6 +313,7 @@ describe('IdentityService', () => {
blockchainAccountId: `${secondRecipient.address}@lto:${secondRecipient.chainId}`,
},
],
capabilityInvocation: [`did:lto:${sender.address}#sign`],
capabilityDelegation: [`did:lto:${secondRecipient.address}#sign`],
});
});
Expand Down
18 changes: 13 additions & 5 deletions src/identity/identity.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,8 @@ export class IdentityService {
didDocument.alsoKnownAs = alsoKnownAs;
}

didDocument.authentication = [`did:lto:${address}#sign`];
didDocument.assertionMethod = [`did:lto:${address}#sign`];
didDocument.capabilityInvocation = [`did:lto:${address}#sign`];

const verificationMethods = await this.verificationMethodService.getMethodsFor(address);
let hasConfiguredOwn = false;

for (const verificationMethod of verificationMethods) {
const {publicKey: recipientPublicKey, keyType: recipientKeyType} =
Expand All @@ -136,7 +133,12 @@ export class IdentityService {
}

const didVerificationMethod = verificationMethod.asDidMethod(recipientPublicKey, KeyType[recipientKeyType]);
didDocument.verificationMethod.push(didVerificationMethod);

if (verificationMethod.recipient !== verificationMethod.sender) {
didDocument.verificationMethod.push(didVerificationMethod);
} else {
hasConfiguredOwn = true;
}

if (verificationMethod.isAuthentication()) {
didDocument.authentication = didDocument.authentication
Expand Down Expand Up @@ -177,6 +179,12 @@ export class IdentityService {
}
}

if (!hasConfiguredOwn) {
didDocument.authentication = [`did:lto:${address}#sign`, ...(didDocument.authentication || [])];
didDocument.assertionMethod = [`did:lto:${address}#sign`, ...(didDocument.assertionMethod || [])];
didDocument.capabilityInvocation = [`did:lto:${address}#sign`, ...(didDocument.capabilityInvocation || [])];
}

return didDocument;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export enum MethodMap {
authentication = 0x0101,
assertionMethod = 0x0101,
assertionMethod = 0x0102,
keyAgreement = 0x0104,
capabilityInvocation = 0x0108,
capabilityDelegation = 0x0110,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,19 @@ export class VerificationMethod {
};
}

public isAuthentication() {
const result = MethodMap.authentication | this.relationships;
return result == this.relationships;
public isAuthentication(): boolean {
return (this.relationships & MethodMap.authentication) === MethodMap.authentication;
}
public isAssertionMethod() {
const result = MethodMap.assertionMethod | this.relationships;
return result == this.relationships;
public isAssertionMethod(): boolean {
return (this.relationships & MethodMap.assertionMethod) === MethodMap.assertionMethod;
}
public isKeyAgreement() {
const result = MethodMap.keyAgreement | this.relationships;
return result == this.relationships;
public isKeyAgreement(): boolean {
return (this.relationships & MethodMap.keyAgreement) === MethodMap.keyAgreement;
}
public isCapabilityInvocation() {
const result = MethodMap.capabilityInvocation | this.relationships;
return result == this.relationships;
return (this.relationships & MethodMap.capabilityInvocation) === MethodMap.capabilityInvocation;
}
public isCapabilityDelegation() {
const result = MethodMap.capabilityDelegation | this.relationships;
return result == this.relationships;
return (this.relationships & MethodMap.capabilityDelegation) === MethodMap.capabilityDelegation;
}
}

0 comments on commit 28dedce

Please sign in to comment.