@sphereon/ssi-sdk.sd-jwt 0.24.1-next.112
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.
- package/LICENSE +201 -0
- package/README.md +3 -0
- package/dist/action-handler.d.ts +69 -0
- package/dist/action-handler.d.ts.map +1 -0
- package/dist/action-handler.js +220 -0
- package/dist/action-handler.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/ssi-sdk.sd-jwt.d.ts +261 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/types.d.ts +167 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
- package/plugin.schema.json +254 -0
- package/src/__tests__/sd-jwt.test.ts +340 -0
- package/src/action-handler.ts +235 -0
- package/src/index.ts +7 -0
- package/src/types.ts +199 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ISDJwtPlugin": {
|
|
3
|
+
"components": {
|
|
4
|
+
"schemas": {
|
|
5
|
+
"ICreateSdJwtPresentationArgs": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"presentation": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Encoded SD-JWT credential"
|
|
11
|
+
},
|
|
12
|
+
"presentationFrame": {
|
|
13
|
+
"$ref": "#/components/schemas/IPresentationFrame"
|
|
14
|
+
},
|
|
15
|
+
"kb": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"payload": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"iat": {
|
|
22
|
+
"type": "number"
|
|
23
|
+
},
|
|
24
|
+
"aud": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"nonce": {
|
|
28
|
+
"type": "string"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"required": [
|
|
32
|
+
"iat",
|
|
33
|
+
"aud",
|
|
34
|
+
"nonce"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"required": [
|
|
39
|
+
"payload"
|
|
40
|
+
],
|
|
41
|
+
"description": "Information to include to add key binding."
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"required": [
|
|
45
|
+
"presentation"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"IPresentationFrame": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": {
|
|
51
|
+
"anyOf": [
|
|
52
|
+
{
|
|
53
|
+
"type": "boolean"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"$ref": "#/components/schemas/IPresentationFrame"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"ICreateSdJwtPresentationResult": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"presentation": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"description": "Encoded presentation."
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"required": [
|
|
70
|
+
"presentation"
|
|
71
|
+
],
|
|
72
|
+
"description": "Created presentation"
|
|
73
|
+
},
|
|
74
|
+
"ICreateSdJwtVcArgs": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"properties": {
|
|
77
|
+
"credentialPayload": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"iss": {
|
|
81
|
+
"type": "string"
|
|
82
|
+
},
|
|
83
|
+
"nbf": {
|
|
84
|
+
"type": "number"
|
|
85
|
+
},
|
|
86
|
+
"exp": {
|
|
87
|
+
"type": "number"
|
|
88
|
+
},
|
|
89
|
+
"cnf": {},
|
|
90
|
+
"vct": {
|
|
91
|
+
"type": "string"
|
|
92
|
+
},
|
|
93
|
+
"status": {},
|
|
94
|
+
"sub": {
|
|
95
|
+
"type": "string"
|
|
96
|
+
},
|
|
97
|
+
"iat": {
|
|
98
|
+
"type": "number"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"required": [
|
|
102
|
+
"iss",
|
|
103
|
+
"vct"
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"disclosureFrame": {
|
|
107
|
+
"$ref": "#/components/schemas/IDisclosureFrame"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"required": [
|
|
111
|
+
"credentialPayload"
|
|
112
|
+
],
|
|
113
|
+
"description": "ICreateSdJwtVcArgs"
|
|
114
|
+
},
|
|
115
|
+
"IDisclosureFrame": {
|
|
116
|
+
"type": "object",
|
|
117
|
+
"properties": {
|
|
118
|
+
"_sd": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": {
|
|
121
|
+
"type": "string"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"_sd_decoy": {
|
|
125
|
+
"type": "number"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"additionalProperties": {
|
|
129
|
+
"anyOf": [
|
|
130
|
+
{
|
|
131
|
+
"type": "array",
|
|
132
|
+
"items": {
|
|
133
|
+
"type": "string"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"type": "number"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"$ref": "#/components/schemas/IDisclosureFrame"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"not": {}
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"ICreateSdJwtVcResult": {
|
|
149
|
+
"type": "object",
|
|
150
|
+
"properties": {
|
|
151
|
+
"credential": {
|
|
152
|
+
"type": "string",
|
|
153
|
+
"description": "the encoded sd-jwt credential"
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"required": [
|
|
157
|
+
"credential"
|
|
158
|
+
],
|
|
159
|
+
"description": "ICreateSdJwtVcResult"
|
|
160
|
+
},
|
|
161
|
+
"IVerifySdJwtPresentationArgs": {
|
|
162
|
+
"type": "object",
|
|
163
|
+
"properties": {
|
|
164
|
+
"presentation": {
|
|
165
|
+
"type": "string"
|
|
166
|
+
},
|
|
167
|
+
"requiredClaimKeys": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"items": {
|
|
170
|
+
"type": "string"
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"kb": {
|
|
174
|
+
"type": "boolean"
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"required": [
|
|
178
|
+
"presentation"
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
"IVerifySdJwtPresentationResult": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"verifiedPayloads": {
|
|
185
|
+
"type": "object",
|
|
186
|
+
"additionalProperties": {}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"required": [
|
|
190
|
+
"verifiedPayloads"
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
"IVerifySdJwtVcArgs": {
|
|
194
|
+
"type": "object",
|
|
195
|
+
"properties": {
|
|
196
|
+
"credential": {
|
|
197
|
+
"type": "string"
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
"required": [
|
|
201
|
+
"credential"
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
"IVerifySdJwtVcResult": {
|
|
205
|
+
"type": "object",
|
|
206
|
+
"properties": {
|
|
207
|
+
"verifiedPayloads": {}
|
|
208
|
+
},
|
|
209
|
+
"required": [
|
|
210
|
+
"verifiedPayloads"
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"methods": {
|
|
215
|
+
"createSdJwtPresentation": {
|
|
216
|
+
"description": "Create a signed SD-JWT presentation.",
|
|
217
|
+
"arguments": {
|
|
218
|
+
"$ref": "#/components/schemas/ICreateSdJwtPresentationArgs"
|
|
219
|
+
},
|
|
220
|
+
"returnType": {
|
|
221
|
+
"$ref": "#/components/schemas/ICreateSdJwtPresentationResult"
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"createSdJwtVc": {
|
|
225
|
+
"description": "Create a signed SD-JWT credential.",
|
|
226
|
+
"arguments": {
|
|
227
|
+
"$ref": "#/components/schemas/ICreateSdJwtVcArgs"
|
|
228
|
+
},
|
|
229
|
+
"returnType": {
|
|
230
|
+
"$ref": "#/components/schemas/ICreateSdJwtVcResult"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"verifySdJwtPresentation": {
|
|
234
|
+
"description": "Verify a signed SD-JWT presentation.",
|
|
235
|
+
"arguments": {
|
|
236
|
+
"$ref": "#/components/schemas/IVerifySdJwtPresentationArgs"
|
|
237
|
+
},
|
|
238
|
+
"returnType": {
|
|
239
|
+
"$ref": "#/components/schemas/IVerifySdJwtPresentationResult"
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"verifySdJwtVc": {
|
|
243
|
+
"description": "Verify a signed SD-JWT credential.",
|
|
244
|
+
"arguments": {
|
|
245
|
+
"$ref": "#/components/schemas/IVerifySdJwtVcArgs"
|
|
246
|
+
},
|
|
247
|
+
"returnType": {
|
|
248
|
+
"$ref": "#/components/schemas/IVerifySdJwtVcResult"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { DisclosureFrame, kbPayload } from '@sd-jwt/types'
|
|
2
|
+
import { createAgent, IDIDManager, IKeyManager, IResolver, TAgent } from '@veramo/core'
|
|
3
|
+
import { DIDManager, MemoryDIDStore } from '@veramo/did-manager'
|
|
4
|
+
import { JwkDIDProvider } from '@sphereon/ssi-sdk-ext.did-provider-jwk'
|
|
5
|
+
import { getDidJwkResolver } from '@sphereon/ssi-sdk-ext.did-resolver-jwk'
|
|
6
|
+
import { DIDResolverPlugin } from '@veramo/did-resolver'
|
|
7
|
+
import { DIDDocument, Resolver, VerificationMethod } from 'did-resolver'
|
|
8
|
+
import { SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
|
|
9
|
+
import { decodeSdJwt } from '@sd-jwt/decode'
|
|
10
|
+
import { KBJwt } from '@sd-jwt/core'
|
|
11
|
+
import { ISDJwtPlugin, SDJwtPlugin } from '../index'
|
|
12
|
+
import { createHash, randomBytes, subtle } from 'crypto'
|
|
13
|
+
import {MemoryKeyStore, MemoryPrivateKeyStore, SphereonKeyManager} from '@sphereon/ssi-sdk-ext.key-manager'
|
|
14
|
+
import {SphereonKeyManagementSystem} from '@sphereon/ssi-sdk-ext.kms-local'
|
|
15
|
+
|
|
16
|
+
const generateDigest = (data: string, algorithm: string) => {
|
|
17
|
+
return createHash(algorithm).update(data).digest()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const generateSalt = (): string => {
|
|
21
|
+
return randomBytes(16).toString('hex');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function verifySignature<T>(data: string, signature: string, key: JsonWebKey) {
|
|
25
|
+
let { alg, crv } = key
|
|
26
|
+
if (alg === 'ES256') alg = 'ECDSA'
|
|
27
|
+
const publicKey = await subtle.importKey(
|
|
28
|
+
'jwk',
|
|
29
|
+
key,
|
|
30
|
+
{ name: alg, namedCurve: crv } as EcKeyImportParams,
|
|
31
|
+
true,
|
|
32
|
+
['verify'],
|
|
33
|
+
)
|
|
34
|
+
return Promise.resolve(
|
|
35
|
+
subtle.verify(
|
|
36
|
+
{ name: alg as string, hash: 'SHA-256' },
|
|
37
|
+
publicKey,
|
|
38
|
+
Buffer.from(signature, 'base64'),
|
|
39
|
+
Buffer.from(data),
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type AgentType = IDIDManager & IKeyManager & IResolver & ISDJwtPlugin
|
|
45
|
+
|
|
46
|
+
describe('Agent plugin', () => {
|
|
47
|
+
let agent: TAgent<AgentType>
|
|
48
|
+
|
|
49
|
+
let issuer: string
|
|
50
|
+
|
|
51
|
+
let holder: string
|
|
52
|
+
|
|
53
|
+
// Issuer Define the claims object with the user's information
|
|
54
|
+
const claims = {
|
|
55
|
+
sub: '',
|
|
56
|
+
given_name: 'John',
|
|
57
|
+
family_name: 'Deo',
|
|
58
|
+
email: 'johndeo@example.com',
|
|
59
|
+
phone: '+1-202-555-0101',
|
|
60
|
+
address: {
|
|
61
|
+
street_address: '123 Main St',
|
|
62
|
+
locality: 'Anytown',
|
|
63
|
+
region: 'Anystate',
|
|
64
|
+
country: 'US',
|
|
65
|
+
},
|
|
66
|
+
birthdate: '1940-01-01',
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Issuer Define the disclosure frame to specify which claims can be disclosed
|
|
70
|
+
const disclosureFrame: DisclosureFrame<typeof claims> = {
|
|
71
|
+
_sd: ['given_name', 'family_name', 'email', 'phone', 'address', 'birthdate'],
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
beforeAll(async () => {
|
|
75
|
+
agent = createAgent<AgentType>({
|
|
76
|
+
plugins: [
|
|
77
|
+
new SDJwtPlugin({
|
|
78
|
+
hasher: generateDigest,
|
|
79
|
+
saltGenerator: generateSalt,
|
|
80
|
+
verifySignature
|
|
81
|
+
}),
|
|
82
|
+
new SphereonKeyManager({
|
|
83
|
+
store: new MemoryKeyStore(),
|
|
84
|
+
kms: {
|
|
85
|
+
local: new SphereonKeyManagementSystem(new MemoryPrivateKeyStore()),
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
new DIDResolverPlugin({
|
|
89
|
+
resolver: new Resolver({
|
|
90
|
+
...getDidJwkResolver(),
|
|
91
|
+
}),
|
|
92
|
+
}),
|
|
93
|
+
new DIDManager({
|
|
94
|
+
store: new MemoryDIDStore(),
|
|
95
|
+
defaultProvider: 'did:jwk',
|
|
96
|
+
providers: {
|
|
97
|
+
'did:jwk': new JwkDIDProvider({
|
|
98
|
+
defaultKms: 'local',
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
],
|
|
103
|
+
})
|
|
104
|
+
issuer = await agent
|
|
105
|
+
.didManagerCreate({
|
|
106
|
+
kms: 'local',
|
|
107
|
+
provider: 'did:jwk',
|
|
108
|
+
alias: 'issuer',
|
|
109
|
+
//we use this curve since nodejs does not support ES256k which is the default one.
|
|
110
|
+
options: { keyType: 'Secp256r1' }
|
|
111
|
+
})
|
|
112
|
+
.then((did) => {
|
|
113
|
+
// we add a key reference
|
|
114
|
+
return `${did.did}#0`
|
|
115
|
+
})
|
|
116
|
+
holder = await agent
|
|
117
|
+
.didManagerCreate({
|
|
118
|
+
kms: 'local',
|
|
119
|
+
provider: 'did:jwk',
|
|
120
|
+
alias: 'holder',
|
|
121
|
+
//we use this curve since nodejs does not support ES256k which is the default one.
|
|
122
|
+
options: { keyType: 'Secp256r1' }
|
|
123
|
+
})
|
|
124
|
+
.then((did) => `${did.did}#0`)
|
|
125
|
+
claims.sub = holder
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('create a sd-jwt', async () => {
|
|
129
|
+
const credentialPayload: SdJwtVcPayload = {
|
|
130
|
+
...claims,
|
|
131
|
+
iss: issuer,
|
|
132
|
+
iat: new Date().getTime() / 1000,
|
|
133
|
+
vct: '',
|
|
134
|
+
}
|
|
135
|
+
const credential = await agent.createSdJwtVc({
|
|
136
|
+
credentialPayload,
|
|
137
|
+
disclosureFrame,
|
|
138
|
+
})
|
|
139
|
+
expect(credential).toBeDefined()
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('create sd without an issuer', async () => {
|
|
143
|
+
const credentialPayload = {
|
|
144
|
+
...claims,
|
|
145
|
+
iat: new Date().getTime() / 1000,
|
|
146
|
+
vct: '',
|
|
147
|
+
}
|
|
148
|
+
expect(
|
|
149
|
+
agent.createSdJwtVc({
|
|
150
|
+
credentialPayload: credentialPayload as unknown as SdJwtVcPayload,
|
|
151
|
+
disclosureFrame,
|
|
152
|
+
}),
|
|
153
|
+
).rejects.toThrow('credential.issuer must not be empty')
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('verify a sd-jwt', async () => {
|
|
157
|
+
const credentialPayload: SdJwtVcPayload = {
|
|
158
|
+
...claims,
|
|
159
|
+
iss: issuer,
|
|
160
|
+
iat: new Date().getTime() / 1000,
|
|
161
|
+
vct: '',
|
|
162
|
+
}
|
|
163
|
+
const credential = await agent.createSdJwtVc({
|
|
164
|
+
credentialPayload,
|
|
165
|
+
disclosureFrame: disclosureFrame,
|
|
166
|
+
})
|
|
167
|
+
await agent.verifySdJwtVc({
|
|
168
|
+
credential: credential.credential,
|
|
169
|
+
})
|
|
170
|
+
}, 5000)
|
|
171
|
+
|
|
172
|
+
it('create a presentation', async () => {
|
|
173
|
+
const credentialPayload: SdJwtVcPayload = {
|
|
174
|
+
...claims,
|
|
175
|
+
iss: issuer,
|
|
176
|
+
iat: new Date().getTime() / 1000,
|
|
177
|
+
vct: '',
|
|
178
|
+
}
|
|
179
|
+
const credential = await agent.createSdJwtVc({
|
|
180
|
+
credentialPayload,
|
|
181
|
+
disclosureFrame,
|
|
182
|
+
})
|
|
183
|
+
const presentation = await agent.createSdJwtPresentation({
|
|
184
|
+
presentation: credential.credential,
|
|
185
|
+
presentationFrame: { given_name: true },
|
|
186
|
+
kb: {
|
|
187
|
+
payload: {
|
|
188
|
+
aud: '1',
|
|
189
|
+
iat: 1,
|
|
190
|
+
nonce: '342',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
expect(presentation).toBeDefined()
|
|
195
|
+
const decoded = await decodeSdJwt(presentation.presentation, generateDigest)
|
|
196
|
+
expect(decoded.kbJwt).toBeDefined()
|
|
197
|
+
expect(((decoded.kbJwt as KBJwt).payload as kbPayload).aud).toBe('1')
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it('create presentation with cnf', async () => {
|
|
201
|
+
const did = await agent.didManagerFind({ alias: 'holder' }).then((dids) => dids[0])
|
|
202
|
+
const resolvedDid = await agent.resolveDid({ didUrl: `${did.did}#0` })
|
|
203
|
+
const jwk: JsonWebKey = (
|
|
204
|
+
(resolvedDid.didDocument as DIDDocument).verificationMethod as VerificationMethod[]
|
|
205
|
+
)[0].publicKeyJwk as JsonWebKey
|
|
206
|
+
const credentialPayload: SdJwtVcPayload = {
|
|
207
|
+
...claims,
|
|
208
|
+
cnf: {
|
|
209
|
+
jwk,
|
|
210
|
+
},
|
|
211
|
+
iss: issuer,
|
|
212
|
+
iat: new Date().getTime() / 1000,
|
|
213
|
+
vct: '',
|
|
214
|
+
}
|
|
215
|
+
const credential = await agent.createSdJwtVc({
|
|
216
|
+
credentialPayload,
|
|
217
|
+
disclosureFrame,
|
|
218
|
+
})
|
|
219
|
+
const presentation = await agent.createSdJwtPresentation({
|
|
220
|
+
presentation: credential.credential,
|
|
221
|
+
presentationFrame: { given_name: true },
|
|
222
|
+
kb: {
|
|
223
|
+
payload: {
|
|
224
|
+
aud: '1',
|
|
225
|
+
iat: 1,
|
|
226
|
+
nonce: '342',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
})
|
|
230
|
+
expect(presentation).toBeDefined()
|
|
231
|
+
const decoded = await decodeSdJwt(presentation.presentation, generateDigest)
|
|
232
|
+
expect(decoded.kbJwt).toBeDefined()
|
|
233
|
+
expect(((decoded.kbJwt as KBJwt).payload as kbPayload).aud).toBe('1')
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
it('includes no holder reference', async () => {
|
|
237
|
+
const newClaims = JSON.parse(JSON.stringify(claims))
|
|
238
|
+
newClaims.sub = undefined
|
|
239
|
+
const credentialPayload: SdJwtVcPayload = {
|
|
240
|
+
...newClaims,
|
|
241
|
+
iss: issuer,
|
|
242
|
+
iat: new Date().getTime() / 1000,
|
|
243
|
+
vct: '',
|
|
244
|
+
}
|
|
245
|
+
const credential = await agent.createSdJwtVc({
|
|
246
|
+
credentialPayload,
|
|
247
|
+
disclosureFrame,
|
|
248
|
+
})
|
|
249
|
+
const presentation = agent.createSdJwtPresentation({
|
|
250
|
+
presentation: credential.credential,
|
|
251
|
+
presentationFrame: { given_name: true },
|
|
252
|
+
kb: {
|
|
253
|
+
payload: {
|
|
254
|
+
aud: '1',
|
|
255
|
+
iat: 1,
|
|
256
|
+
nonce: '342',
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
})
|
|
260
|
+
expect(presentation).rejects.toThrow('credential does not include a holder reference')
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
it('verify a presentation', async () => {
|
|
264
|
+
const holderDId = await agent.resolveDid({ didUrl: holder })
|
|
265
|
+
const jwk: JsonWebKey = (
|
|
266
|
+
(holderDId.didDocument as DIDDocument).verificationMethod as VerificationMethod[]
|
|
267
|
+
)[0].publicKeyJwk as JsonWebKey
|
|
268
|
+
const credentialPayload: SdJwtVcPayload = {
|
|
269
|
+
...claims,
|
|
270
|
+
iss: issuer,
|
|
271
|
+
iat: new Date().getTime() / 1000,
|
|
272
|
+
vct: '',
|
|
273
|
+
cnf: {
|
|
274
|
+
jwk,
|
|
275
|
+
},
|
|
276
|
+
}
|
|
277
|
+
const credential = await agent.createSdJwtVc({
|
|
278
|
+
credentialPayload,
|
|
279
|
+
disclosureFrame,
|
|
280
|
+
})
|
|
281
|
+
const presentation = await agent.createSdJwtPresentation({
|
|
282
|
+
presentation: credential.credential,
|
|
283
|
+
presentationFrame: { given_name: true },
|
|
284
|
+
kb: {
|
|
285
|
+
payload: {
|
|
286
|
+
aud: '1',
|
|
287
|
+
iat: 1,
|
|
288
|
+
nonce: '342',
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
})
|
|
292
|
+
const result = await agent.verifySdJwtPresentation({
|
|
293
|
+
presentation: presentation.presentation,
|
|
294
|
+
requiredClaimKeys: ['given_name'],
|
|
295
|
+
// we are not able to verify the kb yet since we have no reference to the public key of the holder.
|
|
296
|
+
kb: true,
|
|
297
|
+
})
|
|
298
|
+
expect(result).toBeDefined()
|
|
299
|
+
expect((result.verifiedPayloads.payload as typeof claims).given_name).toBe('John')
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
it('verify a presentation with sub set', async () => {
|
|
303
|
+
const holderDId = await agent.resolveDid({ didUrl: holder })
|
|
304
|
+
const jwk: JsonWebKey = (
|
|
305
|
+
(holderDId.didDocument as DIDDocument).verificationMethod as VerificationMethod[]
|
|
306
|
+
)[0].publicKeyJwk as JsonWebKey
|
|
307
|
+
const credentialPayload: SdJwtVcPayload = {
|
|
308
|
+
...claims,
|
|
309
|
+
iss: issuer,
|
|
310
|
+
iat: new Date().getTime() / 1000,
|
|
311
|
+
vct: '',
|
|
312
|
+
cnf: {
|
|
313
|
+
jwk,
|
|
314
|
+
},
|
|
315
|
+
}
|
|
316
|
+
const credential = await agent.createSdJwtVc({
|
|
317
|
+
credentialPayload,
|
|
318
|
+
disclosureFrame,
|
|
319
|
+
})
|
|
320
|
+
const presentation = await agent.createSdJwtPresentation({
|
|
321
|
+
presentation: credential.credential,
|
|
322
|
+
presentationFrame: { given_name: true },
|
|
323
|
+
kb: {
|
|
324
|
+
payload: {
|
|
325
|
+
aud: '1',
|
|
326
|
+
iat: 1,
|
|
327
|
+
nonce: '342',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
})
|
|
331
|
+
const result = await agent.verifySdJwtPresentation({
|
|
332
|
+
presentation: presentation.presentation,
|
|
333
|
+
requiredClaimKeys: ['given_name'],
|
|
334
|
+
// we are not able to verify the kb yet since we have no reference to the public key of the holder.
|
|
335
|
+
kb: true,
|
|
336
|
+
})
|
|
337
|
+
expect(result).toBeDefined()
|
|
338
|
+
expect((result.verifiedPayloads.payload as typeof claims).given_name).toBe('John')
|
|
339
|
+
})
|
|
340
|
+
})
|