-
Notifications
You must be signed in to change notification settings - Fork 13
/
index.spec.ts
149 lines (135 loc) · 4.29 KB
/
index.spec.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import { digest, generateSalt } from '@sd-jwt/crypto-nodejs';
import type {
DisclosureFrame,
Signer,
Verifier,
JwtPayload,
} from '@sd-jwt/types';
import { describe, test, expect } from 'vitest';
import { SDJwtVcInstance } from '..';
import type { SdJwtVcPayload } from '../sd-jwt-vc-payload';
import Crypto from 'node:crypto';
import {
StatusList,
type StatusListJWTHeaderParameters,
createHeaderAndPayload,
} from '@sd-jwt/jwt-status-list';
import { SignJWT } from 'jose';
const iss = 'ExampleIssuer';
const vct = 'ExampleCredentialType';
const iat = new Date().getTime() / 1000;
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
//TODO: to simulate a hosted status list, use the same appraoch as in vct.spec.ts
const createSignerVerifier = () => {
const signer: Signer = async (data: string) => {
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
return Buffer.from(sig).toString('base64url');
};
const verifier: Verifier = async (data: string, sig: string) => {
return Crypto.verify(
null,
Buffer.from(data),
publicKey,
Buffer.from(sig, 'base64url'),
);
};
return { signer, verifier };
};
const generateStatusList = async (): Promise<string> => {
const statusList = new StatusList([0, 1, 0, 0, 0, 0, 1, 1], 1);
const payload: JwtPayload = {
iss: 'https://example.com',
sub: 'https://example.com/status/1',
iat: new Date().getTime() / 1000,
};
const header: StatusListJWTHeaderParameters = {
alg: 'EdDSA',
typ: 'statuslist+jwt',
};
const values = createHeaderAndPayload(statusList, payload, header);
return new SignJWT(values.payload)
.setProtectedHeader(values.header)
.sign(privateKey);
};
const statusListJWT = await generateStatusList();
describe('App', () => {
test('Example', async () => {
const { signer, verifier } = createSignerVerifier();
const sdjwt = new SDJwtVcInstance({
signer,
signAlg: 'EdDSA',
verifier,
hasher: digest,
hashAlg: 'SHA-256',
saltGenerator: generateSalt,
});
const claims = {
firstname: 'John',
};
const disclosureFrame = {
_sd: ['firstname', 'iss'],
};
const expectedPayload: SdJwtVcPayload = { iat, iss, vct, ...claims };
const encodedSdjwt = sdjwt.issue(
expectedPayload,
disclosureFrame as unknown as DisclosureFrame<SdJwtVcPayload>,
);
expect(encodedSdjwt).rejects.toThrowError();
});
});
describe('Revocation', () => {
const { signer, verifier } = createSignerVerifier();
const sdjwt = new SDJwtVcInstance({
signer,
signAlg: 'EdDSA',
verifier,
hasher: digest,
hashAlg: 'SHA-256',
saltGenerator: generateSalt,
statusListFetcher(uri: string) {
// we emulate fetching the status list from the uri. Validation of the JWT is not done here in the test but should be done in the implementation.
return Promise.resolve(statusListJWT);
},
// statusValidator(status: number) {
// // we are only accepting status 0
// if (status === 0) return Promise.resolve();
// throw new Error('Status is not valid');
// },
});
test('Test with a non revcoked credential', async () => {
const claims = {
firstname: 'John',
status: {
status_list: {
uri: 'https://example.com/status-list',
idx: 0,
},
},
};
const expectedPayload: SdJwtVcPayload = { iat, iss, vct, ...claims };
const encodedSdjwt = await sdjwt.issue(expectedPayload);
const result = await sdjwt.verify(encodedSdjwt);
expect(result).toBeDefined();
});
test('Test with a revoked credential', async () => {
const claims = {
firstname: 'John',
status: {
status_list: {
uri: 'https://example.com/status-list',
idx: 1,
},
},
};
const expectedPayload: SdJwtVcPayload = { iat, iss, vct, ...claims };
const encodedSdjwt = await sdjwt.issue(expectedPayload);
const result = sdjwt.verify(encodedSdjwt);
expect(result).rejects.toThrowError('Status is not valid');
});
test('test to fetch the statuslist', async () => {
//TODO: not implemented yet since we need to either mock the fetcher or use a real fetcher
});
test('test with an expired status list', async () => {
//TODO: needs to be implemented
});
});