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

Refactor @web5/dids to support first class Key Management #393

Merged
merged 39 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
073c0f3
Update Web5 Test Vectors to latest
frankhinek Jan 10, 2024
22c001f
Fix issue with c8 not reporting code coverage and bump version
frankhinek Jan 10, 2024
e17d5e8
Remove unnecessary option in crypto tsconfig and enable strict mode f…
frankhinek Jan 10, 2024
09083b2
Add JWK Set to crypto package
frankhinek Jan 12, 2024
7b51b76
Add did:jwk and did:web implementations
frankhinek Jan 12, 2024
1187a09
Add utility type to @web5/common
frankhinek Jan 15, 2024
b8cd77e
Improve DID Utility functions
frankhinek Jan 15, 2024
b79dfff
Add FixedLengthArray utility type
frankhinek Jan 21, 2024
42bae59
Add support for Base32Z to Convert utility
frankhinek Jan 21, 2024
197181c
Improve JWK type
frankhinek Jan 21, 2024
2da26ee
Add InferKeyGeneratorAlgorithm utility type
frankhinek Jan 21, 2024
cf4cb33
Remove did-resolver dependency
frankhinek Jan 21, 2024
80ae0bd
Temporarily disable old implementations
frankhinek Jan 21, 2024
de2cf33
Update DID JWK and DHT implementations
frankhinek Jan 22, 2024
6eff583
Rename createFromKeys to fromKeys and change default publishing behavior
frankhinek Jan 22, 2024
fcc2796
Update JWK and DHT implementations
frankhinek Jan 24, 2024
0b0693f
Rename DidKeySet to PortableDid and add uri
frankhinek Jan 25, 2024
be13b71
Reorganize tests and reintroduce DidResolver
frankhinek Jan 25, 2024
d14076a
Update package-lock.json
frankhinek Jan 25, 2024
4148742
Rename P256 to Secp256r1 and add minimal tests
frankhinek Jan 25, 2024
53aa79b
Add docs for undocumented methods
frankhinek Jan 25, 2024
00700f7
Finish reintroducing DID resolvers
frankhinek Jan 25, 2024
cfb8a44
Support secp256k1 as an algorithm identifier for generateKey()
frankhinek Jan 26, 2024
43f2507
Improve support for secp256r1
frankhinek Jan 26, 2024
0bfbc5b
Rename to LocalKeyManager & AwsKeyManager and improve docs
frankhinek Jan 26, 2024
b7b8d79
Fix Ed25519.validatePublicKey method signature
frankhinek Jan 27, 2024
11b69ed
Refactor of DID Key
frankhinek Jan 27, 2024
7ec833e
Complete implementation of DID Key
frankhinek Jan 29, 2024
29a27ab
Add KeyCompressor type to @web5/crypto
frankhinek Jan 31, 2024
64120f0
Complete refactor of DidIon
frankhinek Jan 31, 2024
4464e53
Complete adding secp256r1 test vectors
frankhinek Jan 31, 2024
2ebbd77
Remove old dependencies and bump versions
frankhinek Jan 31, 2024
6cb1abb
Resolve package dependency issue
frankhinek Jan 31, 2024
c26d27e
Remove old test-vectors directory
frankhinek Jan 31, 2024
38ba056
Remove references to tags in the XChaCha20Poly1305 comments
frankhinek Jan 31, 2024
258446c
Remove duplication from DidDhtUtils.identifierToIdentityKey()
frankhinek Jan 31, 2024
53b6712
Correct typo in comments
frankhinek Jan 31, 2024
0a97f05
Update crypto README
frankhinek Feb 1, 2024
a3e4448
Correct typo, add DHT test, and remove unused file
frankhinek Feb 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,592 changes: 853 additions & 739 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions packages/agent/.c8rc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
".js"
],
"include": [
"tests/compiled/src/**"
"tests/compiled/**/src/**"
],
"exclude": [
"tests/compiled/src/index.js",
"tests/compiled/src/types.js",
"tests/compiled/src/types/**"
"tests/compiled/**/src/index.js",
"tests/compiled/**/src/types.js",
"tests/compiled/**/src/types/**"
],
"reporter": [
"cobertura",
Expand Down
7 changes: 4 additions & 3 deletions packages/agent/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@web5/agent",
"version": "0.2.5",
"version": "0.2.6",
"type": "module",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand Down Expand Up @@ -69,7 +69,7 @@
},
"dependencies": {
"@tbd54566975/dwn-sdk-js": "0.2.10",
"@web5/common": "0.2.2",
"@web5/common": "0.2.3",
"@web5/crypto": "0.2.2",
"@web5/dids": "0.2.4",
"level": "8.0.0",
Expand All @@ -81,6 +81,7 @@
"@playwright/test": "1.40.1",
"@types/chai": "4.3.6",
"@types/chai-as-promised": "7.1.5",
"@types/dns-packet": "5.6.4",
"@types/eslint": "8.44.2",
"@types/mocha": "10.0.1",
"@types/readable-stream": "4.0.6",
Expand All @@ -89,7 +90,7 @@
"@typescript-eslint/parser": "6.4.0",
"@web/test-runner": "0.18.0",
"@web/test-runner-playwright": "0.11.0",
"c8": "8.0.1",
"c8": "9.0.0",
"chai": "4.3.10",
"chai-as-promised": "7.1.1",
"esbuild": "0.19.8",
Expand Down
8 changes: 4 additions & 4 deletions packages/api/.c8rc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
".js"
],
"include": [
"tests/compiled/src/**"
"tests/compiled/**/src/**"
],
"exclude": [
"tests/compiled/src/index.js",
"tests/compiled/src/types.js",
"tests/compiled/src/types/**"
"tests/compiled/**/src/index.js",
"tests/compiled/**/src/types.js",
"tests/compiled/**/src/types/**"
],
"reporter": [
"cobertura",
Expand Down
10 changes: 5 additions & 5 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@
},
"dependencies": {
"@tbd54566975/dwn-sdk-js": "0.2.10",
"@web5/agent": "0.2.5",
"@web5/common": "0.2.2",
"@web5/agent": "0.2.6",
"@web5/common": "0.2.3",
"@web5/crypto": "0.2.2",
"@web5/dids": "0.2.4",
"@web5/user-agent": "0.2.5",
"@web5/user-agent": "0.2.6",
"level": "8.0.0",
"ms": "2.1.3",
"readable-stream": "4.4.2",
Expand All @@ -100,7 +100,7 @@
"@typescript-eslint/parser": "6.4.0",
"@web/test-runner": "0.18.0",
"@web/test-runner-playwright": "0.11.0",
"c8": "8.0.1",
"c8": "9.0.0",
"chai": "4.3.10",
"chai-as-promised": "7.1.1",
"esbuild": "0.19.8",
Expand All @@ -112,7 +112,7 @@
"playwright": "1.40.1",
"rimraf": "4.4.0",
"sinon": "16.1.3",
"source-map-loader": "4.0.1",
"source-map-loader": "4.0.2",
"typescript": "5.1.6"
}
}
8 changes: 4 additions & 4 deletions packages/common/.c8rc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
".js"
],
"include": [
"tests/compiled/src/**"
"tests/compiled/**/src/**"
],
"exclude": [
"tests/compiled/src/index.js",
"tests/compiled/src/types.js",
"tests/compiled/src/types/**"
"tests/compiled/**/src/index.js",
"tests/compiled/**/src/types.js",
"tests/compiled/**/src/types/**"
],
"reporter": [
"cobertura",
Expand Down
4 changes: 2 additions & 2 deletions packages/common/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@web5/common",
"version": "0.2.2",
"version": "0.2.3",
"type": "module",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand Down Expand Up @@ -83,7 +83,7 @@
"@typescript-eslint/parser": "6.4.0",
"@web/test-runner": "0.18.0",
"@web/test-runner-playwright": "0.11.0",
"c8": "8.0.1",
"c8": "9.0.0",
"chai": "4.3.10",
"chai-as-promised": "7.1.1",
"esbuild": "0.19.8",
Expand Down
21 changes: 21 additions & 0 deletions packages/common/src/convert.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Multibase } from 'multiformats';

