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

Update did key v7 #3

Open
wants to merge 55 commits into
base: initial
Choose a base branch
from
Open

Update did key v7 #3

wants to merge 55 commits into from

Conversation

aljones15
Copy link
Contributor

@aljones15 aljones15 commented Aug 3, 2022

Implements all normative statements from did:key spec v7.

NOTE: this does not address missing did resolver functionality, but hey that spec is still kind of in progress.

Features:

  • es6 exports
  • tons of validators related to did:key normative statements
  • better separation of stuff (although it could be better)
  • better github workflows
  • c8 for coverage

@davidlehn can you look out for es6 related issues with this PR?
@mattcollier can you look out for any issues this might causes when deployed?

Awaits:

digitalbazaar/did-io#63

@aljones15 aljones15 self-assigned this Aug 3, 2022
@aljones15 aljones15 marked this pull request as ready for review August 3, 2022 19:57
Copy link
Member

@msporny msporny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Large PRs like this make it very difficult to do a thorough review (too much information all at once).

There are a number of design concerns in this PR, most notably there are a few places where there aren't a proper separation of concerns (we might eventually have to resolve 20 different types of DIDs, so keep that in mind -- how would you design the system to handle resolving all of those simultaneously. There is some private code that should probably be sorted out into different files (in the very least) or modules (eventually).

lib/DidResolutionResult.js Outdated Show resolved Hide resolved
lib/config.js Outdated
cfg.supportedMethods = ['key', 'v1'];
// a list of which did:methods we supported
// experimental is for tests only
cfg.supportedMethods = ['key', 'v1', 'experimental'];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cfg.supportedMethods = ['key', 'v1', 'experimental'];
cfg.supportedMethods = ['key', 'v1', 'experimental'];

We definitely don't want the experimental DID Method in any of our resolution code -- this is going to go into production and could become an attack vector. Why do we need this here?

Copy link
Contributor Author

@aljones15 aljones15 Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a method that is not key for testing the did:key statement about the method always being key. We could use v1, but this actually shows a larger issue, right now passing in a did:v1 will result in this implementation throwing as it only allows did:key.

lib/config.js Outdated Show resolved Hide resolved
*
* @returns {object} The components of the did.
*/
export const getDidKeyComponents = ({did}) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Abstraction here feels wrong... getting method-specific things should probably be placed in method-specific libraries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree here, this should probably be in did-method-key-js. I made an issue to start discussion on this: digitalbazaar/did-method-key#46

There are a lot of validation stuff included here that should be in did-method-key-js ed25519-verification-key-2020 and possibly x25519.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking this as resolved as getDidKeyComponents is no longer in this library and the way we parse did keys has changed. See digitalbazaar/did-method-key#47 for how did keys are parsed now.

scheme,
method,
// if multibase exists use the version
version: multibase ? version : '1',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it's wrong, you can have version AND multibase exist at the same time. If the code block is right, it feels confusing. Didn't pass the code smell test... something seems off here.

Copy link
Contributor Author

@aljones15 aljones15 Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is exactly what this accounts for did:key:3:zf00 will result in multibase and version being defined at the same time. If multibase is not defined then the string 1 is used as the version. p.s. this results from using the algorithm from the spec that states to separate the components of the identifier using :.

Copy link
Member

@dlongley dlongley Aug 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another problem that needs accounting for here is if someone uses did:key:1:... (version 1 the wrong way) ... that needs to be an error, I'd think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that actually should not error as the version number is a positive integer unless I'm not understanding this correctly.

Comment on lines 10 to 11
this.name = 'InvalidDidError';
this.code = 'invalidDid';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this.name = 'InvalidDidError';
this.code = 'invalidDid';
this.name = 'InvalidDidError';
this.code = 'invalidDid';

Why do we have an error class whose name and code differ only in the first character? Where is this.name used, when an exception is thrown... in which case, would it be easier to read if this were more human readable? This same question applies to everything below.

Copy link
Contributor Author

@aljones15 aljones15 Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so name is a property on any Error in javascript.

new TypeError().name
"TypeError"

Those names follow the convention above, they are usually something like SpecificError and repeat the name of the Class.

On the other hand the error names from the spec following this pattern specificError.

So I decided to not buck trends and use typical Javascript Error names and then use the property code for the errors from the spec. I also might add that using the property code makes our errors less likely to be mutated in ways that could create problems down the road.

p.s. it kind of sucks, but you do have to manually set the name:

class SpecificError extends Error {}
new SpecificError().name
"Error"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like maybe it should be a SyntaxError or something instead, not a new error name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could handle this like this:

class DidKeyError extends Error {
  constructor(message, code) {
    super(message);
    this.name = 'DidKeyError';
    ths.code = code;
  }
}

This would be similar to the jsonld error pattern: https://github.com/digitalbazaar/jsonld.js/blob/main/lib/JsonLdError.js

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@msporny So we're now using DidResolverError or DataError where needed. Can this be considered resolved?

Comment on lines 43 to 44
_validateDidKey({method, version, multibase});
_validateMultibaseEd25519({didKeyComponents});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be broken out into other libraries -- what happens if you don't feed a did:key into this method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hence issues like this: digitalbazaar/ed25519-verification-key-2020#18

The problem is I couldn't get consensus in any realistic time frame to add these errors to this libraries. So the validators are created in really small functions that can be ported over to other libraries when consensus is achieved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There validators have been moved to their respective libraries. See digitalbazaar/did-method-key#47

if(!_convertSearchParamToBoolean({param: enableExperimentalPublicKeyTypes})) {
const verificationFormats = ['Multikey', 'JsonWebKey2020'];
//keyAgreement is an encryption verification method
if(didDocument.type.includes('KeyAgreementKey')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels very dangerous... we shouldn't be doing substring matching on types. We should only be doing whole string matching on types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems fair so changed it here: ef6af7a

lib/validators/index.js Outdated Show resolved Hide resolved
};

export const makeRequest = async ({did}) => {
const basePath = '/1.0/resolve/identifiers/';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required by the DID Resolution spec, feels off to me. /1.0/identifiers/resolve feels a bit better.

Copy link
Contributor Author

@aljones15 aljones15 Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no and not not sure where that came from. The spec gives this example: https://dev.uniresolver.io/1.0/identifiers/

So we can probably just do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the route here: 3364e4a

@aljones15 aljones15 requested review from dlongley and msporny August 12, 2022 17:21
lib/http.js Outdated Show resolved Hide resolved
lib/logger.js Outdated Show resolved Hide resolved
test/mocha/helpers.js Outdated Show resolved Hide resolved
"cross-env": "^7.0.3",
"nyc": "^15.1.0"
"c8": "^7.12.0",
"cross-env": "^7.0.3"
},
"nyc": {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be c8 as nyc is no longer being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make an issue about this one and update it at a later time. This PR is way beyond crammed with comments right now.

#4

Copy link

@JSAssassin JSAssassin Aug 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aljones15 It's just a small change you need to make. You've already removed nyc and added c8 in this PR. All you need to change is "nyc" on L23 to "c8", and you're good.

test/test.config.js Outdated Show resolved Hide resolved
test/test.js Outdated Show resolved Hide resolved
*
* @param {object} options - Options to use.
* @param {string} options.did - The did or didUrl being resolved.
* @param {object} options.didOptions - Options passed to the resolver.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the description be more clear? To me the description for didOptions sounds the same as description for resolverOptions. How are the two different?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an excellent point and I made changes here: e83a8ce

test/mocha/helpers.js Show resolved Hide resolved
@aljones15 aljones15 requested a review from JSAssassin August 17, 2022 22:58
lib/didResolver.js Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants