Fork of github.com/did-method-plc/did-method-plc
1import * as crypto from '@atproto/crypto'
2import * as t from './types'
3import { UnsupportedKeyError } from './error'
4import { ParsedMultikey } from '@atproto/crypto'
5
6export const formatDidDoc = (data: t.DocumentData): t.DidDocument => {
7 const context = [
8 'https://www.w3.org/ns/did/v1',
9 'https://w3id.org/security/multikey/v1',
10 ]
11
12 const verificationMethods: VerificationMethod[] = []
13 for (const [keyid, key] of Object.entries(data.verificationMethods)) {
14 const info = formatKeyAndContext(key)
15 if (info.context && !context.includes(info.context)) {
16 context.push(info.context)
17 }
18 verificationMethods.push({
19 id: `${data.did}#${keyid}`,
20 type: info.type,
21 controller: data.did,
22 publicKeyMultibase: info.publicKeyMultibase,
23 })
24 }
25
26 const services: Service[] = []
27 for (const [serviceId, service] of Object.entries(data.services)) {
28 services.push({
29 id: `#${serviceId}`,
30 type: service.type,
31 serviceEndpoint: service.endpoint,
32 })
33 }
34
35 return {
36 '@context': context,
37 id: data.did,
38 alsoKnownAs: data.alsoKnownAs,
39 verificationMethod: verificationMethods,
40 service: services,
41 }
42}
43
44type VerificationMethod = {
45 id: string
46 type: string
47 controller: string
48 publicKeyMultibase: string
49}
50
51type Service = {
52 id: string
53 type: string
54 serviceEndpoint: string
55}
56
57type KeyAndContext = {
58 context?: string
59 type: string
60 publicKeyMultibase: string
61}
62
63const formatKeyAndContext = (key: string): KeyAndContext => {
64 let keyInfo: ParsedMultikey
65 try {
66 keyInfo = crypto.parseDidKey(key)
67 } catch (err) {
68 return {
69 // we can't specify a context for a key type we don't recognize
70 type: 'Multikey',
71 publicKeyMultibase: key.replace(/^(did:key:)/, ''),
72 }
73 }
74 const { jwtAlg } = keyInfo
75
76 if (jwtAlg === crypto.P256_JWT_ALG) {
77 return {
78 context: 'https://w3id.org/security/suites/ecdsa-2019/v1',
79 type: 'Multikey',
80 publicKeyMultibase: key.replace(/^(did:key:)/, ''),
81 }
82 } else if (jwtAlg === crypto.SECP256K1_JWT_ALG) {
83 return {
84 context: 'https://w3id.org/security/suites/secp256k1-2019/v1',
85 type: 'Multikey',
86 publicKeyMultibase: key.replace(/^(did:key:)/, ''),
87 }
88 }
89
90 // this codepath might seem unreachable/redundant, but it's possible
91 // parseDidKey() supports more key formats in future, before this function
92 // can be updated likewise
93 return {
94 // we can't specify a context for a key type we don't recognize
95 type: 'Multikey',
96 publicKeyMultibase: key.replace(/^(did:key:)/, ''),
97 }
98}