@sphereon/ssi-sdk-ext.did-resolver-key 0.10.2-next.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +10 -0
  3. package/dist/drivers/bls12381g2.d.ts +8 -0
  4. package/dist/drivers/bls12381g2.d.ts.map +1 -0
  5. package/dist/drivers/bls12381g2.js +49 -0
  6. package/dist/drivers/bls12381g2.js.map +1 -0
  7. package/dist/drivers/ed25519.d.ts +8 -0
  8. package/dist/drivers/ed25519.d.ts.map +1 -0
  9. package/dist/drivers/ed25519.js +118 -0
  10. package/dist/drivers/ed25519.js.map +1 -0
  11. package/dist/drivers/jwk.jcs.d.ts +8 -0
  12. package/dist/drivers/jwk.jcs.d.ts.map +1 -0
  13. package/dist/drivers/jwk.jcs.js +23 -0
  14. package/dist/drivers/jwk.jcs.js.map +1 -0
  15. package/dist/drivers/secp256k1.d.ts +8 -0
  16. package/dist/drivers/secp256k1.d.ts.map +1 -0
  17. package/dist/drivers/secp256k1.js +49 -0
  18. package/dist/drivers/secp256k1.js.map +1 -0
  19. package/dist/drivers/secp256r1.d.ts +24 -0
  20. package/dist/drivers/secp256r1.d.ts.map +1 -0
  21. package/dist/drivers/secp256r1.js +100 -0
  22. package/dist/drivers/secp256r1.js.map +1 -0
  23. package/dist/drivers/secp384r1.d.ts +24 -0
  24. package/dist/drivers/secp384r1.d.ts.map +1 -0
  25. package/dist/drivers/secp384r1.js +100 -0
  26. package/dist/drivers/secp384r1.js.map +1 -0
  27. package/dist/drivers/secp521r1.d.ts +23 -0
  28. package/dist/drivers/secp521r1.d.ts.map +1 -0
  29. package/dist/drivers/secp521r1.js +88 -0
  30. package/dist/drivers/secp521r1.js.map +1 -0
  31. package/dist/index.d.ts +8 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +94 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/types.d.ts +14 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +6 -0
  38. package/dist/types.js.map +1 -0
  39. package/package.json +55 -0
  40. package/src/__tests__/__snapshots__/secp256r1.test.ts.snap +218 -0
  41. package/src/__tests__/__snapshots__/secp384r1.test.ts.snap +249 -0
  42. package/src/__tests__/__snapshots__/secp521r1.test.ts.snap +280 -0
  43. package/src/__tests__/fixtures/bls_did_doc.json +29 -0
  44. package/src/__tests__/fixtures/ed25519-x25519.json +240 -0
  45. package/src/__tests__/fixtures/ed25519_did_doc.json +24 -0
  46. package/src/__tests__/fixtures/jwk_jcs_did_doc.json +35 -0
  47. package/src/__tests__/fixtures/secp256k1_did_doc.json +21 -0
  48. package/src/__tests__/key_resolver.test.ts +44 -0
  49. package/src/__tests__/secp256r1.test.ts +207 -0
  50. package/src/__tests__/secp384r1.test.ts +233 -0
  51. package/src/__tests__/secp521r1.test.ts +202 -0
  52. package/src/drivers/bls12381g2.ts +24 -0
  53. package/src/drivers/ed25519.ts +115 -0
  54. package/src/drivers/jwk.jcs.ts +28 -0
  55. package/src/drivers/secp256k1.ts +25 -0
  56. package/src/drivers/secp256r1.ts +82 -0
  57. package/src/drivers/secp384r1.ts +82 -0
  58. package/src/drivers/secp521r1.ts +68 -0
  59. package/src/index.ts +65 -0
  60. package/src/types.ts +22 -0
