@sphereon/ssi-sdk.vc-status-list 0.34.1-feature.SSISDK.17.bitstring.sl.9 → 0.34.1-feature.disable.test.8
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 +29 -309
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -49
- package/dist/index.d.ts +8 -49
- package/dist/index.js +30 -310
- package/dist/index.js.map +1 -1
- package/package.json +7 -8
- package/src/functions.ts +10 -19
- package/src/impl/IStatusList.ts +2 -3
- package/src/impl/OAuthStatusList.ts +11 -17
- package/src/impl/StatusList2021.ts +3 -3
- package/src/impl/StatusListFactory.ts +0 -2
- package/src/types/index.ts +4 -48
- package/src/utils.ts +2 -35
- package/src/impl/BitstringStatusListImplementation.ts +0 -301
- package/src/types/BitstringStatusList.ts +0 -4
package/src/impl/IStatusList.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { IAgentContext, ICredentialPlugin } from '@veramo/core'
|
|
2
2
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
3
|
-
import {
|
|
4
|
-
BitstringStatus,
|
|
3
|
+
import type {
|
|
5
4
|
CheckStatusIndexArgs,
|
|
6
5
|
CreateStatusListArgs,
|
|
7
6
|
Status2021,
|
|
@@ -34,7 +33,7 @@ export interface IStatusList {
|
|
|
34
33
|
/**
|
|
35
34
|
* Checks the status at a given index in the status list
|
|
36
35
|
*/
|
|
37
|
-
checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth
|
|
36
|
+
checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth>
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* Collects the status list details
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IAgentContext, ICredentialPlugin, IKeyManager } from '@veramo/core'
|
|
2
|
-
import { type CompactJWT, type
|
|
2
|
+
import { type CompactJWT, type CWT, type CredentialProofFormat, StatusListType } from '@sphereon/ssi-types'
|
|
3
3
|
import type {
|
|
4
4
|
CheckStatusIndexArgs,
|
|
5
5
|
CreateStatusListArgs,
|
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
UpdateStatusListFromEncodedListArgs,
|
|
11
11
|
UpdateStatusListIndexArgs,
|
|
12
12
|
} from '../types'
|
|
13
|
-
import { determineProofFormat,
|
|
13
|
+
import { determineProofFormat, getAssertedValue, getAssertedValues } from '../utils'
|
|
14
14
|
import type { IStatusList } from './IStatusList'
|
|
15
15
|
import { StatusList } from '@sd-jwt/jwt-status-list'
|
|
16
16
|
import type { IJwtService } from '@sphereon/ssi-sdk-ext.jwt-service'
|
|
@@ -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
|
|
|
@@ -32,8 +32,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
32
32
|
|
|
33
33
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
|
|
34
34
|
const { issuer, id, oauthStatusList, keyRef } = args
|
|
35
|
-
const { bitsPerStatus } = oauthStatusList
|
|
36
|
-
const expiresAt = ensureDate(oauthStatusList.expiresAt)
|
|
35
|
+
const { bitsPerStatus, expiresAt } = oauthStatusList
|
|
37
36
|
const length = args.length ?? DEFAULT_LIST_LENGTH
|
|
38
37
|
const issuerString = typeof issuer === 'string' ? issuer : issuer.id
|
|
39
38
|
const correlationId = getAssertedValue('correlationId', args.correlationId)
|
|
@@ -57,8 +56,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
async updateStatusListIndex(args: UpdateStatusListIndexArgs, context: IRequiredContext): Promise<StatusListResult> {
|
|
60
|
-
const { statusListCredential, value, keyRef } = args
|
|
61
|
-
const expiresAt = ensureDate(oauthStatusList.expiresAt)
|
|
59
|
+
const { statusListCredential, value, expiresAt, keyRef } = args
|
|
62
60
|
if (typeof statusListCredential !== 'string') {
|
|
63
61
|
return Promise.reject('statusListCredential in neither JWT nor CWT')
|
|
64
62
|
}
|
|
@@ -72,10 +70,6 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
72
70
|
throw new Error('Status list index out of bounds')
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
if (typeof value !== 'number') {
|
|
76
|
-
throw new Error('Status list values should be of type number')
|
|
77
|
-
}
|
|
78
|
-
|
|
79
73
|
statusList.setStatus(index, value)
|
|
80
74
|
const { statusListCredential: signedCredential, encodedList } = await this.createSignedStatusList(
|
|
81
75
|
proofFormat,
|
|
@@ -108,15 +102,15 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
108
102
|
throw new Error('OAuthStatusList options are required for type OAuthStatusList')
|
|
109
103
|
}
|
|
110
104
|
const { proofFormat, oauthStatusList, keyRef } = args
|
|
111
|
-
const { bitsPerStatus } = oauthStatusList
|
|
112
|
-
const expiresAt = ensureDate(oauthStatusList.expiresAt)
|
|
105
|
+
const { bitsPerStatus, expiresAt } = oauthStatusList
|
|
113
106
|
|
|
114
107
|
const { issuer, id } = getAssertedValues(args)
|
|
115
108
|
const issuerString = typeof issuer === 'string' ? issuer : issuer.id
|
|
116
109
|
|
|
117
110
|
const listToUpdate = StatusList.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS)
|
|
118
111
|
const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
|
|
119
|
-
|
|
112
|
+
// FIXME: See above.
|
|
113
|
+
listToUpdate.setStatus(index, args.value ? 1 : 0)
|
|
120
114
|
|
|
121
115
|
const { statusListCredential, encodedList } = await this.createSignedStatusList(
|
|
122
116
|
proofFormat ?? DEFAULT_PROOF_FORMAT,
|
|
@@ -144,7 +138,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
144
138
|
}
|
|
145
139
|
}
|
|
146
140
|
|
|
147
|
-
private buildContentType(proofFormat:
|
|
141
|
+
private buildContentType(proofFormat: 'jwt' | 'lds' | 'EthereumEip712Signature2021' | 'cbor' | undefined) {
|
|
148
142
|
return `application/statuslist+${proofFormat === 'cbor' ? 'cwt' : 'jwt'}`
|
|
149
143
|
}
|
|
150
144
|
|
|
@@ -159,7 +153,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
159
153
|
|
|
160
154
|
const index = typeof statusListIndex === 'number' ? statusListIndex : parseInt(statusListIndex)
|
|
161
155
|
if (index < 0 || index >= statusList.statusList.length) {
|
|
162
|
-
throw new Error(
|
|
156
|
+
throw new Error('Status list index out of bounds')
|
|
163
157
|
}
|
|
164
158
|
|
|
165
159
|
return statusList.getStatus(index)
|
|
@@ -190,7 +184,7 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
190
184
|
}
|
|
191
185
|
|
|
192
186
|
private async createSignedStatusList(
|
|
193
|
-
proofFormat:
|
|
187
|
+
proofFormat: 'jwt' | 'lds' | 'EthereumEip712Signature2021' | 'cbor',
|
|
194
188
|
context: IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>,
|
|
195
189
|
statusList: StatusList,
|
|
196
190
|
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 VeramoProofFormat
|
|
28
28
|
|
|
29
29
|
export class StatusList2021Implementation implements IStatusList {
|
|
30
30
|
async createNewStatusList(
|
|
@@ -126,7 +126,7 @@ export class StatusList2021Implementation implements IStatusList {
|
|
|
126
126
|
const { issuer, id } = getAssertedValues(args)
|
|
127
127
|
const statusList = await StatusList.decode({ encodedList: args.encodedList })
|
|
128
128
|
const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
|
|
129
|
-
statusList.setStatus(index, args.value
|
|
129
|
+
statusList.setStatus(index, args.value)
|
|
130
130
|
|
|
131
131
|
const newEncodedList = await statusList.encode()
|
|
132
132
|
const credential = await this.createVerifiableCredential(
|
|
@@ -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: 'jwt' | 'lds' | 'EthereumEip712Signature2021' | 'cbor' | undefined) {
|
|
238
238
|
switch (proofFormat) {
|
|
239
239
|
case 'jwt':
|
|
240
240
|
return `application/statuslist+jwt`
|
|
@@ -2,7 +2,6 @@ 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'
|
|
6
5
|
|
|
7
6
|
export class StatusListFactory {
|
|
8
7
|
private static instance: StatusListFactory
|
|
@@ -12,7 +11,6 @@ export class StatusListFactory {
|
|
|
12
11
|
this.implementations = new Map()
|
|
13
12
|
this.implementations.set(StatusListType.StatusList2021, new StatusList2021Implementation())
|
|
14
13
|
this.implementations.set(StatusListType.OAuthStatusList, new OAuthStatusListImplementation())
|
|
15
|
-
this.implementations.set(StatusListType.BitstringStatusList, new BitstringStatusListImplementation())
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
public static getInstance(): StatusListFactory {
|
package/src/types/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
2
2
|
import {
|
|
3
|
-
type CredentialProofFormat,
|
|
4
3
|
type ICredential,
|
|
5
4
|
type ICredentialStatus,
|
|
6
5
|
type IIssuer,
|
|
7
6
|
type IVerifiableCredential,
|
|
8
7
|
type OrPromise,
|
|
8
|
+
type CredentialProofFormat,
|
|
9
9
|
type StatusListCredential,
|
|
10
10
|
StatusListCredentialIdMode,
|
|
11
11
|
StatusListDriverType,
|
|
@@ -26,7 +26,6 @@ import { DataSource } from 'typeorm'
|
|
|
26
26
|
import type { BitsPerStatus } from '@sd-jwt/jwt-status-list'
|
|
27
27
|
import type { SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
|
|
28
28
|
import type { StatusListOpts } from '@sphereon/oid4vci-common'
|
|
29
|
-
import { BitstringStatusPurpose } from '@4sure-tech/vc-bitstring-status-lists'
|
|
30
29
|
|
|
31
30
|
export enum StatusOAuth {
|
|
32
31
|
Valid = 0,
|
|
@@ -39,8 +38,6 @@ export enum Status2021 {
|
|
|
39
38
|
Invalid = 1,
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
export type BitstringStatus = number
|
|
43
|
-
|
|
44
41
|
export type StatusList2021Args = {
|
|
45
42
|
indexingDirection: StatusListIndexingDirection
|
|
46
43
|
statusPurpose?: StatusPurpose2021
|
|
@@ -52,14 +49,6 @@ export type OAuthStatusListArgs = {
|
|
|
52
49
|
expiresAt?: Date
|
|
53
50
|
}
|
|
54
51
|
|
|
55
|
-
export type BitstringStatusListArgs = {
|
|
56
|
-
statusPurpose: BitstringStatusPurpose
|
|
57
|
-
bitsPerStatus: number
|
|
58
|
-
ttl?: number
|
|
59
|
-
validFrom?: Date
|
|
60
|
-
validUntil?: Date
|
|
61
|
-
}
|
|
62
|
-
|
|
63
52
|
export type BaseCreateNewStatusListArgs = {
|
|
64
53
|
type: StatusListType
|
|
65
54
|
id: string
|
|
@@ -70,7 +59,6 @@ export type BaseCreateNewStatusListArgs = {
|
|
|
70
59
|
keyRef?: string
|
|
71
60
|
statusList2021?: StatusList2021Args
|
|
72
61
|
oauthStatusList?: OAuthStatusListArgs
|
|
73
|
-
bitstringStatusList?: BitstringStatusListArgs
|
|
74
62
|
driverType?: StatusListDriverType
|
|
75
63
|
}
|
|
76
64
|
|
|
@@ -83,18 +71,10 @@ export type UpdateOAuthStatusListArgs = {
|
|
|
83
71
|
expiresAt?: Date
|
|
84
72
|
}
|
|
85
73
|
|
|
86
|
-
export type UpdateBitstringStatusListArgs = {
|
|
87
|
-
statusPurpose: BitstringStatusPurpose
|
|
88
|
-
bitsPerStatus: number
|
|
89
|
-
validFrom?: Date
|
|
90
|
-
validUntil?: Date
|
|
91
|
-
ttl?: number
|
|
92
|
-
}
|
|
93
|
-
|
|
94
74
|
export interface UpdateStatusListFromEncodedListArgs {
|
|
95
75
|
type?: StatusListType
|
|
96
76
|
statusListIndex: number | string
|
|
97
|
-
value:
|
|
77
|
+
value: boolean
|
|
98
78
|
proofFormat?: CredentialProofFormat
|
|
99
79
|
keyRef?: string
|
|
100
80
|
correlationId?: string
|
|
@@ -103,14 +83,13 @@ export interface UpdateStatusListFromEncodedListArgs {
|
|
|
103
83
|
id: string
|
|
104
84
|
statusList2021?: UpdateStatusList2021Args
|
|
105
85
|
oauthStatusList?: UpdateOAuthStatusListArgs
|
|
106
|
-
bitstringStatusList?: UpdateBitstringStatusListArgs
|
|
107
86
|
}
|
|
108
87
|
|
|
109
88
|
export interface UpdateStatusListFromStatusListCredentialArgs {
|
|
110
89
|
statusListCredential: StatusListCredential // | CompactJWT
|
|
111
90
|
keyRef?: string
|
|
112
91
|
statusListIndex: number | string
|
|
113
|
-
value: number | Status2021 | StatusOAuth
|
|
92
|
+
value: number | Status2021 | StatusOAuth
|
|
114
93
|
}
|
|
115
94
|
|
|
116
95
|
export interface StatusListResult {
|
|
@@ -124,7 +103,6 @@ export interface StatusListResult {
|
|
|
124
103
|
issuer: string | IIssuer
|
|
125
104
|
statusList2021?: StatusList2021Details
|
|
126
105
|
oauthStatusList?: OAuthStatusDetails
|
|
127
|
-
bitstringStatusList?: BitstringStatusDetails
|
|
128
106
|
|
|
129
107
|
// These cannot be deduced from the VC, so they are present when callers pass in these values as params
|
|
130
108
|
correlationId?: string
|
|
@@ -142,14 +120,6 @@ interface OAuthStatusDetails {
|
|
|
142
120
|
expiresAt?: Date
|
|
143
121
|
}
|
|
144
122
|
|
|
145
|
-
interface BitstringStatusDetails {
|
|
146
|
-
statusPurpose: BitstringStatusPurpose
|
|
147
|
-
bitsPerStatus: number
|
|
148
|
-
validFrom?: Date
|
|
149
|
-
validUntil?: Date
|
|
150
|
-
ttl?: number
|
|
151
|
-
}
|
|
152
|
-
|
|
153
123
|
export interface StatusList2021EntryCredentialStatus extends ICredentialStatus {
|
|
154
124
|
type: 'StatusList2021Entry'
|
|
155
125
|
statusPurpose: StatusPurpose2021
|
|
@@ -165,16 +135,6 @@ export interface StatusListOAuthEntryCredentialStatus extends ICredentialStatus
|
|
|
165
135
|
expiresAt?: Date
|
|
166
136
|
}
|
|
167
137
|
|
|
168
|
-
export interface BitstringStatusListEntryCredentialStatus extends ICredentialStatus {
|
|
169
|
-
type: 'BitstringStatusListEntry'
|
|
170
|
-
statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
|
|
171
|
-
statusListIndex: string
|
|
172
|
-
statusListCredential: string
|
|
173
|
-
bitsPerStatus?: number
|
|
174
|
-
statusMessage?: Array<BitstringStatus>
|
|
175
|
-
statusReference?: string | string[]
|
|
176
|
-
}
|
|
177
|
-
|
|
178
138
|
export interface StatusList2021ToVerifiableCredentialArgs {
|
|
179
139
|
issuer: string | IIssuer
|
|
180
140
|
id: string
|
|
@@ -194,14 +154,12 @@ export interface CreateStatusListArgs {
|
|
|
194
154
|
length?: number
|
|
195
155
|
statusList2021?: StatusList2021Args
|
|
196
156
|
oauthStatusList?: OAuthStatusListArgs
|
|
197
|
-
bitstringStatusList?: BitstringStatusListArgs
|
|
198
157
|
}
|
|
199
158
|
|
|
200
159
|
export interface UpdateStatusListIndexArgs {
|
|
201
160
|
statusListCredential: StatusListCredential // | CompactJWT
|
|
202
161
|
statusListIndex: number | string
|
|
203
|
-
value: number | Status2021 | StatusOAuth
|
|
204
|
-
bitsPerStatus?: number
|
|
162
|
+
value: number | Status2021 | StatusOAuth
|
|
205
163
|
keyRef?: string
|
|
206
164
|
expiresAt?: Date
|
|
207
165
|
}
|
|
@@ -209,14 +167,12 @@ export interface UpdateStatusListIndexArgs {
|
|
|
209
167
|
export interface CheckStatusIndexArgs {
|
|
210
168
|
statusListCredential: StatusListCredential // | CompactJWT
|
|
211
169
|
statusListIndex: string | number
|
|
212
|
-
bitsPerStatus?: number
|
|
213
170
|
}
|
|
214
171
|
|
|
215
172
|
export interface ToStatusListDetailsArgs {
|
|
216
173
|
statusListPayload: StatusListCredential
|
|
217
174
|
correlationId?: string
|
|
218
175
|
driverType?: StatusListDriverType
|
|
219
|
-
bitsPerStatus?: number
|
|
220
176
|
}
|
|
221
177
|
|
|
222
178
|
/**
|
package/src/utils.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { jwtDecode } from 'jwt-decode'
|
|
|
11
11
|
|
|
12
12
|
export function getAssertedStatusListType(type?: StatusListType) {
|
|
13
13
|
const assertedType = type ?? StatusListType.StatusList2021
|
|
14
|
-
if (![StatusListType.StatusList2021, StatusListType.OAuthStatusList
|
|
14
|
+
if (![StatusListType.StatusList2021, StatusListType.OAuthStatusList].includes(assertedType)) {
|
|
15
15
|
throw Error(`StatusList type ${assertedType} is not supported (yet)`)
|
|
16
16
|
}
|
|
17
17
|
return assertedType
|
|
@@ -39,9 +39,8 @@ 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', 'EthereumEip712Signature2021']],
|
|
43
43
|
[StatusListType.OAuthStatusList, ['jwt', 'cbor']],
|
|
44
|
-
[StatusListType.BitstringStatusList, ['lds']],
|
|
45
44
|
])
|
|
46
45
|
|
|
47
46
|
export function assertValidProofType(type: StatusListType, proofFormat: CredentialProofFormat) {
|
|
@@ -94,35 +93,3 @@ export function determineProofFormat(credential: StatusListCredential): Credenti
|
|
|
94
93
|
throw Error('Cannot determine credential payload type')
|
|
95
94
|
}
|
|
96
95
|
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Ensures a value is converted to a Date object if it's a valid date string,
|
|
100
|
-
* otherwise returns the original value or undefined
|
|
101
|
-
*
|
|
102
|
-
* @param value - The value to convert to Date (can be Date, string, or undefined)
|
|
103
|
-
* @returns Date object, undefined, or the original value if conversion fails
|
|
104
|
-
*/
|
|
105
|
-
export function ensureDate(value: Date | string | undefined): Date | undefined {
|
|
106
|
-
if (value === undefined || value === null) {
|
|
107
|
-
return undefined
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (value instanceof Date) {
|
|
111
|
-
return value
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (typeof value === 'string') {
|
|
115
|
-
if (value.trim() === '') {
|
|
116
|
-
return undefined
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const date = new Date(value)
|
|
120
|
-
// Check if the date is valid
|
|
121
|
-
if (isNaN(date.getTime())) {
|
|
122
|
-
return undefined
|
|
123
|
-
}
|
|
124
|
-
return date
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return undefined
|
|
128
|
-
}
|
|
@@ -1,301 +0,0 @@
|
|
|
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
|
-
CredentialMapper,
|
|
5
|
-
type CredentialProofFormat,
|
|
6
|
-
DocumentFormat,
|
|
7
|
-
type IIssuer,
|
|
8
|
-
type StatusListCredential,
|
|
9
|
-
StatusListType,
|
|
10
|
-
} from '@sphereon/ssi-types'
|
|
11
|
-
|
|
12
|
-
import type { IStatusList } from './IStatusList'
|
|
13
|
-
import {
|
|
14
|
-
BitstringStatus,
|
|
15
|
-
CheckStatusIndexArgs,
|
|
16
|
-
CreateStatusListArgs,
|
|
17
|
-
StatusListResult,
|
|
18
|
-
ToStatusListDetailsArgs,
|
|
19
|
-
UpdateStatusListFromEncodedListArgs,
|
|
20
|
-
UpdateStatusListIndexArgs,
|
|
21
|
-
} from '../types'
|
|
22
|
-
|
|
23
|
-
import { assertValidProofType, ensureDate, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
|
|
24
|
-
import { BitstringStatusListCredential } from '../types/BitstringStatusList'
|
|
25
|
-
import { BitstreamStatusList, BitstringStatusPurpose, createStatusListCredential } from '@4sure-tech/vc-bitstring-status-lists'
|
|
26
|
-
|
|
27
|
-
export const DEFAULT_LIST_LENGTH = 131072 // W3C spec minimum
|
|
28
|
-
export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
|
|
29
|
-
export const DEFAULT_STATUS_PURPOSE: BitstringStatusPurpose = 'revocation'
|
|
30
|
-
|
|
31
|
-
export class BitstringStatusListImplementation implements IStatusList {
|
|
32
|
-
async createNewStatusList(
|
|
33
|
-
args: CreateStatusListArgs,
|
|
34
|
-
context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
|
|
35
|
-
): Promise<StatusListResult> {
|
|
36
|
-
if (!args.bitstringStatusList) {
|
|
37
|
-
throw new Error('BitstringStatusList options are required for type BitstringStatusList')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const length = args?.length ?? DEFAULT_LIST_LENGTH
|
|
41
|
-
const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
|
|
42
|
-
assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
|
|
43
|
-
const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
|
|
44
|
-
|
|
45
|
-
const { issuer, id } = args
|
|
46
|
-
const correlationId = getAssertedValue('correlationId', args.correlationId)
|
|
47
|
-
const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList
|
|
48
|
-
const statusListCredential = await this.createVerifiableCredential(
|
|
49
|
-
{
|
|
50
|
-
...args,
|
|
51
|
-
proofFormat: veramoProofFormat,
|
|
52
|
-
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
53
|
-
validFrom: ensureDate(validFrom),
|
|
54
|
-
validUntil: ensureDate(validUntil),
|
|
55
|
-
ttl,
|
|
56
|
-
},
|
|
57
|
-
context,
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
encodedList: statusListCredential.credentialSubject.encodedList,
|
|
62
|
-
statusListCredential: statusListCredential,
|
|
63
|
-
bitstringStatusList: {
|
|
64
|
-
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
65
|
-
...(statusListCredential.validFrom && { validFrom: new Date(statusListCredential.validFrom) }),
|
|
66
|
-
...(statusListCredential.validUntil && { validUntil: new Date(statusListCredential.validUntil) }),
|
|
67
|
-
ttl,
|
|
68
|
-
bitsPerStatus,
|
|
69
|
-
},
|
|
70
|
-
length,
|
|
71
|
-
type: StatusListType.BitstringStatusList,
|
|
72
|
-
proofFormat,
|
|
73
|
-
id,
|
|
74
|
-
correlationId,
|
|
75
|
-
issuer,
|
|
76
|
-
statuslistContentType: this.buildContentType(proofFormat),
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async updateStatusListIndex(
|
|
81
|
-
args: UpdateStatusListIndexArgs,
|
|
82
|
-
context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
|
|
83
|
-
): Promise<StatusListResult> {
|
|
84
|
-
if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
|
|
85
|
-
return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)')
|
|
86
|
-
}
|
|
87
|
-
|
|
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: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: origEncodedList, statusSize: args.bitsPerStatus })
|
|
96
|
-
statusList.setStatus(index, args.value)
|
|
97
|
-
|
|
98
|
-
const proofFormat = CredentialMapper.detectDocumentType(credential) === DocumentFormat.JWT ? 'jwt' : 'lds'
|
|
99
|
-
|
|
100
|
-
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
|
|
101
|
-
|
|
102
|
-
const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
|
|
103
|
-
|
|
104
|
-
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
|
|
105
|
-
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
|
|
106
|
-
const ttl = credSubject.ttl
|
|
107
|
-
|
|
108
|
-
const updatedCredential = await this.createVerifiableCredential(
|
|
109
|
-
{
|
|
110
|
-
...args,
|
|
111
|
-
id,
|
|
112
|
-
issuer,
|
|
113
|
-
statusList,
|
|
114
|
-
proofFormat: proofFormat,
|
|
115
|
-
statusPurpose,
|
|
116
|
-
ttl,
|
|
117
|
-
validFrom,
|
|
118
|
-
validUntil,
|
|
119
|
-
},
|
|
120
|
-
context,
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
return {
|
|
124
|
-
statusListCredential: updatedCredential,
|
|
125
|
-
encodedList: updatedCredential.credentialSubject.encodedList,
|
|
126
|
-
bitstringStatusList: {
|
|
127
|
-
statusPurpose,
|
|
128
|
-
...(updatedCredential.validFrom && { validFrom: new Date(updatedCredential.validFrom) }),
|
|
129
|
-
...(updatedCredential.validUntil && { validUntil: new Date(updatedCredential.validUntil) }),
|
|
130
|
-
bitsPerStatus: args.bitsPerStatus,
|
|
131
|
-
ttl,
|
|
132
|
-
},
|
|
133
|
-
length: statusList.getLength(),
|
|
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
|
-
|
|
150
|
-
if (args.bitstringStatusList.bitsPerStatus < 1) {
|
|
151
|
-
return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)')
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList
|
|
155
|
-
|
|
156
|
-
const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
|
|
157
|
-
assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
|
|
158
|
-
const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
|
|
159
|
-
|
|
160
|
-
const { issuer, id } = getAssertedValues(args)
|
|
161
|
-
const statusList: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: args.encodedList, statusSize: bitsPerStatus })
|
|
162
|
-
const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
|
|
163
|
-
statusList.setStatus(index, args.value)
|
|
164
|
-
|
|
165
|
-
const credential = await this.createVerifiableCredential(
|
|
166
|
-
{
|
|
167
|
-
id,
|
|
168
|
-
issuer,
|
|
169
|
-
statusList,
|
|
170
|
-
proofFormat: veramoProofFormat,
|
|
171
|
-
keyRef: args.keyRef,
|
|
172
|
-
statusPurpose,
|
|
173
|
-
validFrom: ensureDate(validFrom),
|
|
174
|
-
validUntil: ensureDate(validUntil),
|
|
175
|
-
ttl,
|
|
176
|
-
},
|
|
177
|
-
context,
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
return {
|
|
181
|
-
type: StatusListType.BitstringStatusList,
|
|
182
|
-
statusListCredential: credential,
|
|
183
|
-
encodedList: credential.credentialSubject.encodedList,
|
|
184
|
-
bitstringStatusList: {
|
|
185
|
-
statusPurpose,
|
|
186
|
-
bitsPerStatus,
|
|
187
|
-
...(credential.validFrom && { validFrom: new Date(credential.validFrom) }),
|
|
188
|
-
...(credential.validUntil && { validUntil: new Date(credential.validUntil) }),
|
|
189
|
-
ttl,
|
|
190
|
-
},
|
|
191
|
-
length: statusList.getLength(),
|
|
192
|
-
proofFormat: args.proofFormat ?? 'lds',
|
|
193
|
-
id: id,
|
|
194
|
-
issuer: issuer,
|
|
195
|
-
statuslistContentType: this.buildContentType(proofFormat),
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
async checkStatusIndex(args: CheckStatusIndexArgs): Promise<BitstringStatus> {
|
|
200
|
-
if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
|
|
201
|
-
return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)')
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const uniform = CredentialMapper.toUniformCredential(args.statusListCredential)
|
|
205
|
-
const { credentialSubject } = uniform
|
|
206
|
-
const encodedList = getAssertedProperty('encodedList', credentialSubject)
|
|
207
|
-
|
|
208
|
-
const statusSize = args.bitsPerStatus
|
|
209
|
-
const statusList = await BitstreamStatusList.decode({ encodedList, statusSize })
|
|
210
|
-
|
|
211
|
-
const numIndex = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
|
|
212
|
-
if (statusList.getLength() <= numIndex) {
|
|
213
|
-
throw new Error(`Status list index out of bounds, has ${statusList.getLength()} entries, requested ${numIndex}`)
|
|
214
|
-
}
|
|
215
|
-
return statusList.getStatus(numIndex)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult> {
|
|
219
|
-
const { statusListPayload, bitsPerStatus } = args
|
|
220
|
-
if (!bitsPerStatus || bitsPerStatus < 1) {
|
|
221
|
-
return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)')
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const uniform = CredentialMapper.toUniformCredential(statusListPayload)
|
|
225
|
-
const { issuer, credentialSubject } = uniform
|
|
226
|
-
const id = getAssertedValue('id', uniform.id)
|
|
227
|
-
const encodedList = getAssertedProperty('encodedList', credentialSubject)
|
|
228
|
-
const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListPayload) === DocumentFormat.JWT ? 'jwt' : 'lds'
|
|
229
|
-
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
|
|
230
|
-
const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
|
|
231
|
-
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
|
|
232
|
-
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
|
|
233
|
-
const ttl = credSubject.ttl
|
|
234
|
-
const statuslistLength: number = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus)
|
|
235
|
-
|
|
236
|
-
return {
|
|
237
|
-
id,
|
|
238
|
-
encodedList,
|
|
239
|
-
issuer,
|
|
240
|
-
type: StatusListType.BitstringStatusList,
|
|
241
|
-
proofFormat,
|
|
242
|
-
length: statuslistLength,
|
|
243
|
-
statusListCredential: statusListPayload,
|
|
244
|
-
statuslistContentType: this.buildContentType(proofFormat),
|
|
245
|
-
bitstringStatusList: {
|
|
246
|
-
statusPurpose,
|
|
247
|
-
bitsPerStatus,
|
|
248
|
-
validFrom,
|
|
249
|
-
validUntil,
|
|
250
|
-
ttl,
|
|
251
|
-
},
|
|
252
|
-
...(args.correlationId && { correlationId: args.correlationId }),
|
|
253
|
-
...(args.driverType && { driverType: args.driverType }),
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
private async createVerifiableCredential(
|
|
258
|
-
args: {
|
|
259
|
-
id: string
|
|
260
|
-
issuer: string | IIssuer
|
|
261
|
-
statusList?: BitstreamStatusList
|
|
262
|
-
proofFormat: VeramoProofFormat
|
|
263
|
-
statusPurpose: BitstringStatusPurpose
|
|
264
|
-
validFrom?: Date
|
|
265
|
-
validUntil?: Date
|
|
266
|
-
ttl?: number
|
|
267
|
-
keyRef?: string
|
|
268
|
-
},
|
|
269
|
-
context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
|
|
270
|
-
): Promise<BitstringStatusListCredential> {
|
|
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 unsignedCredential = await createStatusListCredential(args)
|
|
278
|
-
|
|
279
|
-
const verifiableCredential = await context.agent.createVerifiableCredential({
|
|
280
|
-
credential: unsignedCredential,
|
|
281
|
-
keyRef: args.keyRef ?? identifier.kmsKeyRef,
|
|
282
|
-
proofFormat: args.proofFormat,
|
|
283
|
-
fetchRemoteContexts: true,
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
return CredentialMapper.toWrappedVerifiableCredential(verifiableCredential as StatusListCredential).original as BitstringStatusListCredential
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
private buildContentType(proofFormat: CredentialProofFormat | undefined) {
|
|
290
|
-
switch (proofFormat) {
|
|
291
|
-
case 'jwt':
|
|
292
|
-
return `application/statuslist+jwt`
|
|
293
|
-
case 'cbor':
|
|
294
|
-
return `application/statuslist+cwt`
|
|
295
|
-
case 'lds':
|
|
296
|
-
return 'application/statuslist+ld+json'
|
|
297
|
-
default:
|
|
298
|
-
throw Error(`Unsupported content type '${proofFormat}' for status lists`)
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|