From 72890e5a7b3d49d5b2a632b390decee2366ea773 Mon Sep 17 00:00:00 2001 From: gabe Date: Mon, 9 Oct 2023 10:11:15 -0700 Subject: [PATCH] almost reconstructed --- packages/dids/src/dht.ts | 83 +++++++++++++++++++++++++++++++-- packages/dids/tests/dht.spec.ts | 16 ++----- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/packages/dids/src/dht.ts b/packages/dids/src/dht.ts index 626418019..61d3f66fe 100644 --- a/packages/dids/src/dht.ts +++ b/packages/dids/src/dht.ts @@ -1,4 +1,4 @@ -import {Jose, Web5Crypto} from '@web5/crypto'; +import {Jose, PublicKeyJwk, Web5Crypto} from '@web5/crypto'; import DHT from 'bittorrent-dht'; import ed from 'bittorrent-dht-sodium'; import brotli from 'brotli-compress'; @@ -210,12 +210,89 @@ export class DidDht { } /** + * @param did The DID of the document * @param encodedPacket A Uint8Array containing the encoded DNS packet */ - public static async fromEncodedDnsPacket(encodedPacket: Buffer): Promise { + public static async fromEncodedDnsPacket(did: string, encodedPacket: Buffer): Promise { const packet = dns.decode(encodedPacket); + const document: Partial = { + id: did, + verificationMethod: [], + service: [] + }; + + const keyLookup = new Map(); + + for (const answer of packet.answers) { + if (answer.type !== 'TXT') continue; + + const dataStr = answer.data?.toString(); + // Extracts 'k' or 's' from "_k0._did" or "_s0._did" + const recordType = answer.name?.split('.')[0].substring(1, 2); + + switch (recordType) { + case 'k': + const {id, t, k} = DidDht.parseTxtData(dataStr); + const crv = t === '0' ? 'Ed25519' : 'secp256k1'; // Map back the key type + const publicKeyJwk = await Jose.keyToJwk({ + crv: crv, + // kty: crv === 'Ed25519' ? 'EC' : 'OKP', + // alg: crv === 'Ed25519' ? 'EdDSA' : 'ES256K', + keyMaterial: Encoder.decodeAsBytes(k, "key"), + keyType: 'public' + }) as PublicKeyJwk; + document.verificationMethod.push({ + id: `${did}#${id}`, + type: 'JsonWebKey2020', + controller: did, + publicKeyJwk: publicKeyJwk, + }); + keyLookup.set(id, answer.name); + break; + case 's': + const {id: sId, t: sType, uri} = DidDht.parseTxtData(dataStr); + document.service.push({ + id: `${did}#${sId}`, + type: sType, + serviceEndpoint: uri + }); + break; + } + } + + // Extract relationships from root record + const rootRecord = packet.answers.find(answer => answer.name === '_did')?.toString().split(';'); + rootRecord?.forEach(record => { + const [type, ids] = record.split('='); + const idList = ids?.split(',').map(id => keyLookup.get(`_${id}._did`)); + switch (type) { + case 'auth': + document.authentication = idList; + break; + case 'asm': + document.assertionMethod = idList; + break; + case 'agm': + document.keyAgreement = idList; + break; + case 'inv': + document.capabilityInvocation = idList; + break; + case 'del': + document.capabilityDelegation = idList; + break; + } + }); + + return document as DidDocument; + } - return null; + public static parseTxtData(data: string): { [key: string]: string } { + return data.split(',').reduce((acc, pair) => { + const [key, value] = pair.split('='); + acc[key] = value; + return acc; + }, {} as { [key: string]: string }); } public static async printEncodedDnsPacket(encodedPacket: Buffer) { diff --git a/packages/dids/tests/dht.spec.ts b/packages/dids/tests/dht.spec.ts index 68a0bcff5..9aec13b2e 100644 --- a/packages/dids/tests/dht.spec.ts +++ b/packages/dids/tests/dht.spec.ts @@ -51,22 +51,14 @@ describe('Codec', async () => { const keySet = { verificationMethodKeys : [vm], } - const {document} = await DidDhtMethod.create({services: services, keySet: keySet}); - const ck = await Jose.jwkToCryptoKey({key: document.verificationMethod[0].publicKeyJwk}) - const hexKey = Buffer.from(ck.material).toString('hex'); - console.log('hexKey', document.verificationMethod[0].id, hexKey); - - const ck2 = await Jose.jwkToCryptoKey({key: document.verificationMethod[1].publicKeyJwk}) - const hexKey2 = Buffer.from(ck2.material).toString('hex'); - console.log('hexKey2', document.verificationMethod[1].id, hexKey2); - + const {did, document} = await DidDhtMethod.create({services: services, keySet: keySet}); console.log('document', JSON.stringify(document)); const encoded = await DidDht.toEncodedDnsPacket(document); - await DidDht.printEncodedDnsPacket(encoded); - // expect(decoded).to.deep.equal(decoded); + const decoded = await DidDht.fromEncodedDnsPacket(did, encoded); + expect(decoded).to.deep.equal(decoded); - // console.log('decoded', JSON.stringify(decoded)); + console.log('decoded', JSON.stringify(decoded)); }); });