@sphereon/ssi-sdk.vc-status-list 0.34.0 → 0.34.1-feature.SSISDK.17.bitstring.sl.2
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/dist/index.cjs +287 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -7
- package/dist/index.d.ts +53 -7
- package/dist/index.js +288 -18
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/src/functions.ts +7 -6
- package/src/impl/BitstringStatusListImplementation.ts +334 -0
- package/src/impl/IStatusList.ts +3 -2
- package/src/impl/OAuthStatusList.ts +8 -4
- package/src/impl/StatusList2021.ts +2 -2
- package/src/impl/StatusListFactory.ts +2 -0
- package/src/types/BitstringStatusList.ts +42 -0
- package/src/types/index.ts +56 -3
- package/src/utils.ts +1 -1
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import type { IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat } from '@veramo/core'
|
|
2
|
+
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
3
|
+
import {
|
|
4
|
+
type BitstringStatusPurpose,
|
|
5
|
+
CredentialMapper,
|
|
6
|
+
type CredentialProofFormat,
|
|
7
|
+
DocumentFormat,
|
|
8
|
+
type IIssuer,
|
|
9
|
+
type StatusListCredential,
|
|
10
|
+
StatusListType,
|
|
11
|
+
} from '@sphereon/ssi-types'
|
|
12
|
+
|
|
13
|
+
import type { IStatusList } from './IStatusList'
|
|
14
|
+
import {
|
|
15
|
+
BitstringStatus,
|
|
16
|
+
BitstringStatusResult,
|
|
17
|
+
CheckStatusIndexArgs,
|
|
18
|
+
CreateStatusListArgs,
|
|
19
|
+
StatusListResult,
|
|
20
|
+
ToStatusListDetailsArgs,
|
|
21
|
+
UpdateStatusListFromEncodedListArgs,
|
|
22
|
+
UpdateStatusListIndexArgs,
|
|
23
|
+
} from '../types'
|
|
24
|
+
|
|
25
|
+
import { assertValidProofType, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
|
|
26
|
+
import { createList, decodeList } from '@digitalbazaar/vc-bitstring-status-list'
|
|
27
|
+
import { IBitstringStatusList } from '../types/BitstringStatusList'
|
|
28
|
+
|
|
29
|
+
export const DEFAULT_LIST_LENGTH = 131072 // W3C spec minimum
|
|
30
|
+
export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
|
|
31
|
+
export const DEFAULT_STATUS_SIZE = 1
|
|
32
|
+
export const DEFAULT_STATUS_PURPOSE: BitstringStatusPurpose = 'revocation'
|
|
33
|
+
|
|
34
|
+
export class BitstringStatusListImplementation implements IStatusList {
|
|
35
|
+
async createNewStatusList(
|
|
36
|
+
args: CreateStatusListArgs,
|
|
37
|
+
context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
|
|
38
|
+
): Promise<StatusListResult> {
|
|
39
|
+
if (!args.bitstringStatusList) {
|
|
40
|
+
throw new Error('BitstringStatusList options are required for type BitstringStatusList')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const length = args?.length ?? DEFAULT_LIST_LENGTH
|
|
44
|
+
const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
|
|
45
|
+
assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
|
|
46
|
+
const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
|
|
47
|
+
|
|
48
|
+
const { issuer, id } = args
|
|
49
|
+
const correlationId = getAssertedValue('correlationId', args.correlationId)
|
|
50
|
+
const { statusPurpose, statusSize, statusMessage, ttl } = args.bitstringStatusList
|
|
51
|
+
const list = (await createList({ length })) as IBitstringStatusList
|
|
52
|
+
const encodedList = await list.encode()
|
|
53
|
+
|
|
54
|
+
const statusListCredential = await this.createVerifiableCredential(
|
|
55
|
+
{
|
|
56
|
+
...args,
|
|
57
|
+
encodedList,
|
|
58
|
+
proofFormat: veramoProofFormat,
|
|
59
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
60
|
+
statusSize: statusSize ?? DEFAULT_STATUS_SIZE,
|
|
61
|
+
statusMessage: statusMessage,
|
|
62
|
+
ttl,
|
|
63
|
+
},
|
|
64
|
+
context,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
encodedList,
|
|
69
|
+
statusListCredential: statusListCredential,
|
|
70
|
+
bitstringStatusList: {
|
|
71
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
72
|
+
ttl,
|
|
73
|
+
},
|
|
74
|
+
length,
|
|
75
|
+
type: StatusListType.BitstringStatusList,
|
|
76
|
+
proofFormat,
|
|
77
|
+
id,
|
|
78
|
+
correlationId,
|
|
79
|
+
issuer,
|
|
80
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async updateStatusListIndex(
|
|
85
|
+
args: UpdateStatusListIndexArgs,
|
|
86
|
+
context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
|
|
87
|
+
): Promise<StatusListResult> {
|
|
88
|
+
const credential = args.statusListCredential
|
|
89
|
+
const uniform = CredentialMapper.toUniformCredential(credential)
|
|
90
|
+
const { issuer, credentialSubject } = uniform
|
|
91
|
+
const id = getAssertedValue('id', uniform.id)
|
|
92
|
+
const origEncodedList = getAssertedProperty('encodedList', credentialSubject)
|
|
93
|
+
|
|
94
|
+
const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
|
|
95
|
+
const statusList = (await decodeList({ encodedList: origEncodedList })) as IBitstringStatusList
|
|
96
|
+
statusList.setStatus(index, args.value != 0)
|
|
97
|
+
const encodedList = await statusList.encode()
|
|
98
|
+
|
|
99
|
+
const proofFormat = CredentialMapper.detectDocumentType(credential) === DocumentFormat.JWT ? 'jwt' : 'lds'
|
|
100
|
+
|
|
101
|
+
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
|
|
102
|
+
|
|
103
|
+
const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
|
|
104
|
+
|
|
105
|
+
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
|
|
106
|
+
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
|
|
107
|
+
const ttl = credSubject.ttl
|
|
108
|
+
|
|
109
|
+
const updatedCredential = await this.createVerifiableCredential(
|
|
110
|
+
{
|
|
111
|
+
...args,
|
|
112
|
+
id,
|
|
113
|
+
issuer,
|
|
114
|
+
encodedList,
|
|
115
|
+
proofFormat: proofFormat,
|
|
116
|
+
statusPurpose,
|
|
117
|
+
ttl,
|
|
118
|
+
validFrom,
|
|
119
|
+
validUntil,
|
|
120
|
+
},
|
|
121
|
+
context,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
statusListCredential: updatedCredential,
|
|
126
|
+
encodedList,
|
|
127
|
+
bitstringStatusList: {
|
|
128
|
+
statusPurpose,
|
|
129
|
+
validFrom,
|
|
130
|
+
validUntil,
|
|
131
|
+
ttl,
|
|
132
|
+
},
|
|
133
|
+
length: statusList.length - 1,
|
|
134
|
+
type: StatusListType.BitstringStatusList,
|
|
135
|
+
proofFormat: proofFormat,
|
|
136
|
+
id,
|
|
137
|
+
issuer,
|
|
138
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async updateStatusListFromEncodedList(
|
|
143
|
+
args: UpdateStatusListFromEncodedListArgs,
|
|
144
|
+
context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
|
|
145
|
+
): Promise<StatusListResult> {
|
|
146
|
+
if (!args.bitstringStatusList) {
|
|
147
|
+
throw new Error('bitstringStatusList options required for type BitstringStatusList')
|
|
148
|
+
}
|
|
149
|
+
const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
|
|
150
|
+
assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
|
|
151
|
+
const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
|
|
152
|
+
|
|
153
|
+
const { issuer, id } = getAssertedValues(args)
|
|
154
|
+
const statusList = (await decodeList({ encodedList: args.encodedList })) as IBitstringStatusList
|
|
155
|
+
const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
|
|
156
|
+
statusList.setStatus(index, args.value)
|
|
157
|
+
|
|
158
|
+
const newEncodedList = await statusList.encode()
|
|
159
|
+
const { statusPurpose, statusSize, statusMessage, ttl, validFrom, validUntil } = args.bitstringStatusList
|
|
160
|
+
|
|
161
|
+
const credential = await this.createVerifiableCredential(
|
|
162
|
+
{
|
|
163
|
+
id,
|
|
164
|
+
issuer,
|
|
165
|
+
encodedList: newEncodedList,
|
|
166
|
+
proofFormat: veramoProofFormat,
|
|
167
|
+
keyRef: args.keyRef,
|
|
168
|
+
statusPurpose,
|
|
169
|
+
statusSize,
|
|
170
|
+
statusMessage,
|
|
171
|
+
validFrom,
|
|
172
|
+
validUntil,
|
|
173
|
+
ttl,
|
|
174
|
+
},
|
|
175
|
+
context,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
type: StatusListType.BitstringStatusList,
|
|
180
|
+
statusListCredential: credential,
|
|
181
|
+
encodedList: newEncodedList,
|
|
182
|
+
bitstringStatusList: {
|
|
183
|
+
statusPurpose,
|
|
184
|
+
validFrom,
|
|
185
|
+
validUntil,
|
|
186
|
+
ttl,
|
|
187
|
+
},
|
|
188
|
+
length: statusList.length,
|
|
189
|
+
proofFormat: args.proofFormat ?? 'lds',
|
|
190
|
+
id: id,
|
|
191
|
+
issuer: issuer,
|
|
192
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async checkStatusIndex(args: CheckStatusIndexArgs): Promise<BitstringStatusResult> {
|
|
197
|
+
const uniform = CredentialMapper.toUniformCredential(args.statusListCredential)
|
|
198
|
+
const { credentialSubject } = uniform
|
|
199
|
+
const encodedList = getAssertedProperty('encodedList', credentialSubject)
|
|
200
|
+
|
|
201
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
|
|
202
|
+
const messageList = (subject as any).statusMessage as Array<Partial<BitstringStatus>>
|
|
203
|
+
|
|
204
|
+
const numIndex = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
|
|
205
|
+
const hexIndex = `0x${numIndex.toString(16)}`
|
|
206
|
+
const statusMessage = messageList.find((statMsg) => statMsg.status === hexIndex)
|
|
207
|
+
|
|
208
|
+
const statusList = (await decodeList({ encodedList })) as IBitstringStatusList
|
|
209
|
+
if (statusList.length <= numIndex) {
|
|
210
|
+
throw new Error(`Status list index out of bounds, has ${messageList.length} messages, requested ${numIndex}`)
|
|
211
|
+
}
|
|
212
|
+
const value = statusList.getStatus(numIndex)
|
|
213
|
+
return {
|
|
214
|
+
index: numIndex,
|
|
215
|
+
status: hexIndex,
|
|
216
|
+
message: statusMessage?.message,
|
|
217
|
+
set: value,
|
|
218
|
+
} satisfies BitstringStatusResult
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult> {
|
|
222
|
+
const { statusListPayload } = args
|
|
223
|
+
const uniform = CredentialMapper.toUniformCredential(statusListPayload)
|
|
224
|
+
const { issuer, credentialSubject } = uniform
|
|
225
|
+
const id = getAssertedValue('id', uniform.id)
|
|
226
|
+
const encodedList = getAssertedProperty('encodedList', credentialSubject)
|
|
227
|
+
const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListPayload) === DocumentFormat.JWT ? 'jwt' : 'lds'
|
|
228
|
+
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
|
|
229
|
+
const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
|
|
230
|
+
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
|
|
231
|
+
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
|
|
232
|
+
const ttl = credSubject.ttl
|
|
233
|
+
const list = (await decodeList({ encodedList })) as IBitstringStatusList
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
id,
|
|
237
|
+
encodedList,
|
|
238
|
+
issuer,
|
|
239
|
+
type: StatusListType.BitstringStatusList,
|
|
240
|
+
proofFormat,
|
|
241
|
+
length: list.length,
|
|
242
|
+
statusListCredential: statusListPayload,
|
|
243
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
244
|
+
bitstringStatusList: {
|
|
245
|
+
statusPurpose,
|
|
246
|
+
validFrom,
|
|
247
|
+
validUntil,
|
|
248
|
+
ttl,
|
|
249
|
+
},
|
|
250
|
+
...(args.correlationId && { correlationId: args.correlationId }),
|
|
251
|
+
...(args.driverType && { driverType: args.driverType }),
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private async createVerifiableCredential(
|
|
256
|
+
args: {
|
|
257
|
+
id: string
|
|
258
|
+
issuer: string | IIssuer
|
|
259
|
+
encodedList: string
|
|
260
|
+
proofFormat: VeramoProofFormat
|
|
261
|
+
statusPurpose: BitstringStatusPurpose
|
|
262
|
+
statusSize?: number
|
|
263
|
+
statusMessage?: Array<BitstringStatus>
|
|
264
|
+
validFrom?: Date
|
|
265
|
+
validUntil?: Date
|
|
266
|
+
ttl?: number
|
|
267
|
+
keyRef?: string
|
|
268
|
+
},
|
|
269
|
+
context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
|
|
270
|
+
): Promise<StatusListCredential> {
|
|
271
|
+
const identifier = await context.agent.identifierManagedGet({
|
|
272
|
+
identifier: typeof args.issuer === 'string' ? args.issuer : args.issuer.id,
|
|
273
|
+
vmRelationship: 'assertionMethod',
|
|
274
|
+
offlineWhenNoDIDRegistered: true,
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
const credentialSubject: any = {
|
|
278
|
+
id: args.id,
|
|
279
|
+
type: 'BitstringStatusList',
|
|
280
|
+
statusPurpose: args.statusPurpose,
|
|
281
|
+
encodedList: args.encodedList,
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (args.statusSize && args.statusSize > 1) {
|
|
285
|
+
credentialSubject.statusSize = args.statusSize
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (args.statusMessage) {
|
|
289
|
+
credentialSubject.statusMessage = args.statusMessage
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (args.validFrom) {
|
|
293
|
+
credentialSubject.validFrom = args.validFrom
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (args.validUntil) {
|
|
297
|
+
credentialSubject.validUntil = args.validUntil
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (args.ttl) {
|
|
301
|
+
credentialSubject.ttl = args.ttl
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const credential = {
|
|
305
|
+
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://www.w3.org/ns/credentials/status/v1'],
|
|
306
|
+
id: args.id,
|
|
307
|
+
issuer: args.issuer,
|
|
308
|
+
type: ['VerifiableCredential', 'BitstringStatusListCredential'],
|
|
309
|
+
credentialSubject,
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const verifiableCredential = await context.agent.createVerifiableCredential({
|
|
313
|
+
credential,
|
|
314
|
+
keyRef: args.keyRef ?? identifier.kmsKeyRef,
|
|
315
|
+
proofFormat: args.proofFormat,
|
|
316
|
+
fetchRemoteContexts: true,
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
return CredentialMapper.toWrappedVerifiableCredential(verifiableCredential as StatusListCredential).original as StatusListCredential
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
private buildContentType(proofFormat: CredentialProofFormat | undefined) {
|
|
323
|
+
switch (proofFormat) {
|
|
324
|
+
case 'jwt':
|
|
325
|
+
return `application/statuslist+jwt`
|
|
326
|
+
case 'cbor':
|
|
327
|
+
return `application/statuslist+cwt`
|
|
328
|
+
case 'lds':
|
|
329
|
+
return 'application/statuslist+ld+json'
|
|
330
|
+
default:
|
|
331
|
+
throw Error(`Unsupported content type '${proofFormat}' for status lists`)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
package/src/impl/IStatusList.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { IAgentContext, ICredentialPlugin } from '@veramo/core'
|
|
2
2
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
3
|
-
import
|
|
3
|
+
import {
|
|
4
|
+
BitstringStatusResult,
|
|
4
5
|
CheckStatusIndexArgs,
|
|
5
6
|
CreateStatusListArgs,
|
|
6
7
|
Status2021,
|
|
@@ -33,7 +34,7 @@ export interface IStatusList {
|
|
|
33
34
|
/**
|
|
34
35
|
* Checks the status at a given index in the status list
|
|
35
36
|
*/
|
|
36
|
-
checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth>
|
|
37
|
+
checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth | BitstringStatusResult>
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Collects the status list details
|
|
@@ -20,7 +20,7 @@ import { createSignedCbor, decodeStatusListCWT } from './encoding/cbor'
|
|
|
20
20
|
|
|
21
21
|
type IRequiredContext = IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>
|
|
22
22
|
|
|
23
|
-
export const DEFAULT_BITS_PER_STATUS = 1 // 1 bit is sufficient for 0x00 - "VALID"
|
|
23
|
+
export const DEFAULT_BITS_PER_STATUS = 1 // 1 bit is sufficient for 0x00 - "VALID" 0x01 - "INVALID" saving space in the process
|
|
24
24
|
export const DEFAULT_LIST_LENGTH = 250000
|
|
25
25
|
export const DEFAULT_PROOF_FORMAT = 'jwt' as CredentialProofFormat
|
|
26
26
|
|
|
@@ -70,6 +70,10 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
70
70
|
throw new Error('Status list index out of bounds')
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
if (typeof value !== 'number') {
|
|
74
|
+
throw new Error('Status list values should be of type number')
|
|
75
|
+
}
|
|
76
|
+
|
|
73
77
|
statusList.setStatus(index, value)
|
|
74
78
|
const { statusListCredential: signedCredential, encodedList } = await this.createSignedStatusList(
|
|
75
79
|
proofFormat,
|
|
@@ -138,7 +142,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
144
|
|
|
141
|
-
private buildContentType(proofFormat:
|
|
145
|
+
private buildContentType(proofFormat: CredentialProofFormat | undefined) {
|
|
142
146
|
return `application/statuslist+${proofFormat === 'cbor' ? 'cwt' : 'jwt'}`
|
|
143
147
|
}
|
|
144
148
|
|
|
@@ -153,7 +157,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
153
157
|
|
|
154
158
|
const index = typeof statusListIndex === 'number' ? statusListIndex : parseInt(statusListIndex)
|
|
155
159
|
if (index < 0 || index >= statusList.statusList.length) {
|
|
156
|
-
throw new Error(
|
|
160
|
+
throw new Error(`Status list index out of bounds, has ${statusList.statusList.length} items, requested ${index}`)
|
|
157
161
|
}
|
|
158
162
|
|
|
159
163
|
return statusList.getStatus(index)
|
|
@@ -184,7 +188,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
184
188
|
}
|
|
185
189
|
|
|
186
190
|
private async createSignedStatusList(
|
|
187
|
-
proofFormat:
|
|
191
|
+
proofFormat: CredentialProofFormat,
|
|
188
192
|
context: IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>,
|
|
189
193
|
statusList: StatusList,
|
|
190
194
|
issuerString: string,
|
|
@@ -24,7 +24,7 @@ import { Status2021 } from '../types'
|
|
|
24
24
|
import { assertValidProofType, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
|
|
25
25
|
|
|
26
26
|
export const DEFAULT_LIST_LENGTH = 250000
|
|
27
|
-
export const DEFAULT_PROOF_FORMAT = 'lds' as
|
|
27
|
+
export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
|
|
28
28
|
|
|
29
29
|
export class StatusList2021Implementation implements IStatusList {
|
|
30
30
|
async createNewStatusList(
|
|
@@ -234,7 +234,7 @@ export class StatusList2021Implementation implements IStatusList {
|
|
|
234
234
|
return CredentialMapper.toWrappedVerifiableCredential(verifiableCredential as StatusListCredential).original as StatusListCredential
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
private buildContentType(proofFormat:
|
|
237
|
+
private buildContentType(proofFormat: CredentialProofFormat | undefined) {
|
|
238
238
|
switch (proofFormat) {
|
|
239
239
|
case 'jwt':
|
|
240
240
|
return `application/statuslist+jwt`
|
|
@@ -2,6 +2,7 @@ import type { IStatusList } from './IStatusList'
|
|
|
2
2
|
import { StatusList2021Implementation } from './StatusList2021'
|
|
3
3
|
import { OAuthStatusListImplementation } from './OAuthStatusList'
|
|
4
4
|
import { StatusListType } from '@sphereon/ssi-types'
|
|
5
|
+
import { BitstringStatusListImplementation } from './BitstringStatusListImplementation'
|
|
5
6
|
|
|
6
7
|
export class StatusListFactory {
|
|
7
8
|
private static instance: StatusListFactory
|
|
@@ -11,6 +12,7 @@ export class StatusListFactory {
|
|
|
11
12
|
this.implementations = new Map()
|
|
12
13
|
this.implementations.set(StatusListType.StatusList2021, new StatusList2021Implementation())
|
|
13
14
|
this.implementations.set(StatusListType.OAuthStatusList, new OAuthStatusListImplementation())
|
|
15
|
+
this.implementations.set(StatusListType.BitstringStatusList, new BitstringStatusListImplementation())
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
public static getInstance(): StatusListFactory {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type BitstringConstructorOptions = {
|
|
2
|
+
length?: number
|
|
3
|
+
buffer?: Uint8Array
|
|
4
|
+
leftToRightIndexing?: boolean
|
|
5
|
+
littleEndianBits?: boolean // deprecated
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type IBitstring = {
|
|
9
|
+
bits: Uint8Array
|
|
10
|
+
length: number
|
|
11
|
+
leftToRightIndexing: boolean
|
|
12
|
+
|
|
13
|
+
set(position: number, on: boolean): void
|
|
14
|
+
get(position: number): boolean
|
|
15
|
+
encodeBits(): Promise<string>
|
|
16
|
+
compressBits(): Promise<Uint8Array>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type BitstringStatic = {
|
|
20
|
+
new (options?: BitstringConstructorOptions): IBitstring
|
|
21
|
+
decodeBits(options: { encoded: string }): Promise<Uint8Array>
|
|
22
|
+
uncompressBits(options: { compressed: Uint8Array }): Promise<Uint8Array>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type BitstringStatusListConstructorOptions = {
|
|
26
|
+
length?: number
|
|
27
|
+
buffer?: Uint8Array
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type IBitstringStatusList = {
|
|
31
|
+
bitstring: IBitstring
|
|
32
|
+
length: number
|
|
33
|
+
|
|
34
|
+
setStatus(index: number, status: boolean): void
|
|
35
|
+
getStatus(index: number): boolean
|
|
36
|
+
encode(): Promise<string>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type BitstringStatusListStatic = {
|
|
40
|
+
new (options?: BitstringStatusListConstructorOptions): IBitstringStatusList
|
|
41
|
+
decode(options: { encodedList: string }): Promise<IBitstringStatusList>
|
|
42
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
2
2
|
import {
|
|
3
|
+
BitstringStatusPurpose,
|
|
4
|
+
type CredentialProofFormat,
|
|
3
5
|
type ICredential,
|
|
4
6
|
type ICredentialStatus,
|
|
5
7
|
type IIssuer,
|
|
6
8
|
type IVerifiableCredential,
|
|
7
9
|
type OrPromise,
|
|
8
|
-
type CredentialProofFormat,
|
|
9
10
|
type StatusListCredential,
|
|
10
11
|
StatusListCredentialIdMode,
|
|
11
12
|
StatusListDriverType,
|
|
@@ -38,6 +39,20 @@ export enum Status2021 {
|
|
|
38
39
|
Invalid = 1,
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
export type BitstringStatus = {
|
|
43
|
+
status: string
|
|
44
|
+
message?: string
|
|
45
|
+
[x: string]: any
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type BitstringStatusResult = BitstringStatus & {
|
|
49
|
+
index: number
|
|
50
|
+
status: string
|
|
51
|
+
set: boolean
|
|
52
|
+
message?: string
|
|
53
|
+
[x: string]: any
|
|
54
|
+
}
|
|
55
|
+
|
|
41
56
|
export type StatusList2021Args = {
|
|
42
57
|
indexingDirection: StatusListIndexingDirection
|
|
43
58
|
statusPurpose?: StatusPurpose2021
|
|
@@ -49,6 +64,15 @@ export type OAuthStatusListArgs = {
|
|
|
49
64
|
expiresAt?: Date
|
|
50
65
|
}
|
|
51
66
|
|
|
67
|
+
export type BitstringStatusListArgs = {
|
|
68
|
+
statusPurpose: BitstringStatusPurpose
|
|
69
|
+
statusSize?: number
|
|
70
|
+
statusMessage?: Array<BitstringStatus>
|
|
71
|
+
ttl?: number
|
|
72
|
+
validFrom?: Date
|
|
73
|
+
validUntil?: Date
|
|
74
|
+
}
|
|
75
|
+
|
|
52
76
|
export type BaseCreateNewStatusListArgs = {
|
|
53
77
|
type: StatusListType
|
|
54
78
|
id: string
|
|
@@ -71,6 +95,15 @@ export type UpdateOAuthStatusListArgs = {
|
|
|
71
95
|
expiresAt?: Date
|
|
72
96
|
}
|
|
73
97
|
|
|
98
|
+
export type UpdateBitstringStatusListArgs = {
|
|
99
|
+
statusPurpose: BitstringStatusPurpose
|
|
100
|
+
statusSize?: number
|
|
101
|
+
statusMessage?: Array<BitstringStatus>
|
|
102
|
+
validFrom?: Date
|
|
103
|
+
validUntil?: Date
|
|
104
|
+
ttl?: number
|
|
105
|
+
}
|
|
106
|
+
|
|
74
107
|
export interface UpdateStatusListFromEncodedListArgs {
|
|
75
108
|
type?: StatusListType
|
|
76
109
|
statusListIndex: number | string
|
|
@@ -83,13 +116,14 @@ export interface UpdateStatusListFromEncodedListArgs {
|
|
|
83
116
|
id: string
|
|
84
117
|
statusList2021?: UpdateStatusList2021Args
|
|
85
118
|
oauthStatusList?: UpdateOAuthStatusListArgs
|
|
119
|
+
bitstringStatusList?: UpdateBitstringStatusListArgs
|
|
86
120
|
}
|
|
87
121
|
|
|
88
122
|
export interface UpdateStatusListFromStatusListCredentialArgs {
|
|
89
123
|
statusListCredential: StatusListCredential // | CompactJWT
|
|
90
124
|
keyRef?: string
|
|
91
125
|
statusListIndex: number | string
|
|
92
|
-
value: number | Status2021 | StatusOAuth
|
|
126
|
+
value: number | Status2021 | StatusOAuth | BitstringStatus
|
|
93
127
|
}
|
|
94
128
|
|
|
95
129
|
export interface StatusListResult {
|
|
@@ -103,6 +137,7 @@ export interface StatusListResult {
|
|
|
103
137
|
issuer: string | IIssuer
|
|
104
138
|
statusList2021?: StatusList2021Details
|
|
105
139
|
oauthStatusList?: OAuthStatusDetails
|
|
140
|
+
bitstringStatusList?: BitstringStatusDetails
|
|
106
141
|
|
|
107
142
|
// These cannot be deduced from the VC, so they are present when callers pass in these values as params
|
|
108
143
|
correlationId?: string
|
|
@@ -120,6 +155,13 @@ interface OAuthStatusDetails {
|
|
|
120
155
|
expiresAt?: Date
|
|
121
156
|
}
|
|
122
157
|
|
|
158
|
+
interface BitstringStatusDetails {
|
|
159
|
+
statusPurpose: BitstringStatusPurpose
|
|
160
|
+
validFrom?: Date
|
|
161
|
+
validUntil?: Date
|
|
162
|
+
ttl?: number
|
|
163
|
+
}
|
|
164
|
+
|
|
123
165
|
export interface StatusList2021EntryCredentialStatus extends ICredentialStatus {
|
|
124
166
|
type: 'StatusList2021Entry'
|
|
125
167
|
statusPurpose: StatusPurpose2021
|
|
@@ -135,6 +177,16 @@ export interface StatusListOAuthEntryCredentialStatus extends ICredentialStatus
|
|
|
135
177
|
expiresAt?: Date
|
|
136
178
|
}
|
|
137
179
|
|
|
180
|
+
export interface BitstringStatusListEntryCredentialStatus extends ICredentialStatus {
|
|
181
|
+
type: 'BitstringStatusListEntry'
|
|
182
|
+
statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
|
|
183
|
+
statusListIndex: string
|
|
184
|
+
statusListCredential: string
|
|
185
|
+
statusSize?: number
|
|
186
|
+
statusMessage?: Array<BitstringStatus>
|
|
187
|
+
statusReference?: string | string[]
|
|
188
|
+
}
|
|
189
|
+
|
|
138
190
|
export interface StatusList2021ToVerifiableCredentialArgs {
|
|
139
191
|
issuer: string | IIssuer
|
|
140
192
|
id: string
|
|
@@ -154,12 +206,13 @@ export interface CreateStatusListArgs {
|
|
|
154
206
|
length?: number
|
|
155
207
|
statusList2021?: StatusList2021Args
|
|
156
208
|
oauthStatusList?: OAuthStatusListArgs
|
|
209
|
+
bitstringStatusList?: BitstringStatusListArgs
|
|
157
210
|
}
|
|
158
211
|
|
|
159
212
|
export interface UpdateStatusListIndexArgs {
|
|
160
213
|
statusListCredential: StatusListCredential // | CompactJWT
|
|
161
214
|
statusListIndex: number | string
|
|
162
|
-
value: number | Status2021 | StatusOAuth
|
|
215
|
+
value: number | Status2021 | StatusOAuth | BitstringStatus
|
|
163
216
|
keyRef?: string
|
|
164
217
|
expiresAt?: Date
|
|
165
218
|
}
|
package/src/utils.ts
CHANGED
|
@@ -39,7 +39,7 @@ export function getAssertedProperty<T extends object>(propertyName: string, obj:
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
const ValidProofTypeMap = new Map<StatusListType, CredentialProofFormat[]>([
|
|
42
|
-
[StatusListType.StatusList2021, ['jwt', 'lds'
|
|
42
|
+
[StatusListType.StatusList2021, ['jwt', 'lds']],
|
|
43
43
|
[StatusListType.OAuthStatusList, ['jwt', 'cbor']],
|
|
44
44
|
])
|
|
45
45
|
|