-
Notifications
You must be signed in to change notification settings - Fork 52
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
Always set alg and kid on expansion #502
Changes from 15 commits
c0eb781
3e71313
ab67df8
7f8fd7d
24f308e
ec1c910
0c54f87
62cdc2f
44b12b6
e409348
d9608f1
a62c204
07dea7e
847ecb1
fe5d87f
c9493ff
964ca7b
143b293
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -32,6 +32,7 @@ import { extractDidFragment } from '../utils.js'; | |||||||||||||||||
import { DidError, DidErrorCode } from '../did-error.js'; | ||||||||||||||||||
import { DidVerificationRelationship } from '../types/did-core.js'; | ||||||||||||||||||
import { EMPTY_DID_RESOLUTION_RESULT } from '../types/did-resolution.js'; | ||||||||||||||||||
import { getJoseSignatureAlgorithmFromPublicKey } from '@web5/crypto/utils'; | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* Represents a BEP44 message, which is used for storing and retrieving data in the Mainline DHT | ||||||||||||||||||
|
@@ -347,6 +348,15 @@ export enum DidDhtRegisteredKeyType { | |||||||||||||||||
secp256r1 = 2 | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* Private helper that maps did dht registered key types to their corresponding default algorithm identifiers. | ||||||||||||||||||
*/ | ||||||||||||||||||
const KeyTypeToDefaultAlgorithmMap = { | ||||||||||||||||||
[DidDhtRegisteredKeyType.Ed25519] : 'Ed25519', | ||||||||||||||||||
[DidDhtRegisteredKeyType.secp256k1] : 'ES256K', | ||||||||||||||||||
[DidDhtRegisteredKeyType.secp256r1] : 'ES256', | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* Maps {@link https://www.w3.org/TR/did-core/#verification-relationships | DID Core Verification Relationship} | ||||||||||||||||||
* values to the corresponding record name in the DNS packet representation of a DHT DID document. | ||||||||||||||||||
|
@@ -1013,8 +1023,8 @@ export class DidDhtDocument { | |||||||||||||||||
// Process verification methods. | ||||||||||||||||||
case dnsRecordId.startsWith('k'): { | ||||||||||||||||||
// Get the method ID fragment (id), key type (t), Base64URL-encoded public key (k), and | ||||||||||||||||||
// optionally, controller (c) from the decoded TXT record data. | ||||||||||||||||||
const { id, t, k, c } = DidDhtUtils.parseTxtDataToObject(answer.data); | ||||||||||||||||||
// optionally, controller (c) and alg (a) from the decoded TXT record data. | ||||||||||||||||||
const { id, t, k, c, a: parsedAlg } = DidDhtUtils.parseTxtDataToObject(answer.data); | ||||||||||||||||||
|
||||||||||||||||||
// Convert the public key from Base64URL format to a byte array. | ||||||||||||||||||
const publicKeyBytes = Convert.base64Url(k).toUint8Array(); | ||||||||||||||||||
|
@@ -1025,6 +1035,16 @@ export class DidDhtDocument { | |||||||||||||||||
// Convert the public key from a byte array to JWK format. | ||||||||||||||||||
let publicKey = await DidDhtUtils.keyConverter(namedCurve).bytesToPublicKey({ publicKeyBytes }); | ||||||||||||||||||
|
||||||||||||||||||
// DID DHT spec requires `alg` in keys in the DID document | ||||||||||||||||||
publicKey.alg = parsedAlg || getJoseSignatureAlgorithmFromPublicKey(publicKey); | ||||||||||||||||||
|
||||||||||||||||||
// Determine the Key ID (kid): '0' for the identity key or JWK thumbprint for others. | ||||||||||||||||||
if (id === '0') { | ||||||||||||||||||
publicKey.kid = '0'; | ||||||||||||||||||
} else if (publicKey.kid === undefined) { | ||||||||||||||||||
publicKey.kid = await computeJwkThumbprint({ jwk: publicKey }); | ||||||||||||||||||
} | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @decentralgabe just confirmed that
Suggested change
Happy to discuss if I am not making sense! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'm going to update the spec language to always remove the id property |
||||||||||||||||||
|
||||||||||||||||||
// Initialize the `verificationMethod` array if it does not already exist. | ||||||||||||||||||
didDocument.verificationMethod ??= []; | ||||||||||||||||||
|
||||||||||||||||||
|
@@ -1159,7 +1179,12 @@ export class DidDhtDocument { | |||||||||||||||||
let methodId = vm.id.split('#').pop()!; // Remove fragment prefix, if any. | ||||||||||||||||||
idLookup.set(methodId, dnsRecordId); | ||||||||||||||||||
|
||||||||||||||||||
const publicKey = vm.publicKeyJwk; | ||||||||||||||||||
const publicKey = vm.publicKeyJwk!; | ||||||||||||||||||
|
||||||||||||||||||
// Always set `kid` to `0` if `methodId` is `0`, even if `kid` is not given, as a caller/user convenience. | ||||||||||||||||||
if(methodId === '0') { | ||||||||||||||||||
publicKey.kid = '0'; | ||||||||||||||||||
} | ||||||||||||||||||
nitro-neal marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
|
||||||||||||||||||
if (!(publicKey?.crv && publicKey.crv in AlgorithmToKeyTypeMap)) { | ||||||||||||||||||
throw new DidError(DidErrorCode.InvalidPublicKeyType, `Verification method '${vm.id}' contains an unsupported key type: ${publicKey?.crv ?? 'undefined'}`); | ||||||||||||||||||
|
@@ -1177,6 +1202,12 @@ export class DidDhtDocument { | |||||||||||||||||
// Define the data for the DNS TXT record. | ||||||||||||||||||
const txtData = [`id=${methodId}`, `t=${keyType}`, `k=${publicKeyBase64Url}`]; | ||||||||||||||||||
|
||||||||||||||||||
// Only set the algorithm property (`a`) if it differs from the default algorithm for the key type. | ||||||||||||||||||
const algorithmUsedByKey = getJoseSignatureAlgorithmFromPublicKey(publicKey); | ||||||||||||||||||
if(algorithmUsedByKey !== KeyTypeToDefaultAlgorithmMap[keyType]) { | ||||||||||||||||||
txtData.push(`a=${algorithmUsedByKey}`); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Add the controller property, if set to a value other than the Identity Key (DID Subject). | ||||||||||||||||||
if (vm.controller !== didDocument.id) txtData.push(`c=${vm.controller}`); | ||||||||||||||||||
|
||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sanity:
getJoseSignatureAlgorithmFromPublicKey()
does not seem to returnEd25519
that will be expected of vector 3.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
am I using this correctly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the alg is always there for our jwks, but is that not necessarily the case for outside jwks inside the did dht??
if the alg is always there we can just do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get
if(parsedAlg) { publicKey.alg = parsedAlg }
, ifparsedAlg
is always defined, then there is nothing do right? since:const { id, t, k, c, a: parsedAlg } = DidDhtUtils.parseTxtDataToObject(answer.data);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parsed alg will not always be defined, but publicKey.alg is always defined