@@ -0,0 +1,202 @@
1
+ // Brent Shambaugh <brent.shambaugh@gmail.com>. 2021.
2
+
3
+ import * as varint from 'varint'
4
+ import * as mapper from '../drivers/secp521r1'
5
+ import * as u8a from 'uint8arrays'
6
+ import { base58btc } from 'multiformats/bases/base58'
7
+
8
+ describe('Secp521r1 mapper', () => {
9
+ /* const mf = await import('multiformats/bases/base58')
10
+ const base58btc = mf.base58btc*/
11
+ // testing the key from the did:key from the compressed public key
12
+ it('successfully resolves the document from did', async () => {
13
+ const id = 'z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f'
14
+ const multiformatPubKey = base58btc.decode(id)
15
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
16
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
17
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
18
+ expect(doc).toMatchSnapshot()
19
+ })
20
+
21
+ // testing the key from the did:key from the compressed public key
22
+ it('successfully resolves the document from did', async () => {
23
+ const id = 'z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7'
24
+ const multiformatPubKey = base58btc.decode(id)
25
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
26
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
27
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
28
+ expect(doc).toMatchSnapshot()
29
+ })
30
+
31
+ // testing the key from the did:key from the compressed public key
32
+ it('successfully resolves the document from did', async () => {
33
+ const id = 'z2J9gaYaTUV4Ps5GYNNMm4nAyj4pGxd3Nh2zyeFjpEy631ZJ3dYfTDZ68GAhYbNuTn2eMAhKd6hhbzfxLn66vrQ6992jCSxX'
34
+ const multiformatPubKey = base58btc.decode(id)
35
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
36
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
37
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
38
+ expect(doc).toMatchSnapshot()
39
+ })
40
+
41
+ // testing the key from the did:key from the compressed public key
42
+ it('successfully resolves the document from did', async () => {
43
+ const id = 'z2J9gcGTLNfNooB4Mvx7qeEBccSWARJ3y1xjwbMH9A7ra6oq71rD1daVSVm2YmjUZRWJms18QTZXTnhaH5ihiKiVaG52cuAs'
44
+ const multiformatPubKey = base58btc.decode(id)
45
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
46
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
47
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
48
+ expect(doc).toMatchSnapshot()
49
+ })
50
+
51
+ // testing the key from the did:key from the compressed public key
52
+ it('successfully resolves the document from did', async () => {
53
+ const id = 'z2J9gaZDkUkcV4j5nMPp4dzks3vygMwKRSZWg9j7HNYcR5JLRu361LN6TwrBK3r19VisFYUZEGEXhqqffAprjgmVtCwfCUB1'
54
+ const multiformatPubKey = base58btc.decode(id)
55
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
56
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
57
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
58
+ expect(doc).toMatchSnapshot()
59
+ })
60
+
61
+ // testing the key from the did:key from the compressed public key
62
+ it('successfully resolves the document from did', async () => {
63
+ const id = 'z2J9gaYd3MzVdZSQDj1zqsxv2tLD5Np3oD7G5F5dHbsF7Sbf1ovGkRfFcaUZMSSDKheREWxapez3vzVwkRYvrSMt4PM4Am1z'
64
+ const multiformatPubKey = base58btc.decode(id)
65
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
66
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
67
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
68
+ expect(doc).toMatchSnapshot()
69
+ })
70
+
71
+ // testing the key from the did:key from the compressed public key
72
+ it('successfully resolves the document from did', async () => {
73
+ const id = 'z2J9gaYhkf4Ax2QA65KkcrSxr8JDSxUBwzFq3jmq5iBroY2tE7s1uohXVqEvALPxbvdzbWWQTtHvTprUdbNFha3HawyPcD9P'
74
+
75
+ const multiformatPubKey = base58btc.decode(id)
76
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
77
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
78
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
79
+ expect(doc).toMatchSnapshot()
80
+ })
81
+
82
+ // testing the key from the did:key from the compressed public key
83
+ it('successfully resolves the document from did', async () => {
84
+ const id = 'z2J9gcGdbo8riFqfRzgo3gjJyFcbNJm75hrnpDrZTNqQQxgNVBTtKndBiKxzGXrAbyw5W88VDbR1B1FvRQNTnSezghqnJ7p6'
85
+
86
+ const multiformatPubKey = base58btc.decode(id)
87
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
88
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
89
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
90
+ expect(doc).toMatchSnapshot()
91
+ })
92
+
93
+ // testing the key from the did:key from the compressed public key
94
+ it('successfully resolves the document from did', async () => {
95
+ const id = 'z2J9gcGTjd3NaNifwmaNZN27xioMAzHHCDBmkuQ552hm9kWrzhUepDCSAhiuRYBj1sSXR1LBxgqh6vasYzc8JhC12FpaNDhT'
96
+
97
+ const multiformatPubKey = base58btc.decode(id)
98
+ varint.decode(multiformatPubKey) // decode is changing param multiformatPubKey as well
99
+ const pubKeyBytes = multiformatPubKey.slice(varint.decode.bytes)
100
+ const doc = await mapper.keyToDidDoc({ pubKeyBytes, fingerprint: id })
101
+ expect(doc).toMatchSnapshot()
102
+ })
103
+ })
104
+
105
+ test('expect publicKeyBytesToXY to throw an error for undefined', () => {
106
+ expect(() => {
107
+ mapper.pubKeyBytesToXY(undefined as never)
108
+ }).toThrowError('input must be a Uint8Array')
109
+ })
110
+
111
+ test('expect publicKeyBytesToXY to throw an error for null', () => {
112
+ expect(() => {
113
+ mapper.pubKeyBytesToXY(null as never)
114
+ }).toThrowError('input must be a Uint8Array')
115
+ })
116
+
117
+ test('expect publicKeyBytesToXY to throw an error for and integer input', () => {
118
+ expect(() => {
119
+ // @ts-ignore
120
+ mapper.pubKeyBytesToXY(5)
121
+ }).toThrowError('input must be a Uint8Array')
122
+ })
123
+
124
+ test('test a compressed public key in hex to an x,y point with x, and y url encoded with an unsupported prefixi: try2', () => {
125
+ const inputPublicKeyHex =
126
+ '050013673d87114741d183ee420e19472782c1c50a35794abad05d453246b5fd56c1bbb6baea58fa5a19e26586d4bc3db18ff91fac537cdf0913a204c5c6a9949cce8c'
127
+ const publicKey_u8a = pubKeyHexToUint8Array(inputPublicKeyHex)
128
+ expect(() => {
129
+ mapper.pubKeyBytesToXY(publicKey_u8a)
130
+ }).toThrowError('Unexpected pubKeyBytes')
131
+ })
132
+
133
+ test('test a compressed public key in hex to an x,y point with x, and y url encoded with an unsupported prefixi: try3', () => {
134
+ const inputPublicKeyHex =
135
+ '040024fd2216f69ad8a84a8ec630fa4879f82639795a83fa07769d134544130f3af5cfd86ff5460ee7e88a21115cfb9c91898c8ca492feca1992b35c23690af58bd112'
136
+ const publicKey_u8a = pubKeyHexToUint8Array(inputPublicKeyHex)
137
+ expect(() => {
138
+ mapper.pubKeyBytesToXY(publicKey_u8a)
139
+ }).toThrowError('Unexpected pubKeyBytes')
140
+ })
141
+
142
+ test('test a compressed public key in hex to an x,y point with x, and y url encoded with an unsupported prefix', () => {
143
+ const inputPublicKeyHex =
144
+ '010024fd2216f69ad8a84a8ec630fa4879f82639795a83fa07769d134544130f3af5cfd86ff5460ee7e88a21115cfb9c91898c8ca492feca1992b35c23690af58bd112'
145
+ const publicKey_u8a = pubKeyHexToUint8Array(inputPublicKeyHex)
146
+ expect(() => {
147
+ mapper.pubKeyBytesToXY(publicKey_u8a)
148
+ }).toThrowError('Unexpected pubKeyBytes')
149
+ })
150
+
151
+ test('test a compressed public key in hex to an x,y point with x, and y url encoded with an unexpected length', () => {
152
+ const inputPublicKeyHex = '030024fd2216f69ad8a84a8ec630fa4879f82639795a83fa07769d134544130f3af5cfd86ff5460ee7e88a21115cfb9c91898c8ca492feca19'
153
+ const publicKey_u8a = pubKeyHexToUint8Array(inputPublicKeyHex)
154
+ expect(() => {
155
+ mapper.pubKeyBytesToXY(publicKey_u8a)
156
+ }).toThrowError('Unexpected pubKeyBytes')
157
+ })
158
+
159
+ test('test a hex string longer than 67 bytes', () => {
160
+ const inputPublicKeyHex =
161
+ '010024fd2216f69ad8a84a8ec630fa4879f82639795a83fa07769d134544130f3af5cfd86ff5460ee7e88a21115cfb9c91898c8ca492feca1992b35c23690af58bd112000'
162
+ const publicKey_u8a = pubKeyHexToUint8Array(inputPublicKeyHex)
163
+ expect(() => {
164
+ mapper.pubKeyBytesToXY(publicKey_u8a)
165
+ }).toThrowError('Unexpected pubKeyBytes')
166
+ })
167
+
168
+ test('test a hex string longer than 67 bytes: try2', () => {
169
+ const inputPublicKeyHex =
170
+ '030024fd2216f69ad8a84a8ec630fa4879f82639795a83fa07769d134544130f3af5cfd86ff5460ee7e88a21115cfb9c91898c8ca492feca1992b35c23690af58bd11200'
171
+ const publicKey_u8a = pubKeyHexToUint8Array(inputPublicKeyHex)
172
+ expect(() => {
173
+ mapper.pubKeyBytesToXY(publicKey_u8a)
174
+ }).toThrowError('Unexpected pubKeyBytes')
175
+ })
176
+
177
+ test('test a compressed public key in hex to an x,y point with x, and y url encoded', () => {
178
+ const inputPublicKeyHex =
179
+ '0300978fcb87684ebbfb723e695fa6e46640e05624f3e3be9e01c23f713088aa542a8006c259b6a8152f5991bf3713eada06b9eb30c0fcc5c9f877143e51d0c960f8e4'
180
+ const output = {
181
+ xm: 'l4_Lh2hOu_tyPmlfpuRmQOBWJPPjvp4Bwj9xMIiqVCqABsJZtqgVL1mRvzcT6toGueswwPzFyfh3FD5R0Mlg-OQ',
182
+ ym: 'iV1Wy8VO05NKYylHjeXy7RL5zM2gG5pP8PIqBjbFXdo9MPZ3MsyyIF54Ykz76jFp55cD3CrynsUTD41JCQyFrJs',
183
+ }
184
+ const publicKey_u8a = pubKeyHexToUint8Array(inputPublicKeyHex)
185
+ const pubKeyBytesToXY = mapper.pubKeyBytesToXY(publicKey_u8a)
186
+ expect(pubKeyBytesToXY).toEqual(output)
187
+ })
188
+
189
+ //**** end of tests
190
+
191
+ // Function for test. Eliminate this when key-did-resolver is written.
192
+
193
+ function pubKeyHexToUint8Array(publicKeyHex: string) {
194
+ if (!publicKeyHex) {
195
+ throw new TypeError('input cannot be null or undefined.')
196
+ }
197
+ if (publicKeyHex.length % 2 == 0) {
198
+ return u8a.fromString(publicKeyHex, 'base16')
199
+ } else {
200
+ return u8a.fromString('0' + publicKeyHex, 'base16')
201
+ }
202
+ }
@@ -0,0 +1,24 @@
1
+ import { DIDDocument } from 'did-resolver'
2
+ import * as u8a from 'uint8arrays'
3
+ import { KeyToDidDocArgs } from '../index'
4
+
5
+ export const keyToDidDoc = ({ pubKeyBytes, fingerprint }: KeyToDidDocArgs): DIDDocument => {
6
+ const did = `did:key:${fingerprint}`
7
+ const keyId = `${did}#${fingerprint}`
8
+ return {
9
+ id: did,
10
+ verificationMethod: [
11
+ {
12
+ id: keyId,
13
+ type: 'Bls12381G2Key2020',
14
+ controller: did,
15
+ publicKeyBase58: u8a.toString(pubKeyBytes, 'base58btc'),
16
+ },
17
+ ],
18
+ authentication: [keyId],
19
+ assertionMethod: [keyId],
20
+ capabilityDelegation: [keyId],
21
+ capabilityInvocation: [keyId],
22
+ }
23
+ }
24
+ export default { keyToDidDoc }
@@ -0,0 +1,115 @@
1
+ import * as u8a from 'uint8arrays'
2
+ import { DIDDocument } from 'did-resolver'
3
+ // import { edwardsToMontgomery } from '@noble/curves/ed25519'
4
+ import { convertPublicKeyToX25519 } from '@stablelib/ed25519'
5
+ import { DID_LD_JSON, KeyToDidDocArgs } from '../types'
6
+
7
+ function encodeKey(key: Uint8Array, encodeKey?: number) {
8
+ const bytes = new Uint8Array(key.length + 2)
9
+ bytes[0] = encodeKey ?? 0xec
10
+ // The multicodec is encoded as a varint so we need to add this.
11
+ // See js-multicodec for a general implementation
12
+ bytes[1] = 0x01
13
+ bytes.set(key, 2)
14
+ return `z${u8a.toString(bytes, 'base58btc')}`
15
+ }
16
+
17
+ export const keyToDidDoc = (args: KeyToDidDocArgs) => {
18
+ const { options } = args
19
+ if (!options?.publicKeyFormat) {
20
+ return keyToDidDoc2020(args)
21
+ }
22
+ switch (options.publicKeyFormat) {
23
+ case 'Ed25519VerificationKey2018':
24
+ case 'X25519KeyAgreementKey2019':
25
+ return keyToDidDoc2018_2019(args)
26
+ case 'Ed25519VerificationKey2020':
27
+ case 'X25519KeyAgreementKey2020':
28
+ case 'Multikey':
29
+ return keyToDidDoc2020(args)
30
+ default:
31
+ throw Error(`${options.publicKeyFormat} not supported yet for the ed25519 driver`)
32
+ }
33
+ }
34
+ const keyToDidDoc2018_2019 = ({ pubKeyBytes, fingerprint, contentType }: KeyToDidDocArgs): DIDDocument => {
35
+ const did = `did:key:${fingerprint}`
36
+ const keyId = `${did}#${fingerprint}`
37
+
38
+ //todo: Move to noble lib. x25519 values differ between below methods. Current implementation is correct according to DID:key spec
39
+ // const pubKeyHex = u8a.toString(pubKeyBytes, 'base16')
40
+ // const x25519PubBytes = edwardsToMontgomery(pubKeyHex)
41
+ const x25519PubBytes = convertPublicKeyToX25519(pubKeyBytes)
42
+
43
+ const x25519KeyId = `${did}#${encodeKey(x25519PubBytes)}`
44
+ return {
45
+ ...(contentType === DID_LD_JSON && {
46
+ '@context': [
47
+ 'https://www.w3.org/ns/did/v1',
48
+ 'https://w3id.org/security/suites/ed25519-2018/v1',
49
+ 'https://w3id.org/security/suites/x25519-2019/v1',
50
+ ],
51
+ }),
52
+ id: did,
53
+ verificationMethod: [
54
+ {
55
+ id: keyId,
56
+ type: 'Ed25519VerificationKey2018',
57
+ controller: did,
58
+ publicKeyBase58: u8a.toString(pubKeyBytes, 'base58btc'),
59
+ },
60
+ {
61
+ id: x25519KeyId,
62
+ type: 'X25519KeyAgreementKey2019',
63
+ controller: did,
64
+ publicKeyBase58: u8a.toString(x25519PubBytes, 'base58btc'),
65
+ },
66
+ ],
67
+ authentication: [keyId],
68
+ assertionMethod: [keyId],
69
+ capabilityDelegation: [keyId],
70
+ capabilityInvocation: [keyId],
71
+ keyAgreement: [x25519KeyId],
72
+ }
73
+ }
74
+
75
+ const keyToDidDoc2020 = ({ pubKeyBytes, fingerprint, contentType }: KeyToDidDocArgs): DIDDocument => {
76
+ const did = `did:key:${fingerprint}`
77
+ const keyId = `${did}#${fingerprint}`
78
+ //todo: Move to noble lib. x25519 values differ between below methods. Current implementation is correct according to DID:key spec
79
+ // const pubKeyHex = u8a.toString(pubKeyBytes, 'base16')
80
+ // const x25519PubBytes = edwardsToMontgomery(pubKeyBytes)
81
+ const x25519PubBytes = convertPublicKeyToX25519(pubKeyBytes)
82
+
83
+ const x25519KeyId = `${did}#${encodeKey(x25519PubBytes)}`
84
+ return {
85
+ ...(contentType === DID_LD_JSON && {
86
+ '@context': [
87
+ 'https://www.w3.org/ns/did/v1',
88
+ 'https://w3id.org/security/suites/ed25519-2020/v1',
89
+ 'https://w3id.org/security/suites/x25519-2020/v1',
90
+ ],
91
+ }),
92
+ id: did,
93
+ verificationMethod: [
94
+ {
95
+ id: keyId,
96
+ type: 'Ed25519VerificationKey2020',
97
+ controller: did,
98
+ publicKeyMultibase: encodeKey(pubKeyBytes, 0xed),
99
+ },
100
+ ],
101
+ authentication: [keyId],
102
+ assertionMethod: [keyId],
103
+ capabilityDelegation: [keyId],
104
+ capabilityInvocation: [keyId],
105
+ keyAgreement: [
106
+ {
107
+ id: x25519KeyId,
108
+ type: 'X25519KeyAgreementKey2020',
109
+ controller: did,
110
+ publicKeyMultibase: encodeKey(x25519PubBytes, 0xec),
111
+ },
112
+ ],
113
+ }
114
+ }
115
+ export default { keyToDidDoc }
@@ -0,0 +1,28 @@
1
+ import { DIDDocument } from 'did-resolver'
2
+ import { DID_LD_JSON, KeyToDidDocArgs } from '../index'
3
+ import { jwkJcsDecode } from '@sphereon/ssi-sdk-ext.key-utils'
4
+
5
+ export const keyToDidDoc = ({ pubKeyBytes, fingerprint, contentType }: KeyToDidDocArgs): DIDDocument => {
6
+ const did = `did:key:${fingerprint}`
7
+ const keyId = `${did}#${fingerprint}`
8
+ const publicKeyJwk = jwkJcsDecode(pubKeyBytes)
9
+ return {
10
+ ...(contentType === DID_LD_JSON && {
11
+ '@context': ['https://www.w3.org/ns/did/v1', 'https://w3id.org/security/suites/jws-2020/v1'],
12
+ }),
13
+ id: did,
14
+ verificationMethod: [
15
+ {
16
+ id: keyId,
17
+ type: 'JsonWebKey2020',
18
+ controller: did,
19
+ publicKeyJwk,
20
+ },
21
+ ],
22
+ authentication: [keyId],
23
+ assertionMethod: [keyId],
24
+ capabilityDelegation: [keyId],
25
+ capabilityInvocation: [keyId],
26
+ }
27
+ }
28
+ export default { keyToDidDoc }
@@ -0,0 +1,25 @@
1
+ import * as u8a from 'uint8arrays'
2
+ import { DIDDocument } from 'did-resolver'
3
+ import { KeyToDidDocArgs } from '../types'
4
+
5
+ export const keyToDidDoc = ({ pubKeyBytes, fingerprint }: KeyToDidDocArgs): DIDDocument => {
6
+ const did = `did:key:${fingerprint}`
7
+ const keyId = `${did}#${fingerprint}`
8
+ return {
9
+ id: did,
10
+ verificationMethod: [
11
+ {
12
+ id: keyId,
13
+ type: 'Secp256k1VerificationKey2018',
14
+ controller: did,
15
+ publicKeyBase58: u8a.toString(pubKeyBytes, 'base58btc'),
16
+ },
17
+ ],
18
+ authentication: [keyId],
19
+ assertionMethod: [keyId],
20
+ capabilityDelegation: [keyId],
21
+ capabilityInvocation: [keyId],
22
+ }
23
+ }
24
+
25
+ export default { keyToDidDoc }
@@ -0,0 +1,82 @@
1
+ // Brent Shambaugh <brent.shambaugh@gmail.com>. 2021.
2
+
3
+ import * as u8a from 'uint8arrays'
4
+
5
+ import * as nist_weierstrauss from 'nist-weierstrauss'
6
+ import { base64urlPoint } from 'nist-weierstrauss'
7
+ import { KeyToDidDocArgs } from '../types'
8
+
9
+ /**
10
+ * Constructs the document based on the method key
11
+ */
12
+ export function keyToDidDoc({ pubKeyBytes, fingerprint }: KeyToDidDocArgs): any {
13
+ const did = `did:key:${fingerprint}`
14
+ const keyId = `${did}#${fingerprint}`
15
+ const key = pubKeyBytesToXY(pubKeyBytes)
16
+ return {
17
+ id: did,
18
+ verificationMethod: [
19
+ {
20
+ id: keyId,
21
+ type: 'JsonWebKey2020',
22
+ controller: did,
23
+ publicKeyJwk: {
24
+ kty: 'EC',
25
+ crv: 'P-256',
26
+ x: key.xm,
27
+ y: key.ym,
28
+ },
29
+ },
30
+ ],
31
+ authentication: [keyId],
32
+ assertionMethod: [keyId],
33
+ capabilityDelegation: [keyId],
34
+ capabilityInvocation: [keyId],
35
+ }
36
+ }
37
+
38
+ /**
39
+ *
40
+ * @param pubKeyBytes - public key as uncompressed byte array with no prefix (raw key),
41
+ * uncompressed with 0x04 prefix, or compressed with 0x02 prefix if even and 0x03 prefix if odd.
42
+ * @returns point x,y with coordinates as multibase encoded base64urls
43
+ *
44
+ * See the the did:key specification: https://w3c-ccg.github.io/did-method-key/#p-256.
45
+ * At present only raw p-256 keys are covered in the specification.
46
+ * @throws TypeError: input cannot be null or undefined.
47
+ * @throws Error: Unexpected pubKeyBytes
48
+ * @internal
49
+ */
50
+ export function pubKeyBytesToXY(pubKeyBytes: Uint8Array): base64urlPoint {
51
+ if (!nist_weierstrauss.nist_weierstrauss_common.testUint8Array(pubKeyBytes)) {
52
+ throw new TypeError('input must be a Uint8Array')
53
+ }
54
+ const publicKeyHex = nist_weierstrauss.nist_weierstrauss_common.pubKeyBytesToHex(pubKeyBytes)
55
+ const bytesCount = publicKeyHex.length / 2
56
+
57
+ // raw p-256 key
58
+ if (bytesCount == 64) {
59
+ return nist_weierstrauss.nist_weierstrauss_common.publicKeyToXY(publicKeyHex)
60
+ }
61
+
62
+ // uncompressed p-256 key, SEC format
63
+ if (bytesCount == 65) {
64
+ if (publicKeyHex.slice(0, 2) == '04') {
65
+ const publicKey = publicKeyHex.slice(2)
66
+ return nist_weierstrauss.nist_weierstrauss_common.publicKeyToXY(publicKey)
67
+ }
68
+ }
69
+
70
+ // compressed p-256 key, SEC format
71
+ if (bytesCount == 33) {
72
+ if (publicKeyHex.slice(0, 2) == '03' || publicKeyHex.slice(0, 2) == '02') {
73
+ const publicKey = u8a.fromString(publicKeyHex, 'base16')
74
+ const point = nist_weierstrauss.secp256r1.ECPointDecompress(publicKey)
75
+ return nist_weierstrauss.nist_weierstrauss_common.publicKeyIntToXY(point)
76
+ }
77
+ }
78
+
79
+ throw new Error('Unexpected pubKeyBytes')
80
+ }
81
+
82
+ export default { keyToDidDoc }
@@ -0,0 +1,82 @@
1
+ // Brent Shambaugh <brent.shambaugh@gmail.com>. 2021.
2
+
3
+ import * as u8a from 'uint8arrays'
4
+
5
+ import * as nist_weierstrauss from 'nist-weierstrauss'
6
+ import { base64urlPoint } from 'nist-weierstrauss'
7
+ import { KeyToDidDocArgs } from '../types'
8
+
9
+ /**
10
+ * Constructs the document based on the method key
11
+ */
12
+ export function keyToDidDoc({ pubKeyBytes, fingerprint }: KeyToDidDocArgs): any {
13
+ const did = `did:key:${fingerprint}`
14
+ const keyId = `${did}#${fingerprint}`
15
+ const key = pubKeyBytesToXY(pubKeyBytes)
16
+ return {
17
+ id: did,
18
+ verificationMethod: [
19
+ {
20
+ id: keyId,
21
+ type: 'JsonWebKey2020',
22
+ controller: did,
23
+ publicKeyJwk: {
24
+ kty: 'EC',
25
+ crv: 'P-384',
26
+ x: key.xm,
27
+ y: key.ym,
28
+ },
29
+ },
30
+ ],
31
+ authentication: [keyId],
32
+ assertionMethod: [keyId],
33
+ capabilityDelegation: [keyId],
34
+ capabilityInvocation: [keyId],
35
+ }
36
+ }
37
+
38
+ /**
39
+ *
40
+ * @param pubKeyBytes - public key as uncompressed byte array with no prefix (raw key),
41
+ * uncompressed with 0x04 prefix, or compressed with 0x02 prefix if even and 0x03 prefix if odd.
42
+ * @returns point x,y with coordinates as multibase encoded base64urls
43
+ *
44
+ * See the the did:key specification: https://w3c-ccg.github.io/did-method-key/#p-384.
45
+ * At present only raw p-384 keys are covered in the specification.
46
+ * @throws TypeError: input cannot be null or undefined.
47
+ * @throws Error: Unexpected pubKeyBytes
48
+ * @internal
49
+ */
50
+ export function pubKeyBytesToXY(pubKeyBytes: Uint8Array): base64urlPoint {
51
+ if (!nist_weierstrauss.nist_weierstrauss_common.testUint8Array(pubKeyBytes)) {
52
+ throw new TypeError('input must be a Uint8Array')
53
+ }
54
+ const publicKeyHex = nist_weierstrauss.nist_weierstrauss_common.pubKeyBytesToHex(pubKeyBytes)
55
+ const bytesCount = publicKeyHex.length / 2
56
+
57
+ // raw p-384 key
58
+ if (bytesCount == 96) {
59
+ return nist_weierstrauss.nist_weierstrauss_common.publicKeyToXY(publicKeyHex)
60
+ }
61
+
62
+ // uncompressed p-384 key, SEC format
63
+ if (bytesCount == 97) {
64
+ if (publicKeyHex.slice(0, 2) == '04') {
65
+ const publicKey = publicKeyHex.slice(2)
66
+ return nist_weierstrauss.nist_weierstrauss_common.publicKeyToXY(publicKey)
67
+ }
68
+ }
69
+
70
+ // compressed p-384 key, SEC format
71
+ if (bytesCount == 49) {
72
+ if (publicKeyHex.slice(0, 2) == '03' || publicKeyHex.slice(0, 2) == '02') {
73
+ const publicKey = u8a.fromString(publicKeyHex, 'base16')
74
+ const point = nist_weierstrauss.secp384r1.ECPointDecompress(publicKey)
75
+ return nist_weierstrauss.nist_weierstrauss_common.publicKeyIntToXY(point)
76
+ }
77
+ }
78
+
79
+ throw new Error('Unexpected pubKeyBytes')
80
+ }
81
+
82
+ export default { keyToDidDoc }
@@ -0,0 +1,68 @@
1
+ // Brent Shambaugh <brent.shambaugh@gmail.com>. 2021.
2
+
3
+ import * as u8a from 'uint8arrays'
4
+
5
+ import * as nist_weierstrauss from 'nist-weierstrauss'
6
+ import { base64urlPoint } from 'nist-weierstrauss'
7
+ import { KeyToDidDocArgs } from '../types'
8
+
9
+ /**
10
+ * Constructs the document based on the method key
11
+ */
12
+ export function keyToDidDoc({ pubKeyBytes, fingerprint }: KeyToDidDocArgs): any {
13
+ const did = `did:key:${fingerprint}`
14
+ const keyId = `${did}#${fingerprint}`
15
+ const key = pubKeyBytesToXY(pubKeyBytes)
16
+ return {
17
+ id: did,
18
+ verificationMethod: [
19
+ {
20
+ id: keyId,
21
+ type: 'JsonWebKey2020',
22
+ controller: did,
23
+ publicKeyJwk: {
24
+ kty: 'EC',
25
+ crv: 'P-521',
26
+ x: key.xm,
27
+ y: key.ym,
28
+ },
29
+ },
30
+ ],
31
+ authentication: [keyId],
32
+ assertionMethod: [keyId],
33
+ capabilityDelegation: [keyId],
34
+ capabilityInvocation: [keyId],
35
+ }
36
+ }
37
+
38
+ /**
39
+ *
40
+ * @param pubKeyBytes - public key as compressed with 0x02 prefix if even and 0x03 prefix if odd.
41
+ * @returns point x,y with coordinates as multibase encoded base64urls
42
+ *
43
+ * See the the did:key specification: https://w3c-ccg.github.io/did-method-key/#p-521.
44
+ * For compression see: https://tools.ietf.org/id/draft-jivsov-ecc-compact-05.html#rfc.section.3
45
+ * @throws TypeError: input cannot be null or undefined.
46
+ * @throws Error: Unexpected pubKeyBytes
47
+ * @internal
48
+ */
49
+ export function pubKeyBytesToXY(pubKeyBytes: Uint8Array): base64urlPoint {
50
+ if (!nist_weierstrauss.nist_weierstrauss_common.testUint8Array(pubKeyBytes)) {
51
+ throw new TypeError('input must be a Uint8Array')
52
+ }
53
+ const publicKeyHex = nist_weierstrauss.nist_weierstrauss_common.pubKeyBytesToHex(pubKeyBytes)
54
+
55
+ // compressed p-521 key, SEC format
56
+ // publicKeyHex.length / 2.0 = 67.0 bytes
57
+ if (132 <= publicKeyHex.length && publicKeyHex.length <= 134) {
58
+ if (publicKeyHex.slice(0, 2) == '03' || publicKeyHex.slice(0, 2) == '02') {
59
+ const publicKey = u8a.fromString(publicKeyHex, 'base16')
60
+ const point = nist_weierstrauss.secp521r1.ECPointDecompress(publicKey)
61
+ return nist_weierstrauss.nist_weierstrauss_common.publicKeyIntToXY(point)
62
+ }
63
+ }
64
+
65
+ throw new Error('Unexpected pubKeyBytes')
66
+ }
67
+
68
+ export default { keyToDidDoc }