Skip to content

Commit

Permalink
Support reading JsonWebKey-typed keys.
Browse files Browse the repository at this point in the history
  • Loading branch information
dlongley committed Oct 3, 2024
1 parent 84f727e commit c82f570
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# @digitalbazaar/ed25519-verification-key-2020 ChangeLog

## 4.2.0 - 2024-10-dd

### Added
- Add support for reading `JsonWebKey`-typed keys.

## 4.1.0 - 2022-08-09

### Added
Expand Down
41 changes: 38 additions & 3 deletions lib/Ed25519VerificationKey2020.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*!
* Copyright (c) 2021 Digital Bazaar, Inc. All rights reserved.
* Copyright (c) 2021-2024 Digital Bazaar, Inc. All rights reserved.
*/
import * as base58btc from 'base58-universal';
import * as base64url from 'base64url-universal';
Expand Down Expand Up @@ -92,8 +92,8 @@ export class Ed25519VerificationKey2020 extends LDKeyPair {
if(options.type === 'Ed25519VerificationKey2018') {
return Ed25519VerificationKey2020.fromEd25519VerificationKey2018(options);
}
if(options.type === 'JsonWebKey2020') {
return Ed25519VerificationKey2020.fromJsonWebKey2020(options);
if(options.type === 'JsonWebKey' || options.type === 'JsonWebKey2020') {
return Ed25519VerificationKey2020.fromJsonWebKey(options);
}
return new Ed25519VerificationKey2020(options);
}
Expand Down Expand Up @@ -144,6 +144,26 @@ export class Ed25519VerificationKey2020 extends LDKeyPair {
if(type !== 'JsonWebKey2020') {
throw new TypeError(`Invalid key type: "${type}".`);
}
return Ed25519VerificationKey2020.fromJsonWebKey({
id, type, controller, publicKeyJwk
});
}

/**
* Creates a key pair instance (public key only) from a JsonWebKey object.
*
* @param {object} options - Options hashmap.
* @param {string} options.id - Key id.
* @param {string} options.type - Key suite type.
* @param {string} options.controller - Key controller.
* @param {object} options.publicKeyJwk - JWK object.
*
* @returns {Promise<Ed25519VerificationKey2020>} Resolves with key pair.
*/
static fromJsonWebKey({id, type, controller, publicKeyJwk} = {}) {
if(!(type === 'JsonWebKey' || type === 'JsonWebKey2020')) {
throw new TypeError(`Invalid key type: "${type}".`);
}
if(!publicKeyJwk) {
throw new TypeError('"publicKeyJwk" property is required.');
}
Expand Down Expand Up @@ -331,6 +351,21 @@ export class Ed25519VerificationKey2020 extends LDKeyPair {
new Uint8Array(await ed25519.sha256digest({data})));
}

/**
* Returns the JsonWebKey representation of this key pair.
*
* @returns {Promise<object>} JsonWebKey representation.
*/
async toJsonWebKey() {
return {
'@context': 'https://w3id.org/security/jwk/v1',
id: this.controller + '#' + await this.jwkThumbprint(),
type: 'JsonWebKey',
controller: this.controller,
publicKeyJwk: this.toJwk({publicKey: true})
};
}

/**
* Returns the JsonWebKey2020 representation of this key pair.
*
Expand Down
48 changes: 47 additions & 1 deletion test/Ed25519VerificationKey2020.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*!
* Copyright (c) 2020-2022 Digital Bazaar, Inc. All rights reserved.
* Copyright (c) 2020-2024 Digital Bazaar, Inc. All rights reserved.
*/
import chai from 'chai';
import * as base58btc from 'base58-universal';
Expand Down Expand Up @@ -304,6 +304,52 @@ describe('Ed25519VerificationKey2020', () => {
});
});

describe('JsonWebKey', () => {
it('round trip imports/exports', async () => {
const keyData = {
'@context': 'https://w3id.org/security/jwk/v1',
id: 'did:example:123#kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k',
type: 'JsonWebKey',
controller: 'did:example:123',
publicKeyJwk: {
kty: 'OKP',
crv: 'Ed25519',
x: '11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo'
}
};

const key = await Ed25519VerificationKey2020.from(keyData);

expect(key.controller).to.equal('did:example:123');
expect(key.id).to
.equal('did:example:123#kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k');
expect(key.publicKeyMultibase).to
.equal('z6MktwupdmLXVVqTzCw4i46r4uGyosGXRnR3XjN4Zq7oMMsw');

const exported = await key.toJsonWebKey();

expect(exported).to.eql(keyData);
});

it('computes jwk thumbprint', async () => {
const keyData = {
id: 'did:example:123#_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A',
type: 'JsonWebKey',
controller: 'did:example:123',
publicKeyJwk: {
kty: 'OKP',
crv: 'Ed25519',
x: 'VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ'
}
};

const key = await Ed25519VerificationKey2020.from(keyData);

expect(await key.jwkThumbprint()).to
.equal('_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A');
});
});

describe('JsonWebKey2020', () => {
it('round trip imports/exports', async () => {
const keyData = {
Expand Down

0 comments on commit c82f570

Please sign in to comment.