import { base32z } from 'multiformats/bases/base32';
import { base58btc } from 'multiformats/bases/base58';
import { base64url } from 'multiformats/bases/base64';

Expand Down Expand Up @@ -28,6 +29,10 @@ export class Convert {
return new Convert(data, 'AsyncIterable');
}

static base32Z(data: string): Convert {
return new Convert(data, 'Base32Z');
}

static base58Btc(data: string): Convert {
return new Convert(data, 'Base58Btc');
}
Expand Down Expand Up @@ -131,6 +136,18 @@ export class Convert {
}
}

toBase32Z(): string {
switch (this.format) {

case 'Uint8Array': {
return base32z.baseEncode(this.data);
}

default:
throw new TypeError(`Conversion from ${this.format} to Base64Z is not supported.`);
}
}

toBase58Btc(): string {
switch (this.format) {

Expand Down Expand Up @@ -357,6 +374,10 @@ export class Convert {
return new Uint8Array(this.data);
}

case 'Base32Z': {
return base32z.baseDecode(this.data);
}

case 'Base58Btc': {
return base58btc.baseDecode(this.data);
}
Expand Down
117 changes: 116 additions & 1 deletion packages/common/src/type-utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,67 @@
/**
* Represents an array of a fixed length, preventing modifications to its size.
*
* The `FixedLengthArray` utility type transforms a standard array into a variant where
* methods that could alter the length are omitted. It leverages TypeScript's advanced types,
* such as conditional types and mapped types, to ensure that the array cannot be resized
* through methods like `push`, `pop`, `splice`, `shift`, and `unshift`. The utility type
* maintains all other characteristics of a standard array, including indexing, iteration,
* and type checking for its elements.
*
* Note: The type does not prevent direct assignment to indices, even if it would exceed
* the original length. However, such actions would lead to TypeScript type errors.
*
* @example
* ```ts
* // Declare a variable with a type of fixed-length array of three strings.
* let myFixedLengthArray: FixedLengthArray< [string, string, string]>;
*
* // Array declaration tests
* myFixedLengthArray = [ 'a', 'b', 'c' ]; // OK
* myFixedLengthArray = [ 'a', 'b', 123 ]; // TYPE ERROR
* myFixedLengthArray = [ 'a' ]; // LENGTH ERROR
* myFixedLengthArray = [ 'a', 'b' ]; // LENGTH ERROR
*
* // Index assignment tests
* myFixedLengthArray[1] = 'foo'; // OK
* myFixedLengthArray[1000] = 'foo'; // INVALID INDEX ERROR
*
* // Methods that mutate array length
* myFixedLengthArray.push('foo'); // MISSING METHOD ERROR
* myFixedLengthArray.pop(); // MISSING METHOD ERROR
*
* // Direct length manipulation
* myFixedLengthArray.length = 123; // READ-ONLY ERROR
*
* // Destructuring
* let [ a ] = myFixedLengthArray; // OK
* let [ a, b ] = myFixedLengthArray; // OK
* let [ a, b, c ] = myFixedLengthArray; // OK
* let [ a, b, c, d ] = myFixedLengthArray; // INVALID INDEX ERROR
* ```
*
* @template T extends any[] - The array type to be transformed.
*/
export type FixedLengthArray<T extends any[]> =
Pick<T, Exclude<keyof T, ArrayLengthMutationKeys>>
& {
/**
* Custom iterator for the `FixedLengthArray` type.
*
* This iterator allows the `FixedLengthArray` to be used in standard iteration
* contexts, such as `for...of` loops and spread syntax. It ensures that even though
* the array is of a fixed length with disabled mutation methods, it still retains
* iterable behavior similar to a regular array.
*
* @returns An IterableIterator for the array items.
*/
[Symbol.iterator]: () => IterableIterator<ArrayItems<T>>
};

/** Helper types for {@link FixedLengthArray} */
type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift' | number;
type ArrayItems<T extends Array<any>> = T extends Array<infer TItems> ? TItems : never;

/**
* isArrayBufferSlice
*
Expand Down Expand Up @@ -72,6 +136,34 @@ export function isDefined<T>(arg: T): arg is Exclude<T, null | undefined> {
return arg !== null && typeof arg !== 'undefined';
}

/**
* Utility type that transforms a type `T` to have only certain keys `K` as required, while the
* rest remain optional, except for keys specified in `O`, which are omitted entirely.
*
* This type is useful when you need a variation of a type where only specific properties are
* required, and others are either optional or not included at all. It allows for more flexible type
* definitions based on existing types without the need to redefine them.
*
* @template T - The original type to be transformed.
* @template K - The keys of `T` that should be required.
* @template O - The keys of `T` that should be omitted from the resulting type (optional).
*
* @example
* ```ts
* // Given an interface
* interface Example {
* requiredProp: string;
* optionalProp?: number;
* anotherOptionalProp?: boolean;
* }
*
* // Making 'optionalProp' required and omitting 'anotherOptionalProp'
* type ModifiedExample = RequireOnly<Example, 'optionalProp', 'anotherOptionalProp'>;
* // Result: { requiredProp?: string; optionalProp: number; }
* ```
*/
export type RequireOnly<T, K extends keyof T, O extends keyof T = never> = Required<Pick<T, K>> & Omit<Partial<T>, O>;

/**
* universalTypeOf
*
Expand Down Expand Up @@ -114,4 +206,27 @@ export function universalTypeOf(value: unknown) {
const [_, type] = match as RegExpMatchArray;

return type;
}
}

/**
* Utility type to extract the type resolved by a Promise.
*
* This type unwraps the type `T` from `Promise<T>` if `T` is a Promise, otherwise returns `T` as
* is. It's useful in situations where you need to handle the type returned by a promise-based
* function in a synchronous context, such as defining types for test vectors or handling return
* types in non-async code blocks.
*
* @template T - The type to unwrap from the Promise.
*
* @example
* ```ts
* // For a Promise type, it extracts the resolved type.
* type AsyncNumber = Promise<number>;
* type UnwrappedNumber = UnwrapPromise<AsyncNumber>; // number
*
* // For a non-Promise type, it returns the type as is.
* type StringValue = string;
* type UnwrappedString = UnwrapPromise<StringValue>; // string
* ```
*/
export type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
7 changes: 1 addition & 6 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,4 @@ export interface KeyValueStore<K, V> {
* @returns A promise that resolves when the value has been set.
*/
set(key: K, value: V): Promise<void>;
}

/**
* Represents an object type where a subset of keys are required and everything else is optional.
*/
export type RequireOnly<T, K extends keyof T, O extends keyof T = never> = Required<Pick<T, K>> & Omit<Partial<T>, O>;
}
36 changes: 36 additions & 0 deletions packages/common/tests/convert.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,23 @@ describe('Convert', () =>{
});
});

