@dwn-protocol/id-sdk 0.2.5 → 0.2.6
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/package.json +2 -3
- package/src/agent/app-data-store.ts +0 -365
- package/src/agent/did-manager.ts +0 -393
- package/src/agent/dwn-manager.ts +0 -548
- package/src/agent/identity-manager.ts +0 -165
- package/src/agent/index.ts +0 -19
- package/src/agent/json-rpc.ts +0 -107
- package/src/agent/key-manager.ts +0 -302
- package/src/agent/kms-local.ts +0 -412
- package/src/agent/outbox.ts +0 -128
- package/src/agent/rpc-client.ts +0 -223
- package/src/agent/store-managed-did.ts +0 -295
- package/src/agent/store-managed-identity.ts +0 -243
- package/src/agent/store-managed-key.ts +0 -754
- package/src/agent/sync-manager.ts +0 -631
- package/src/agent/test-managed-agent.ts +0 -299
- package/src/agent/types/agent.ts +0 -145
- package/src/agent/types/managed-key.ts +0 -442
- package/src/agent/utils.ts +0 -190
- package/src/common/convert.ts +0 -424
- package/src/common/index.ts +0 -9
- package/src/common/multicodec.ts +0 -176
- package/src/common/object.ts +0 -43
- package/src/common/stores.ts +0 -125
- package/src/common/stream-node.ts +0 -381
- package/src/common/stream.ts +0 -406
- package/src/common/type-utils.ts +0 -117
- package/src/common/types.ts +0 -48
- package/src/credentials/credential-bbs.ts +0 -419
- package/src/credentials/credential.ts +0 -324
- package/src/credentials/index.ts +0 -5
- package/src/credentials/presentation.ts +0 -182
- package/src/credentials/status-list.ts +0 -365
- package/src/credentials/utils.ts +0 -58
- package/src/credentials/validators.ts +0 -52
- package/src/crypto/algorithms-api/aes/base.ts +0 -49
- package/src/crypto/algorithms-api/aes/ctr.ts +0 -51
- package/src/crypto/algorithms-api/aes/index.ts +0 -2
- package/src/crypto/algorithms-api/crypto-algorithm.ts +0 -127
- package/src/crypto/algorithms-api/crypto-key.ts +0 -56
- package/src/crypto/algorithms-api/ec/base.ts +0 -39
- package/src/crypto/algorithms-api/ec/ecdh.ts +0 -53
- package/src/crypto/algorithms-api/ec/ecdsa.ts +0 -37
- package/src/crypto/algorithms-api/ec/eddsa.ts +0 -30
- package/src/crypto/algorithms-api/ec/index.ts +0 -4
- package/src/crypto/algorithms-api/errors.ts +0 -29
- package/src/crypto/algorithms-api/index.ts +0 -6
- package/src/crypto/algorithms-api/pbkdf/index.ts +0 -1
- package/src/crypto/algorithms-api/pbkdf/pbkdf2.ts +0 -91
- package/src/crypto/crypto-algorithms/aes-ctr.ts +0 -70
- package/src/crypto/crypto-algorithms/bbs.ts +0 -110
- package/src/crypto/crypto-algorithms/ecdh.ts +0 -115
- package/src/crypto/crypto-algorithms/ecdsa.ts +0 -111
- package/src/crypto/crypto-algorithms/eddsa.ts +0 -110
- package/src/crypto/crypto-algorithms/index.ts +0 -6
- package/src/crypto/crypto-algorithms/pbkdf2.ts +0 -54
- package/src/crypto/crypto-primitives/aes-ctr.ts +0 -131
- package/src/crypto/crypto-primitives/aes-gcm.ts +0 -138
- package/src/crypto/crypto-primitives/bbs.ts +0 -183
- package/src/crypto/crypto-primitives/concat-kdf.ts +0 -207
- package/src/crypto/crypto-primitives/ed25519.ts +0 -201
- package/src/crypto/crypto-primitives/index.ts +0 -10
- package/src/crypto/crypto-primitives/pbkdf2.ts +0 -78
- package/src/crypto/crypto-primitives/secp256k1.ts +0 -322
- package/src/crypto/crypto-primitives/x25519.ts +0 -101
- package/src/crypto/crypto-primitives/xchacha20-poly1305.ts +0 -46
- package/src/crypto/crypto-primitives/xchacha20.ts +0 -34
- package/src/crypto/index.ts +0 -8
- package/src/crypto/jose.ts +0 -948
- package/src/crypto/types/crypto-key.ts +0 -4
- package/src/crypto/types/iddwn-crypto.ts +0 -119
- package/src/crypto/utils.ts +0 -200
- package/src/did-api.ts +0 -72
- package/src/dids/dht.ts +0 -412
- package/src/dids/did-dht.ts +0 -436
- package/src/dids/did-ion.ts +0 -613
- package/src/dids/did-key.ts +0 -791
- package/src/dids/did-resolver.ts +0 -107
- package/src/dids/index.ts +0 -9
- package/src/dids/resolver-cache-level.ts +0 -82
- package/src/dids/resolver-cache-noop.ts +0 -25
- package/src/dids/types.ts +0 -278
- package/src/dids/utils.ts +0 -129
- package/src/dwn-api.ts +0 -584
- package/src/iddwn.ts +0 -241
- package/src/identity-agent/index.ts +0 -270
- package/src/index.ts +0 -26
- package/src/interfaces/metadata.ts +0 -163
- package/src/interfaces/queue.ts +0 -108
- package/src/interfaces/services.ts +0 -122
- package/src/interfaces/transactions.ts +0 -220
- package/src/protocol.ts +0 -68
- package/src/proxy-agent/index.ts +0 -255
- package/src/record.ts +0 -521
- package/src/service-options.ts +0 -62
- package/src/typings/decentralized-identity__ion-pow-sdk.d.ts +0 -7
- package/src/user-agent/index.ts +0 -295
- package/src/utils.ts +0 -29
- package/src/vc-api.ts +0 -505
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
import type { IDAgent } from '../agent/index.js';
|
|
2
|
-
import type { DwnApi } from '../dwn-api.js';
|
|
3
|
-
import type { Record } from '../record.js';
|
|
4
|
-
import type { VerifiableCredential, SignOptions } from './credential.js';
|
|
5
|
-
import { VerifiableCredential as VC } from './credential.js';
|
|
6
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
7
|
-
import { getCurrentXmlSchema112Timestamp } from './utils.js';
|
|
8
|
-
import { Convert } from '../common/index.js';
|
|
9
|
-
import pako from 'pako';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Constants for Status List 2021 implementation
|
|
13
|
-
*/
|
|
14
|
-
export const STATUS_LIST_DATA_FORMAT = 'application/vc-status-list+jwt';
|
|
15
|
-
export const STATUS_LIST_SCHEMA = 'StatusList2021Credential';
|
|
16
|
-
export const STATUS_LIST_CONTEXT = 'https://w3id.org/vc/status-list/2021/v1';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Status purpose types as per Status List 2021 spec
|
|
20
|
-
*/
|
|
21
|
-
export type StatusPurpose = 'revocation' | 'suspension';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Options for creating a status list credential
|
|
25
|
-
*/
|
|
26
|
-
export type CreateStatusListOptions = {
|
|
27
|
-
issuer: string;
|
|
28
|
-
statusPurpose: StatusPurpose;
|
|
29
|
-
signOptions: SignOptions;
|
|
30
|
-
size?: number; // Optional: size of bitstring (default: 131072 bits = 16KB uncompressed)
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Options for revoking a credential
|
|
35
|
-
*/
|
|
36
|
-
export type RevokeCredentialOptions = {
|
|
37
|
-
credentialId: string;
|
|
38
|
-
statusListRecordId: string;
|
|
39
|
-
statusListIndex: number;
|
|
40
|
-
signOptions: SignOptions;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Options for checking credential status
|
|
45
|
-
*/
|
|
46
|
-
export type CheckStatusOptions = {
|
|
47
|
-
statusListCredentialId: string;
|
|
48
|
-
statusListIndex: number;
|
|
49
|
-
statusListRecordId?: string; // Optional: if status list is in DWN
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Status List 2021 implementation for credential revocation
|
|
54
|
-
* Based on: https://w3c.github.io/vc-status-list-2021/
|
|
55
|
-
*
|
|
56
|
-
* @beta
|
|
57
|
-
*/
|
|
58
|
-
export class StatusListManager {
|
|
59
|
-
private agent: IDAgent;
|
|
60
|
-
private connectedDid: string;
|
|
61
|
-
private dwnApi: DwnApi;
|
|
62
|
-
|
|
63
|
-
constructor(options: { agent: IDAgent, connectedDid: string, dwnApi: DwnApi }) {
|
|
64
|
-
this.agent = options.agent;
|
|
65
|
-
this.connectedDid = options.connectedDid;
|
|
66
|
-
this.dwnApi = options.dwnApi;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Create a Status List Credential for tracking revocation/suspension status
|
|
71
|
-
*
|
|
72
|
-
* @param options - Options for creating the status list
|
|
73
|
-
* @returns Status list credential and DWN record
|
|
74
|
-
*/
|
|
75
|
-
async createStatusList(options: CreateStatusListOptions): Promise<{
|
|
76
|
-
statusListCredential: VerifiableCredential;
|
|
77
|
-
statusListJwt: string;
|
|
78
|
-
record: Record;
|
|
79
|
-
}> {
|
|
80
|
-
const { issuer, statusPurpose, signOptions, size = 131072 } = options;
|
|
81
|
-
|
|
82
|
-
// Create empty bitstring (all zeros = no credentials revoked)
|
|
83
|
-
const bitstring = new Uint8Array(Math.ceil(size / 8));
|
|
84
|
-
bitstring.fill(0);
|
|
85
|
-
|
|
86
|
-
// Compress bitstring with gzip
|
|
87
|
-
const compressed = pako.gzip(bitstring);
|
|
88
|
-
|
|
89
|
-
// Base64url encode the compressed bitstring
|
|
90
|
-
const encodedList = Convert.uint8Array(compressed).toBase64Url();
|
|
91
|
-
|
|
92
|
-
// Create status list credential subject
|
|
93
|
-
const statusListId = `urn:uuid:${uuidv4()}`;
|
|
94
|
-
const credentialSubject = {
|
|
95
|
-
id: `${statusListId}#list`,
|
|
96
|
-
type: 'StatusList2021',
|
|
97
|
-
statusPurpose: statusPurpose,
|
|
98
|
-
encodedList: encodedList
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
// Create the status list credential
|
|
102
|
-
// Note: The subject for a status list credential is the list itself
|
|
103
|
-
// The subject parameter will be overridden by the id in credentialSubject data
|
|
104
|
-
const statusListCredential = VC.create({
|
|
105
|
-
issuer: issuer,
|
|
106
|
-
subject: statusListId, // This will be overridden by id in credentialSubject
|
|
107
|
-
data: credentialSubject,
|
|
108
|
-
type: 'StatusList2021Credential'
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Add Status List context
|
|
112
|
-
statusListCredential.vcDataModel['@context'] = [
|
|
113
|
-
'https://www.w3.org/2018/credentials/v1',
|
|
114
|
-
STATUS_LIST_CONTEXT
|
|
115
|
-
];
|
|
116
|
-
|
|
117
|
-
// Update type to include StatusList2021Credential
|
|
118
|
-
statusListCredential.vcDataModel.type = [
|
|
119
|
-
'VerifiableCredential',
|
|
120
|
-
'StatusList2021Credential'
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
// Set the ID
|
|
124
|
-
statusListCredential.vcDataModel.id = statusListId;
|
|
125
|
-
|
|
126
|
-
// Sign the status list credential
|
|
127
|
-
const statusListJwt = await statusListCredential.sign(signOptions);
|
|
128
|
-
|
|
129
|
-
// Store in DWN
|
|
130
|
-
const { record } = await this.dwnApi.records.create({
|
|
131
|
-
data: statusListJwt,
|
|
132
|
-
message: {
|
|
133
|
-
schema: STATUS_LIST_SCHEMA,
|
|
134
|
-
dataFormat: STATUS_LIST_DATA_FORMAT,
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
statusListCredential,
|
|
140
|
-
statusListJwt,
|
|
141
|
-
record
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Add credentialStatus to a credential, linking it to a status list
|
|
147
|
-
*
|
|
148
|
-
* @param vc - The verifiable credential to add status to
|
|
149
|
-
* @param statusListCredentialId - The ID of the status list credential
|
|
150
|
-
* @param statusListIndex - The index in the status list for this credential
|
|
151
|
-
* @param statusPurpose - The purpose (revocation or suspension)
|
|
152
|
-
* @returns The credential with credentialStatus added
|
|
153
|
-
*/
|
|
154
|
-
addCredentialStatus(
|
|
155
|
-
vc: VerifiableCredential,
|
|
156
|
-
statusListCredentialId: string,
|
|
157
|
-
statusListIndex: number,
|
|
158
|
-
statusPurpose: StatusPurpose = 'revocation'
|
|
159
|
-
): VerifiableCredential {
|
|
160
|
-
const credentialStatus = {
|
|
161
|
-
id: `${statusListCredentialId}#${statusListIndex}`,
|
|
162
|
-
type: 'StatusList2021Entry',
|
|
163
|
-
statusPurpose: statusPurpose,
|
|
164
|
-
statusListIndex: statusListIndex.toString(),
|
|
165
|
-
statusListCredential: statusListCredentialId
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
// Add credentialStatus to the VC
|
|
169
|
-
vc.vcDataModel.credentialStatus = credentialStatus;
|
|
170
|
-
|
|
171
|
-
// Add Status List context if not already present
|
|
172
|
-
const contexts = Array.isArray(vc.vcDataModel['@context'])
|
|
173
|
-
? vc.vcDataModel['@context']
|
|
174
|
-
: [vc.vcDataModel['@context']];
|
|
175
|
-
|
|
176
|
-
if (!contexts.includes(STATUS_LIST_CONTEXT)) {
|
|
177
|
-
vc.vcDataModel['@context'] = [...contexts, STATUS_LIST_CONTEXT];
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return vc;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Revoke a credential by updating the status list bitstring
|
|
185
|
-
*
|
|
186
|
-
* @param options - Options for revoking the credential
|
|
187
|
-
* @returns Updated status list credential and record
|
|
188
|
-
*/
|
|
189
|
-
async revokeCredential(options: RevokeCredentialOptions): Promise<{
|
|
190
|
-
statusListCredential: VerifiableCredential;
|
|
191
|
-
statusListJwt: string;
|
|
192
|
-
record: Record;
|
|
193
|
-
}> {
|
|
194
|
-
return this.updateCredentialStatus({
|
|
195
|
-
...options,
|
|
196
|
-
revoked: true
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Suspend a credential by updating the status list bitstring
|
|
202
|
-
*
|
|
203
|
-
* @param options - Options for suspending the credential
|
|
204
|
-
* @returns Updated status list credential and record
|
|
205
|
-
*/
|
|
206
|
-
async suspendCredential(options: RevokeCredentialOptions): Promise<{
|
|
207
|
-
statusListCredential: VerifiableCredential;
|
|
208
|
-
statusListJwt: string;
|
|
209
|
-
record: Record;
|
|
210
|
-
}> {
|
|
211
|
-
return this.updateCredentialStatus({
|
|
212
|
-
...options,
|
|
213
|
-
revoked: true // Suspension also sets the bit to 1
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Check if a credential is revoked or suspended
|
|
219
|
-
*
|
|
220
|
-
* @param options - Options for checking status
|
|
221
|
-
* @returns Status information
|
|
222
|
-
*/
|
|
223
|
-
async checkStatus(options: CheckStatusOptions): Promise<{
|
|
224
|
-
revoked: boolean;
|
|
225
|
-
suspended: boolean;
|
|
226
|
-
}> {
|
|
227
|
-
const { statusListCredentialId, statusListIndex, statusListRecordId } = options;
|
|
228
|
-
|
|
229
|
-
let statusListJwt: string;
|
|
230
|
-
|
|
231
|
-
// Resolve status list credential
|
|
232
|
-
if (statusListRecordId) {
|
|
233
|
-
// Read from DWN
|
|
234
|
-
const { record } = await this.dwnApi.records.read({
|
|
235
|
-
message: {
|
|
236
|
-
filter: {
|
|
237
|
-
recordId: statusListRecordId
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
statusListJwt = await record.data.text();
|
|
243
|
-
} else {
|
|
244
|
-
// Try to resolve from URL (external status list)
|
|
245
|
-
// For now, we'll require statusListRecordId for SDK-native status lists
|
|
246
|
-
throw new Error('statusListRecordId is required for DWN-based status lists');
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Parse the status list credential
|
|
250
|
-
const statusListVc = VC.parseJwt(statusListJwt);
|
|
251
|
-
const credentialSubject = statusListVc.vcDataModel.credentialSubject as any;
|
|
252
|
-
|
|
253
|
-
if (!credentialSubject || !credentialSubject.encodedList) {
|
|
254
|
-
throw new Error('Invalid status list credential: missing encodedList');
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Decode and decompress the bitstring
|
|
258
|
-
const encodedList = credentialSubject.encodedList;
|
|
259
|
-
const compressed = Convert.base64Url(encodedList).toUint8Array();
|
|
260
|
-
const bitstring = pako.ungzip(compressed);
|
|
261
|
-
|
|
262
|
-
// Check the bit at the specified index
|
|
263
|
-
const byteIndex = Math.floor(statusListIndex / 8);
|
|
264
|
-
const bitIndex = statusListIndex % 8;
|
|
265
|
-
|
|
266
|
-
if (byteIndex >= bitstring.length) {
|
|
267
|
-
throw new Error(`Status list index ${statusListIndex} is out of bounds`);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const byte = bitstring[byteIndex];
|
|
271
|
-
const bit = (byte >> bitIndex) & 1;
|
|
272
|
-
const isRevoked = bit === 1;
|
|
273
|
-
|
|
274
|
-
// Determine if it's revocation or suspension based on statusPurpose
|
|
275
|
-
const statusPurpose = credentialSubject.statusPurpose as StatusPurpose;
|
|
276
|
-
const revoked = isRevoked && statusPurpose === 'revocation';
|
|
277
|
-
const suspended = isRevoked && statusPurpose === 'suspension';
|
|
278
|
-
|
|
279
|
-
return { revoked, suspended };
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Private method to update credential status in a status list
|
|
284
|
-
*/
|
|
285
|
-
private async updateCredentialStatus(options: RevokeCredentialOptions & { revoked: boolean }): Promise<{
|
|
286
|
-
statusListCredential: VerifiableCredential;
|
|
287
|
-
statusListJwt: string;
|
|
288
|
-
record: Record;
|
|
289
|
-
}> {
|
|
290
|
-
const { statusListRecordId, statusListIndex, signOptions, revoked } = options;
|
|
291
|
-
|
|
292
|
-
// Read the existing status list record
|
|
293
|
-
const { record } = await this.dwnApi.records.read({
|
|
294
|
-
message: {
|
|
295
|
-
filter: {
|
|
296
|
-
recordId: statusListRecordId
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
const statusListJwt = await record.data.text();
|
|
302
|
-
const statusListVc = VC.parseJwt(statusListJwt);
|
|
303
|
-
|
|
304
|
-
// Get the credential subject
|
|
305
|
-
const credentialSubject = statusListVc.vcDataModel.credentialSubject as any;
|
|
306
|
-
if (!credentialSubject || !credentialSubject.encodedList) {
|
|
307
|
-
throw new Error('Invalid status list credential: missing encodedList');
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Decode and decompress the bitstring
|
|
311
|
-
const encodedList = credentialSubject.encodedList;
|
|
312
|
-
const compressed = Convert.base64Url(encodedList).toUint8Array();
|
|
313
|
-
const bitstring = pako.ungzip(compressed);
|
|
314
|
-
|
|
315
|
-
// Update the bit at the specified index
|
|
316
|
-
const byteIndex = Math.floor(statusListIndex / 8);
|
|
317
|
-
const bitIndex = statusListIndex % 8;
|
|
318
|
-
|
|
319
|
-
if (byteIndex >= bitstring.length) {
|
|
320
|
-
throw new Error(`Status list index ${statusListIndex} is out of bounds`);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Set or clear the bit
|
|
324
|
-
if (revoked) {
|
|
325
|
-
bitstring[byteIndex] |= (1 << bitIndex); // Set bit to 1
|
|
326
|
-
} else {
|
|
327
|
-
bitstring[byteIndex] &= ~(1 << bitIndex); // Clear bit to 0
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Re-compress and encode
|
|
331
|
-
const newCompressed = pako.gzip(bitstring);
|
|
332
|
-
const newEncodedList = Convert.uint8Array(newCompressed).toBase64Url();
|
|
333
|
-
|
|
334
|
-
// Update the credential subject
|
|
335
|
-
credentialSubject.encodedList = newEncodedList;
|
|
336
|
-
|
|
337
|
-
// Create updated status list credential
|
|
338
|
-
const updatedStatusListVc = VC.create({
|
|
339
|
-
issuer: statusListVc.issuer,
|
|
340
|
-
subject: statusListVc.vcDataModel.id || `urn:uuid:${uuidv4()}`,
|
|
341
|
-
data: credentialSubject,
|
|
342
|
-
type: 'StatusList2021Credential'
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
// Preserve context and type
|
|
346
|
-
updatedStatusListVc.vcDataModel['@context'] = statusListVc.vcDataModel['@context'];
|
|
347
|
-
updatedStatusListVc.vcDataModel.type = statusListVc.vcDataModel.type;
|
|
348
|
-
updatedStatusListVc.vcDataModel.id = statusListVc.vcDataModel.id;
|
|
349
|
-
|
|
350
|
-
// Sign the updated credential
|
|
351
|
-
const updatedStatusListJwt = await updatedStatusListVc.sign(signOptions);
|
|
352
|
-
|
|
353
|
-
// Update the DWN record
|
|
354
|
-
await record.update({
|
|
355
|
-
data: updatedStatusListJwt
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
return {
|
|
359
|
-
statusListCredential: updatedStatusListVc,
|
|
360
|
-
statusListJwt: updatedStatusListJwt,
|
|
361
|
-
record
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
package/src/credentials/utils.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Retrieves the current timestamp in XML Schema 1.1.2 date-time format.
|
|
3
|
-
*
|
|
4
|
-
* This function omits the milliseconds part from the ISO 8601 timestamp, returning a date-time
|
|
5
|
-
* string in the format "yyyy-MM-ddTHH:mm:ssZ".
|
|
6
|
-
*
|
|
7
|
-
* @returns The current timestamp in XML Schema 1.1.2 format.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* const currentTimestamp = getCurrentXmlSchema112Timestamp(); // "2023-08-23T12:34:56Z"
|
|
11
|
-
*/
|
|
12
|
-
export function getCurrentXmlSchema112Timestamp(): string {
|
|
13
|
-
// Omit the milliseconds part from toISOString() output
|
|
14
|
-
return new Date().toISOString().replace(/\.\d+Z$/, 'Z');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Calculates a future timestamp in XML Schema 1.1.2 date-time format based on a given number of
|
|
19
|
-
* seconds.
|
|
20
|
-
*
|
|
21
|
-
* This function takes a number of seconds and adds it to the current timestamp, returning a
|
|
22
|
-
* date-time string in the format "yyyy-MM-ddTHH:mm:ssZ" without milliseconds.
|
|
23
|
-
*
|
|
24
|
-
* @param secondsInFuture - The number of seconds to project into the future.
|
|
25
|
-
* @returns The future timestamp in XML Schema 1.1.2 format.
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* const futureTimestamp = getFutureXmlSchema112Timestamp(60); // "2023-08-23T12:35:56Z"
|
|
29
|
-
*/
|
|
30
|
-
export function getFutureXmlSchema112Timestamp(secondsInFuture: number): string {
|
|
31
|
-
const futureDate = new Date(Date.now() + secondsInFuture * 1000);
|
|
32
|
-
return futureDate.toISOString().replace(/\.\d+Z$/, 'Z');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Validates a timestamp string against the XML Schema 1.1.2 date-time format.
|
|
37
|
-
*
|
|
38
|
-
* This function checks whether the provided timestamp string conforms to the
|
|
39
|
-
* format "yyyy-MM-ddTHH:mm:ssZ", without milliseconds, as defined in XML Schema 1.1.2.
|
|
40
|
-
*
|
|
41
|
-
* @param timestamp - The timestamp string to validate.
|
|
42
|
-
* @returns `true` if the timestamp is valid, `false` otherwise.
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* const isValid = isValidXmlSchema112Timestamp('2023-08-23T12:34:56Z'); // true
|
|
46
|
-
*/
|
|
47
|
-
export function isValidXmlSchema112Timestamp(timestamp: string): boolean {
|
|
48
|
-
// Format: yyyy-MM-ddTHH:mm:ssZ
|
|
49
|
-
const regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
|
|
50
|
-
if (!regex.test(timestamp)) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const date = new Date(timestamp);
|
|
55
|
-
|
|
56
|
-
return !isNaN(date.getTime());
|
|
57
|
-
}
|
|
58
|
-
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_CONTEXT,
|
|
3
|
-
DEFAULT_VC_TYPE,
|
|
4
|
-
VerifiableCredential
|
|
5
|
-
} from './credential.js';
|
|
6
|
-
|
|
7
|
-
import { isValidXmlSchema112Timestamp } from './utils.js';
|
|
8
|
-
|
|
9
|
-
import type {
|
|
10
|
-
ICredentialContextType,
|
|
11
|
-
ICredentialSubject
|
|
12
|
-
} from '@sphereon/ssi-types';
|
|
13
|
-
|
|
14
|
-
export class VcValidator {
|
|
15
|
-
static validateCredentialPayload(vc: VerifiableCredential): void {
|
|
16
|
-
this.validateContext(vc.vcDataModel['@context']);
|
|
17
|
-
this.validateVcType(vc.type);
|
|
18
|
-
this.validateCredentialSubject(vc.vcDataModel.credentialSubject);
|
|
19
|
-
if (vc.vcDataModel.issuanceDate) this.validateTimestamp(vc.vcDataModel.issuanceDate);
|
|
20
|
-
if (vc.vcDataModel.expirationDate) this.validateTimestamp(vc.vcDataModel.expirationDate);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
static validateContext(value: ICredentialContextType | ICredentialContextType[]): void {
|
|
24
|
-
const input = this.asArray(value);
|
|
25
|
-
if (input.length < 1 || input.indexOf(DEFAULT_CONTEXT) === -1) {
|
|
26
|
-
throw new Error(`@context is missing default context "${DEFAULT_CONTEXT}"`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
static validateVcType(value: string | string[]): void {
|
|
31
|
-
const input = this.asArray(value);
|
|
32
|
-
if (input.length < 1 || input.indexOf(DEFAULT_VC_TYPE) === -1) {
|
|
33
|
-
throw new Error(`type is missing default "${DEFAULT_VC_TYPE}"`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static validateCredentialSubject(value: ICredentialSubject | ICredentialSubject[]): void {
|
|
38
|
-
if (Object.keys(value).length === 0) {
|
|
39
|
-
throw new Error(`credentialSubject must not be empty`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static validateTimestamp(timestamp: string) {
|
|
44
|
-
if(!isValidXmlSchema112Timestamp(timestamp)){
|
|
45
|
-
throw new Error(`timestamp is not valid xml schema 112 timestamp`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static asArray(arg: any | any[]): any[] {
|
|
50
|
-
return Array.isArray(arg) ? arg : [arg];
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { universalTypeOf } from '../../../common/index.js';
|
|
2
|
-
|
|
3
|
-
import type { IDCrypto } from '../../types/iddwn-crypto.js';
|
|
4
|
-
|
|
5
|
-
import { checkRequiredProperty } from '../../utils.js';
|
|
6
|
-
import { CryptoAlgorithm } from '../crypto-algorithm.js';
|
|
7
|
-
import { InvalidAccessError, OperationError } from '../errors.js';
|
|
8
|
-
|
|
9
|
-
export abstract class BaseAesAlgorithm extends CryptoAlgorithm {
|
|
10
|
-
|
|
11
|
-
public checkGenerateKey(options: {
|
|
12
|
-
algorithm: IDCrypto.AesGenerateKeyOptions,
|
|
13
|
-
keyUsages: IDCrypto.KeyUsage[]
|
|
14
|
-
}): void {
|
|
15
|
-
const { algorithm, keyUsages } = options;
|
|
16
|
-
// Algorithm specified in the operation must match the algorithm implementation processing the operation.
|
|
17
|
-
this.checkAlgorithmName({ algorithmName: algorithm.name });
|
|
18
|
-
// The algorithm object must contain a length property.
|
|
19
|
-
checkRequiredProperty({ property: 'length', inObject: algorithm });
|
|
20
|
-
// The length specified must be a number.
|
|
21
|
-
if (universalTypeOf(algorithm.length) !== 'Number') {
|
|
22
|
-
throw new TypeError(`Algorithm 'length' is not of type: Number.`);
|
|
23
|
-
}
|
|
24
|
-
// The length specified must be one of the allowed bit lengths for AES.
|
|
25
|
-
if (![128, 192, 256].includes(algorithm.length)) {
|
|
26
|
-
throw new OperationError(`Algorithm 'length' must be 128, 192, or 256.`);
|
|
27
|
-
}
|
|
28
|
-
// The key usages specified must be permitted by the algorithm implementation processing the operation.
|
|
29
|
-
this.checkKeyUsages({ keyUsages, allowedKeyUsages: this.keyUsages });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public abstract generateKey(options: {
|
|
33
|
-
algorithm: IDCrypto.AesGenerateKeyOptions,
|
|
34
|
-
extractable: boolean,
|
|
35
|
-
keyUsages: IDCrypto.KeyUsage[]
|
|
36
|
-
}): Promise<IDCrypto.CryptoKey>;
|
|
37
|
-
|
|
38
|
-
public override async deriveBits(): Promise<Uint8Array> {
|
|
39
|
-
throw new InvalidAccessError(`Requested operation 'deriveBits' is not valid for ${this.name} keys.`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public override async sign(): Promise<Uint8Array> {
|
|
43
|
-
throw new InvalidAccessError(`Requested operation 'sign' is not valid for ${this.name} keys.`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
public override async verify(): Promise<boolean> {
|
|
47
|
-
throw new InvalidAccessError(`Requested operation 'verify' is not valid for ${this.name} keys.`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { universalTypeOf } from '../../../common/index.js';
|
|
2
|
-
|
|
3
|
-
import type { IDCrypto } from '../../types/iddwn-crypto.js';
|
|
4
|
-
|
|
5
|
-
import { BaseAesAlgorithm } from './base.js';
|
|
6
|
-
import { OperationError } from '../errors.js';
|
|
7
|
-
import { checkRequiredProperty } from '../../utils.js';
|
|
8
|
-
|
|
9
|
-
export abstract class BaseAesCtrAlgorithm extends BaseAesAlgorithm {
|
|
10
|
-
|
|
11
|
-
public readonly name = 'AES-CTR';
|
|
12
|
-
|
|
13
|
-
public readonly keyUsages: IDCrypto.KeyUsage[] = ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'];
|
|
14
|
-
|
|
15
|
-
public checkAlgorithmOptions(options: {
|
|
16
|
-
algorithm: IDCrypto.AesCtrOptions,
|
|
17
|
-
key: IDCrypto.CryptoKey
|
|
18
|
-
}): void {
|
|
19
|
-
const { algorithm, key } = options;
|
|
20
|
-
// Algorithm specified in the operation must match the algorithm implementation processing the operation.
|
|
21
|
-
this.checkAlgorithmName({ algorithmName: algorithm.name });
|
|
22
|
-
// The algorithm object must contain a counter property.
|
|
23
|
-
checkRequiredProperty({ property: 'counter', inObject: algorithm });
|
|
24
|
-
// The counter must a Uint8Array.
|
|
25
|
-
if (!(universalTypeOf(algorithm.counter) === 'Uint8Array')) {
|
|
26
|
-
throw new TypeError(`Algorithm 'counter' is not of type: Uint8Array.`);
|
|
27
|
-
}
|
|
28
|
-
// The initial value of the counter block must be 16 bytes long (the AES block size).
|
|
29
|
-
if (algorithm.counter.byteLength !== 16) {
|
|
30
|
-
throw new OperationError(`Algorithm 'counter' must have length: 16 bytes.`);
|
|
31
|
-
}
|
|
32
|
-
// The algorithm object must contain a length property.
|
|
33
|
-
checkRequiredProperty({ property: 'length', inObject: algorithm });
|
|
34
|
-
// The length specified must be a number.
|
|
35
|
-
if (universalTypeOf(algorithm.length) !== 'Number') {
|
|
36
|
-
throw new TypeError(`Algorithm 'length' is not of type: Number.`);
|
|
37
|
-
}
|
|
38
|
-
// The length specified must be between 1 and 128.
|
|
39
|
-
if ((algorithm.length < 1 || algorithm.length > 128)) {
|
|
40
|
-
throw new OperationError(`Algorithm 'length' should be in the range: 1 to 128.`);
|
|
41
|
-
}
|
|
42
|
-
// The options object must contain a key property.
|
|
43
|
-
checkRequiredProperty({ property: 'key', inObject: options });
|
|
44
|
-
// The key object must be a CryptoKey.
|
|
45
|
-
this.checkCryptoKey({ key });
|
|
46
|
-
// The key algorithm must match the algorithm implementation processing the operation.
|
|
47
|
-
this.checkKeyAlgorithm({ keyAlgorithmName: key.algorithm.name });
|
|
48
|
-
// The CryptoKey object must be a secret key.
|
|
49
|
-
this.checkKeyType({ keyType: key.type, allowedKeyType: 'secret' });
|
|
50
|
-
}
|
|
51
|
-
}
|