describe('from: Base64Z', () => {
it('to: Uint8Array', () => {
// Test Vector 1.
let input = '5umembtazeybqcd7grysfp711g1z56wzo8irzhae494hh58zguhy';
let output = new Uint8Array([
220, 214, 133, 134, 56, 186, 0, 23,
48, 125, 49, 1, 98, 183, 178, 145,
165, 125, 250, 151, 129, 234, 75, 243,
8, 215, 245, 206, 108, 247, 52, 248
]);

let result = Convert.base32Z(input).toUint8Array();

expect(result).to.deep.equal(output);
});
});

describe('from: BufferSource', () => {
it('to: ArrayBuffer', () => {
// Test Vector 1 - BufferSource is Uint8Array.
Expand Down Expand Up @@ -500,6 +517,21 @@ describe('Convert', () =>{
expect(result).to.deep.equal(output);
});

it('to: Base32Z', () => {
// Test Vector 1.
let input = new Uint8Array([
220, 214, 133, 134, 56, 186, 0, 23,
48, 125, 49, 1, 98, 183, 178, 145,
165, 125, 250, 151, 129, 234, 75, 243,
8, 215, 245, 206, 108, 247, 52, 248
]);
let output = '5umembtazeybqcd7grysfp711g1z56wzo8irzhae494hh58zguhy';

let result = Convert.uint8Array(input).toBase32Z();

expect(result).to.deep.equal(output);
});

it('to: Base58Btc', () => {
// Test Vector 1.
let input = new Uint8Array([51, 52, 53]);
Expand Down Expand Up @@ -567,6 +599,10 @@ describe('Convert', () =>{
}
});

it('toBase32Z() throw an error', () => {
expect(() => unsupported.toBase32Z()).to.throw(TypeError, 'not supported');
});

it('toBase58Btc() throw an error', () => {
expect(() => unsupported.toBase58Btc()).to.throw(TypeError, 'not supported');
});
Expand Down
Loading
Loading