@sd-jwt/core 0.3.2-next.76 → 0.3.2-next.95
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/README.md +2 -38
- package/dist/index.d.mts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +12 -1
- package/dist/index.mjs +13 -3
- package/package.json +8 -9
- package/src/index.ts +23 -4
- package/src/test/index.spec.ts +136 -13
- package/test/app-e2e.spec.ts +7 -7
package/README.md
CHANGED
|
@@ -32,44 +32,8 @@ Ensure you have Node.js installed as a prerequisite.
|
|
|
32
32
|
|
|
33
33
|
### Usage
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```jsx
|
|
38
|
-
import { DisclosureFrame } from '@sd-jwt/core';
|
|
39
|
-
|
|
40
|
-
// Issuer defines the claims object with the user's information
|
|
41
|
-
const claims = {
|
|
42
|
-
firstname: 'John',
|
|
43
|
-
lastname: 'Doe',
|
|
44
|
-
ssn: '123-45-6789',
|
|
45
|
-
id: '1234',
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// Issuer defines the disclosure frame to specify which claims can be disclosed/undisclosed
|
|
49
|
-
const disclosureFrame: DisclosureFrame<typeof claims> = {
|
|
50
|
-
_sd: ['firstname', 'lastname', 'ssn'],
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// Issuer issues a signed JWT credential with the specified claims and disclosure frame
|
|
54
|
-
// returns an encoded JWT
|
|
55
|
-
const credential = await sdjwt.issue(claims, disclosureFrame);
|
|
56
|
-
|
|
57
|
-
// Holder may validate the credential from the issuer
|
|
58
|
-
const valid = await sdjwt.validate(credential);
|
|
59
|
-
|
|
60
|
-
// Holder defines the presentation frame to specify which claims should be presented
|
|
61
|
-
// The list of presented claims must be a subset of the disclosed claims
|
|
62
|
-
const presentationFrame = ['firstname', 'ssn'];
|
|
63
|
-
|
|
64
|
-
// Holder creates a presentation using the issued credential and the presentation frame
|
|
65
|
-
// returns an encoded SD JWT.
|
|
66
|
-
const presentation = await sdjwt.present(credential, presentationFrame);
|
|
67
|
-
|
|
68
|
-
// Verifier can verify the presentation using the Issuer's public key
|
|
69
|
-
const verified = await sdjwt.verify(presentation);
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Check out more details in our [documentation](https://github.com/openwallet-foundation-labs/sd-jwt-js/tree/next/docs) or [examples](https://github.com/openwallet-foundation-labs/sd-jwt-js/tree/next/examples)
|
|
35
|
+
The library can be used to create sd-jwt based credentials. To be compliant with the `sd-jwt-vc` standard, you can use the `@sd-jwt/sd-jwt-vc` that is implementing this spec.
|
|
36
|
+
If you want to use the pure sd-jwt class or implement your own sd-jwt credential approach, you can use this library.
|
|
73
37
|
|
|
74
38
|
### Dependencies
|
|
75
39
|
|
package/dist/index.d.mts
CHANGED
|
@@ -66,16 +66,24 @@ declare const pack: <T extends Record<string, unknown>>(claims: T, disclosureFra
|
|
|
66
66
|
|
|
67
67
|
declare const createDecoy: (hash: HasherAndAlg, saltGenerator: SaltGenerator) => Promise<string>;
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
type SdJwtPayload = Record<string, unknown>;
|
|
70
|
+
declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
71
|
+
protected type?: string;
|
|
70
72
|
static DEFAULT_hashAlg: string;
|
|
71
73
|
private userConfig;
|
|
72
74
|
constructor(userConfig?: SDJWTConfig);
|
|
73
75
|
private createKBJwt;
|
|
74
76
|
private SignJwt;
|
|
75
77
|
private VerifyJwt;
|
|
76
|
-
issue<Payload extends
|
|
78
|
+
issue<Payload extends ExtendedPayload>(payload: Payload, disclosureFrame?: DisclosureFrame<Payload>, options?: {
|
|
77
79
|
header?: object;
|
|
78
80
|
}): Promise<SDJWTCompact>;
|
|
81
|
+
/**
|
|
82
|
+
* Validates if the disclosureFrame contains any reserved fields. If so it will throw an error.
|
|
83
|
+
* @param disclosureFrame
|
|
84
|
+
* @returns
|
|
85
|
+
*/
|
|
86
|
+
protected validateReservedFields<T extends ExtendedPayload>(disclosureFrame: DisclosureFrame<T>): void;
|
|
79
87
|
present(encodedSDJwt: string, presentationKeys?: string[], options?: {
|
|
80
88
|
kb?: KBOptions;
|
|
81
89
|
}): Promise<SDJWTCompact>;
|
|
@@ -104,4 +112,4 @@ declare class SDJwtInstance {
|
|
|
104
112
|
getClaims(endcodedSDJwt: SDJWTCompact): Promise<unknown>;
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
export { Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtInstance, createDecoy, listKeys, pack };
|
|
115
|
+
export { Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtInstance, type SdJwtPayload, createDecoy, listKeys, pack };
|
package/dist/index.d.ts
CHANGED
|
@@ -66,16 +66,24 @@ declare const pack: <T extends Record<string, unknown>>(claims: T, disclosureFra
|
|
|
66
66
|
|
|
67
67
|
declare const createDecoy: (hash: HasherAndAlg, saltGenerator: SaltGenerator) => Promise<string>;
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
type SdJwtPayload = Record<string, unknown>;
|
|
70
|
+
declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
71
|
+
protected type?: string;
|
|
70
72
|
static DEFAULT_hashAlg: string;
|
|
71
73
|
private userConfig;
|
|
72
74
|
constructor(userConfig?: SDJWTConfig);
|
|
73
75
|
private createKBJwt;
|
|
74
76
|
private SignJwt;
|
|
75
77
|
private VerifyJwt;
|
|
76
|
-
issue<Payload extends
|
|
78
|
+
issue<Payload extends ExtendedPayload>(payload: Payload, disclosureFrame?: DisclosureFrame<Payload>, options?: {
|
|
77
79
|
header?: object;
|
|
78
80
|
}): Promise<SDJWTCompact>;
|
|
81
|
+
/**
|
|
82
|
+
* Validates if the disclosureFrame contains any reserved fields. If so it will throw an error.
|
|
83
|
+
* @param disclosureFrame
|
|
84
|
+
* @returns
|
|
85
|
+
*/
|
|
86
|
+
protected validateReservedFields<T extends ExtendedPayload>(disclosureFrame: DisclosureFrame<T>): void;
|
|
79
87
|
present(encodedSDJwt: string, presentationKeys?: string[], options?: {
|
|
80
88
|
kb?: KBOptions;
|
|
81
89
|
}): Promise<SDJWTCompact>;
|
|
@@ -104,4 +112,4 @@ declare class SDJwtInstance {
|
|
|
104
112
|
getClaims(endcodedSDJwt: SDJWTCompact): Promise<unknown>;
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
export { Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtInstance, createDecoy, listKeys, pack };
|
|
115
|
+
export { Jwt, type JwtData, KBJwt, SDJwt, type SDJwtData, SDJwtInstance, type SdJwtPayload, createDecoy, listKeys, pack };
|
package/dist/index.js
CHANGED
|
@@ -460,6 +460,9 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
460
460
|
if (!this.userConfig.signAlg) {
|
|
461
461
|
throw new import_utils5.SDJWTException("sign alogrithm not specified");
|
|
462
462
|
}
|
|
463
|
+
if (disclosureFrame) {
|
|
464
|
+
this.validateReservedFields(disclosureFrame);
|
|
465
|
+
}
|
|
463
466
|
const hasher = this.userConfig.hasher;
|
|
464
467
|
const hashAlg = (_a = this.userConfig.hashAlg) != null ? _a : _SDJwtInstance.DEFAULT_hashAlg;
|
|
465
468
|
const { packedClaims, disclosures } = yield pack(
|
|
@@ -470,7 +473,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
470
473
|
);
|
|
471
474
|
const alg = this.userConfig.signAlg;
|
|
472
475
|
const OptionHeader = (_b = options == null ? void 0 : options.header) != null ? _b : {};
|
|
473
|
-
const CustomHeader = this.userConfig.omitTyp ? OptionHeader : __spreadValues({ typ:
|
|
476
|
+
const CustomHeader = this.userConfig.omitTyp ? OptionHeader : __spreadValues({ typ: this.type }, OptionHeader);
|
|
474
477
|
const header = __spreadProps(__spreadValues({}, CustomHeader), { alg });
|
|
475
478
|
const jwt = new Jwt({
|
|
476
479
|
header,
|
|
@@ -486,6 +489,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
486
489
|
return sdJwt.encodeSDJwt();
|
|
487
490
|
});
|
|
488
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* Validates if the disclosureFrame contains any reserved fields. If so it will throw an error.
|
|
494
|
+
* @param disclosureFrame
|
|
495
|
+
* @returns
|
|
496
|
+
*/
|
|
497
|
+
validateReservedFields(disclosureFrame) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
489
500
|
present(encodedSDJwt, presentationKeys, options) {
|
|
490
501
|
return __async(this, null, function* () {
|
|
491
502
|
var _a;
|
package/dist/index.mjs
CHANGED
|
@@ -381,8 +381,7 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
|
|
|
381
381
|
|
|
382
382
|
// src/index.ts
|
|
383
383
|
import {
|
|
384
|
-
KB_JWT_TYP as KB_JWT_TYP2
|
|
385
|
-
SD_JWT_TYP
|
|
384
|
+
KB_JWT_TYP as KB_JWT_TYP2
|
|
386
385
|
} from "@sd-jwt/types";
|
|
387
386
|
import { getSDAlgAndPayload as getSDAlgAndPayload2 } from "@sd-jwt/decode";
|
|
388
387
|
var _SDJwtInstance = class _SDJwtInstance {
|
|
@@ -441,6 +440,9 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
441
440
|
if (!this.userConfig.signAlg) {
|
|
442
441
|
throw new SDJWTException4("sign alogrithm not specified");
|
|
443
442
|
}
|
|
443
|
+
if (disclosureFrame) {
|
|
444
|
+
this.validateReservedFields(disclosureFrame);
|
|
445
|
+
}
|
|
444
446
|
const hasher = this.userConfig.hasher;
|
|
445
447
|
const hashAlg = (_a = this.userConfig.hashAlg) != null ? _a : _SDJwtInstance.DEFAULT_hashAlg;
|
|
446
448
|
const { packedClaims, disclosures } = yield pack(
|
|
@@ -451,7 +453,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
451
453
|
);
|
|
452
454
|
const alg = this.userConfig.signAlg;
|
|
453
455
|
const OptionHeader = (_b = options == null ? void 0 : options.header) != null ? _b : {};
|
|
454
|
-
const CustomHeader = this.userConfig.omitTyp ? OptionHeader : __spreadValues({ typ:
|
|
456
|
+
const CustomHeader = this.userConfig.omitTyp ? OptionHeader : __spreadValues({ typ: this.type }, OptionHeader);
|
|
455
457
|
const header = __spreadProps(__spreadValues({}, CustomHeader), { alg });
|
|
456
458
|
const jwt = new Jwt({
|
|
457
459
|
header,
|
|
@@ -467,6 +469,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
467
469
|
return sdJwt.encodeSDJwt();
|
|
468
470
|
});
|
|
469
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Validates if the disclosureFrame contains any reserved fields. If so it will throw an error.
|
|
474
|
+
* @param disclosureFrame
|
|
475
|
+
* @returns
|
|
476
|
+
*/
|
|
477
|
+
validateReservedFields(disclosureFrame) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
470
480
|
present(encodedSDJwt, presentationKeys, options) {
|
|
471
481
|
return __async(this, null, function* () {
|
|
472
482
|
var _a;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/core",
|
|
3
|
-
"version": "0.3.2-next.
|
|
3
|
+
"version": "0.3.2-next.95+a2daee4",
|
|
4
4
|
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "rm -rf **/dist && tsup",
|
|
16
16
|
"lint": "biome lint ./src",
|
|
17
|
-
"test": "pnpm run test:node && pnpm run test:browser && pnpm run test:
|
|
18
|
-
"test:node": "vitest run ./src/test/*.spec.ts
|
|
17
|
+
"test": "pnpm run test:node && pnpm run test:browser && pnpm run test:cov",
|
|
18
|
+
"test:node": "vitest run ./src/test/*.spec.ts",
|
|
19
19
|
"test:browser": "vitest run ./src/test/*.spec.ts --environment jsdom",
|
|
20
|
-
"test:e2e": "vitest run ./test/*e2e.spec.ts --environment node",
|
|
21
20
|
"test:cov": "vitest run --coverage"
|
|
22
21
|
},
|
|
23
22
|
"keywords": [
|
|
@@ -39,12 +38,12 @@
|
|
|
39
38
|
},
|
|
40
39
|
"license": "Apache-2.0",
|
|
41
40
|
"devDependencies": {
|
|
42
|
-
"@sd-jwt/crypto-nodejs": "0.3.2-next.
|
|
41
|
+
"@sd-jwt/crypto-nodejs": "0.3.2-next.95+a2daee4"
|
|
43
42
|
},
|
|
44
43
|
"dependencies": {
|
|
45
|
-
"@sd-jwt/decode": "0.3.2-next.
|
|
46
|
-
"@sd-jwt/types": "0.3.2-next.
|
|
47
|
-
"@sd-jwt/utils": "0.3.2-next.
|
|
44
|
+
"@sd-jwt/decode": "0.3.2-next.95+a2daee4",
|
|
45
|
+
"@sd-jwt/types": "0.3.2-next.95+a2daee4",
|
|
46
|
+
"@sd-jwt/utils": "0.3.2-next.95+a2daee4"
|
|
48
47
|
},
|
|
49
48
|
"publishConfig": {
|
|
50
49
|
"access": "public"
|
|
@@ -62,5 +61,5 @@
|
|
|
62
61
|
"esm"
|
|
63
62
|
]
|
|
64
63
|
},
|
|
65
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "a2daee4acc8def8b4d5871b36f740f0f5d50479d"
|
|
66
65
|
}
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
KB_JWT_TYP,
|
|
10
10
|
SDJWTCompact,
|
|
11
11
|
SDJWTConfig,
|
|
12
|
-
SD_JWT_TYP,
|
|
13
12
|
} from '@sd-jwt/types';
|
|
14
13
|
import { getSDAlgAndPayload } from '@sd-jwt/decode';
|
|
15
14
|
|
|
@@ -18,7 +17,12 @@ export * from './kbjwt';
|
|
|
18
17
|
export * from './jwt';
|
|
19
18
|
export * from './decoy';
|
|
20
19
|
|
|
21
|
-
export
|
|
20
|
+
export type SdJwtPayload = Record<string, unknown>;
|
|
21
|
+
|
|
22
|
+
export class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
23
|
+
//header type
|
|
24
|
+
protected type?: string;
|
|
25
|
+
|
|
22
26
|
public static DEFAULT_hashAlg = 'sha-256';
|
|
23
27
|
|
|
24
28
|
private userConfig: SDJWTConfig = {};
|
|
@@ -68,7 +72,7 @@ export class SDJwtInstance {
|
|
|
68
72
|
return jwt.verify(this.userConfig.verifier);
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
public async issue<Payload extends
|
|
75
|
+
public async issue<Payload extends ExtendedPayload>(
|
|
72
76
|
payload: Payload,
|
|
73
77
|
disclosureFrame?: DisclosureFrame<Payload>,
|
|
74
78
|
options?: {
|
|
@@ -87,6 +91,10 @@ export class SDJwtInstance {
|
|
|
87
91
|
throw new SDJWTException('sign alogrithm not specified');
|
|
88
92
|
}
|
|
89
93
|
|
|
94
|
+
if (disclosureFrame) {
|
|
95
|
+
this.validateReservedFields<Payload>(disclosureFrame);
|
|
96
|
+
}
|
|
97
|
+
|
|
90
98
|
const hasher = this.userConfig.hasher;
|
|
91
99
|
const hashAlg = this.userConfig.hashAlg ?? SDJwtInstance.DEFAULT_hashAlg;
|
|
92
100
|
|
|
@@ -100,7 +108,7 @@ export class SDJwtInstance {
|
|
|
100
108
|
const OptionHeader = options?.header ?? {};
|
|
101
109
|
const CustomHeader = this.userConfig.omitTyp
|
|
102
110
|
? OptionHeader
|
|
103
|
-
: { typ:
|
|
111
|
+
: { typ: this.type, ...OptionHeader };
|
|
104
112
|
const header = { ...CustomHeader, alg };
|
|
105
113
|
const jwt = new Jwt({
|
|
106
114
|
header,
|
|
@@ -119,6 +127,17 @@ export class SDJwtInstance {
|
|
|
119
127
|
return sdJwt.encodeSDJwt();
|
|
120
128
|
}
|
|
121
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Validates if the disclosureFrame contains any reserved fields. If so it will throw an error.
|
|
132
|
+
* @param disclosureFrame
|
|
133
|
+
* @returns
|
|
134
|
+
*/
|
|
135
|
+
protected validateReservedFields<T extends ExtendedPayload>(
|
|
136
|
+
disclosureFrame: DisclosureFrame<T>,
|
|
137
|
+
) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
122
141
|
public async present(
|
|
123
142
|
encodedSDJwt: string,
|
|
124
143
|
presentationKeys?: string[],
|
package/src/test/index.spec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SDJwtInstance } from '../index';
|
|
1
|
+
import { SDJwtInstance, SdJwtPayload } from '../index';
|
|
2
2
|
import { Signer, Verifier } from '@sd-jwt/types';
|
|
3
3
|
import Crypto from 'node:crypto';
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
@@ -23,13 +23,13 @@ export const createSignerVerifier = () => {
|
|
|
23
23
|
|
|
24
24
|
describe('index', () => {
|
|
25
25
|
test('create', async () => {
|
|
26
|
-
const sdjwt = new SDJwtInstance();
|
|
26
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>();
|
|
27
27
|
expect(sdjwt).toBeDefined();
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
test('kbJwt', async () => {
|
|
31
31
|
const { signer, verifier } = createSignerVerifier();
|
|
32
|
-
const sdjwt = new SDJwtInstance({
|
|
32
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
33
33
|
signer,
|
|
34
34
|
signAlg: 'EdDSA',
|
|
35
35
|
verifier,
|
|
@@ -41,6 +41,9 @@ describe('index', () => {
|
|
|
41
41
|
const credential = await sdjwt.issue(
|
|
42
42
|
{
|
|
43
43
|
foo: 'bar',
|
|
44
|
+
iss: 'Issuer',
|
|
45
|
+
iat: new Date().getTime(),
|
|
46
|
+
vct: '',
|
|
44
47
|
},
|
|
45
48
|
{
|
|
46
49
|
_sd: ['foo'],
|
|
@@ -64,7 +67,7 @@ describe('index', () => {
|
|
|
64
67
|
|
|
65
68
|
test('issue', async () => {
|
|
66
69
|
const { signer, verifier } = createSignerVerifier();
|
|
67
|
-
const sdjwt = new SDJwtInstance({
|
|
70
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
68
71
|
signer,
|
|
69
72
|
signAlg: 'EdDSA',
|
|
70
73
|
verifier,
|
|
@@ -74,6 +77,9 @@ describe('index', () => {
|
|
|
74
77
|
const credential = await sdjwt.issue(
|
|
75
78
|
{
|
|
76
79
|
foo: 'bar',
|
|
80
|
+
iss: 'Issuer',
|
|
81
|
+
iat: new Date().getTime(),
|
|
82
|
+
vct: '',
|
|
77
83
|
},
|
|
78
84
|
{
|
|
79
85
|
_sd: ['foo'],
|
|
@@ -95,7 +101,7 @@ describe('index', () => {
|
|
|
95
101
|
);
|
|
96
102
|
};
|
|
97
103
|
|
|
98
|
-
const sdjwt = new SDJwtInstance({
|
|
104
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
99
105
|
signer,
|
|
100
106
|
signAlg: 'EdDSA',
|
|
101
107
|
verifier: failedverifier,
|
|
@@ -106,6 +112,9 @@ describe('index', () => {
|
|
|
106
112
|
const credential = await sdjwt.issue(
|
|
107
113
|
{
|
|
108
114
|
foo: 'bar',
|
|
115
|
+
iss: 'Issuer',
|
|
116
|
+
iat: new Date().getTime(),
|
|
117
|
+
vct: '',
|
|
109
118
|
},
|
|
110
119
|
{
|
|
111
120
|
_sd: ['foo'],
|
|
@@ -130,7 +139,7 @@ describe('index', () => {
|
|
|
130
139
|
Buffer.from(sig, 'base64url'),
|
|
131
140
|
);
|
|
132
141
|
};
|
|
133
|
-
const sdjwt = new SDJwtInstance({
|
|
142
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
134
143
|
signer,
|
|
135
144
|
signAlg: 'EdDSA',
|
|
136
145
|
verifier,
|
|
@@ -144,6 +153,9 @@ describe('index', () => {
|
|
|
144
153
|
const credential = await sdjwt.issue(
|
|
145
154
|
{
|
|
146
155
|
foo: 'bar',
|
|
156
|
+
iss: 'Issuer',
|
|
157
|
+
iat: new Date().getTime(),
|
|
158
|
+
vct: '',
|
|
147
159
|
},
|
|
148
160
|
{
|
|
149
161
|
_sd: ['foo'],
|
|
@@ -169,7 +181,7 @@ describe('index', () => {
|
|
|
169
181
|
|
|
170
182
|
test('verify with kbJwt', async () => {
|
|
171
183
|
const { signer, verifier } = createSignerVerifier();
|
|
172
|
-
const sdjwt = new SDJwtInstance({
|
|
184
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
173
185
|
signer,
|
|
174
186
|
signAlg: 'EdDSA',
|
|
175
187
|
verifier,
|
|
@@ -183,6 +195,9 @@ describe('index', () => {
|
|
|
183
195
|
const credential = await sdjwt.issue(
|
|
184
196
|
{
|
|
185
197
|
foo: 'bar',
|
|
198
|
+
iss: 'Issuer',
|
|
199
|
+
iat: new Date().getTime(),
|
|
200
|
+
vct: '',
|
|
186
201
|
},
|
|
187
202
|
{
|
|
188
203
|
_sd: ['foo'],
|
|
@@ -204,11 +219,14 @@ describe('index', () => {
|
|
|
204
219
|
});
|
|
205
220
|
|
|
206
221
|
test('Hasher not found', async () => {
|
|
207
|
-
const sdjwt = new SDJwtInstance({});
|
|
222
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({});
|
|
208
223
|
try {
|
|
209
224
|
const credential = await sdjwt.issue(
|
|
210
225
|
{
|
|
211
226
|
foo: 'bar',
|
|
227
|
+
iss: 'Issuer',
|
|
228
|
+
iat: new Date().getTime(),
|
|
229
|
+
vct: '',
|
|
212
230
|
},
|
|
213
231
|
{
|
|
214
232
|
_sd: ['foo'],
|
|
@@ -222,13 +240,16 @@ describe('index', () => {
|
|
|
222
240
|
});
|
|
223
241
|
|
|
224
242
|
test('SaltGenerator not found', async () => {
|
|
225
|
-
const sdjwt = new SDJwtInstance({
|
|
243
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
226
244
|
hasher: digest,
|
|
227
245
|
});
|
|
228
246
|
try {
|
|
229
247
|
const credential = await sdjwt.issue(
|
|
230
248
|
{
|
|
231
249
|
foo: 'bar',
|
|
250
|
+
iss: 'Issuer',
|
|
251
|
+
iat: new Date().getTime(),
|
|
252
|
+
vct: '',
|
|
232
253
|
},
|
|
233
254
|
{
|
|
234
255
|
_sd: ['foo'],
|
|
@@ -242,7 +263,7 @@ describe('index', () => {
|
|
|
242
263
|
});
|
|
243
264
|
|
|
244
265
|
test('Signer not found', async () => {
|
|
245
|
-
const sdjwt = new SDJwtInstance({
|
|
266
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
246
267
|
hasher: digest,
|
|
247
268
|
saltGenerator: generateSalt,
|
|
248
269
|
});
|
|
@@ -250,6 +271,9 @@ describe('index', () => {
|
|
|
250
271
|
const credential = await sdjwt.issue(
|
|
251
272
|
{
|
|
252
273
|
foo: 'bar',
|
|
274
|
+
iss: 'Issuer',
|
|
275
|
+
iat: new Date().getTime(),
|
|
276
|
+
vct: '',
|
|
253
277
|
},
|
|
254
278
|
{
|
|
255
279
|
_sd: ['foo'],
|
|
@@ -264,7 +288,7 @@ describe('index', () => {
|
|
|
264
288
|
|
|
265
289
|
test('Verifier not found', async () => {
|
|
266
290
|
const { signer, verifier } = createSignerVerifier();
|
|
267
|
-
const sdjwt = new SDJwtInstance({
|
|
291
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
268
292
|
signer,
|
|
269
293
|
hasher: digest,
|
|
270
294
|
saltGenerator: generateSalt,
|
|
@@ -277,6 +301,9 @@ describe('index', () => {
|
|
|
277
301
|
const credential = await sdjwt.issue(
|
|
278
302
|
{
|
|
279
303
|
foo: 'bar',
|
|
304
|
+
iss: 'Issuer',
|
|
305
|
+
iat: new Date().getTime(),
|
|
306
|
+
vct: '',
|
|
280
307
|
},
|
|
281
308
|
{
|
|
282
309
|
_sd: ['foo'],
|
|
@@ -301,7 +328,7 @@ describe('index', () => {
|
|
|
301
328
|
|
|
302
329
|
test('kbSigner not found', async () => {
|
|
303
330
|
const { signer, verifier } = createSignerVerifier();
|
|
304
|
-
const sdjwt = new SDJwtInstance({
|
|
331
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
305
332
|
signer,
|
|
306
333
|
verifier,
|
|
307
334
|
hasher: digest,
|
|
@@ -314,6 +341,9 @@ describe('index', () => {
|
|
|
314
341
|
const credential = await sdjwt.issue(
|
|
315
342
|
{
|
|
316
343
|
foo: 'bar',
|
|
344
|
+
iss: 'Issuer',
|
|
345
|
+
iat: new Date().getTime(),
|
|
346
|
+
vct: '',
|
|
317
347
|
},
|
|
318
348
|
{
|
|
319
349
|
_sd: ['foo'],
|
|
@@ -336,7 +366,7 @@ describe('index', () => {
|
|
|
336
366
|
|
|
337
367
|
test('kbVerifier not found', async () => {
|
|
338
368
|
const { signer, verifier } = createSignerVerifier();
|
|
339
|
-
const sdjwt = new SDJwtInstance({
|
|
369
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
340
370
|
signer,
|
|
341
371
|
verifier,
|
|
342
372
|
hasher: digest,
|
|
@@ -349,6 +379,9 @@ describe('index', () => {
|
|
|
349
379
|
const credential = await sdjwt.issue(
|
|
350
380
|
{
|
|
351
381
|
foo: 'bar',
|
|
382
|
+
iss: 'Issuer',
|
|
383
|
+
iat: new Date().getTime(),
|
|
384
|
+
vct: '',
|
|
352
385
|
},
|
|
353
386
|
{
|
|
354
387
|
_sd: ['foo'],
|
|
@@ -370,4 +403,94 @@ describe('index', () => {
|
|
|
370
403
|
expect(e).toBeDefined();
|
|
371
404
|
}
|
|
372
405
|
});
|
|
406
|
+
|
|
407
|
+
test('kbSignAlg not found', async () => {
|
|
408
|
+
const { signer, verifier } = createSignerVerifier();
|
|
409
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
410
|
+
signer,
|
|
411
|
+
verifier,
|
|
412
|
+
hasher: digest,
|
|
413
|
+
saltGenerator: generateSalt,
|
|
414
|
+
kbSigner: signer,
|
|
415
|
+
signAlg: 'EdDSA',
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const credential = await sdjwt.issue(
|
|
419
|
+
{
|
|
420
|
+
foo: 'bar',
|
|
421
|
+
iss: 'Issuer',
|
|
422
|
+
iat: new Date().getTime(),
|
|
423
|
+
vct: '',
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
_sd: ['foo'],
|
|
427
|
+
},
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
const presentation = sdjwt.present(credential, ['foo'], {
|
|
431
|
+
kb: {
|
|
432
|
+
payload: {
|
|
433
|
+
aud: '1',
|
|
434
|
+
iat: 1,
|
|
435
|
+
nonce: '342',
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
expect(presentation).rejects.toThrow(
|
|
440
|
+
'Key Binding sign algorithm not specified',
|
|
441
|
+
);
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
test('hasher is not found', async () => {
|
|
445
|
+
const { signer } = createSignerVerifier();
|
|
446
|
+
const sdjwt_create = new SDJwtInstance<SdJwtPayload>({
|
|
447
|
+
signer,
|
|
448
|
+
hasher: digest,
|
|
449
|
+
saltGenerator: generateSalt,
|
|
450
|
+
signAlg: 'EdDSA',
|
|
451
|
+
});
|
|
452
|
+
const credential = await sdjwt_create.issue(
|
|
453
|
+
{
|
|
454
|
+
foo: 'bar',
|
|
455
|
+
iss: 'Issuer',
|
|
456
|
+
iat: new Date().getTime(),
|
|
457
|
+
vct: '',
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
_sd: ['foo'],
|
|
461
|
+
},
|
|
462
|
+
);
|
|
463
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({});
|
|
464
|
+
expect(sdjwt.keys('')).rejects.toThrow('Hasher not found');
|
|
465
|
+
expect(sdjwt.presentableKeys('')).rejects.toThrow('Hasher not found');
|
|
466
|
+
expect(sdjwt.getClaims('')).rejects.toThrow('Hasher not found');
|
|
467
|
+
expect(() => sdjwt.decode('')).toThrowError('Hasher not found');
|
|
468
|
+
expect(sdjwt.present(credential, ['foo'])).rejects.toThrow(
|
|
469
|
+
'Hasher not found',
|
|
470
|
+
);
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
test('presentableKeys', async () => {
|
|
474
|
+
const { signer } = createSignerVerifier();
|
|
475
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
476
|
+
signer,
|
|
477
|
+
hasher: digest,
|
|
478
|
+
saltGenerator: generateSalt,
|
|
479
|
+
signAlg: 'EdDSA',
|
|
480
|
+
});
|
|
481
|
+
const credential = await sdjwt.issue(
|
|
482
|
+
{
|
|
483
|
+
foo: 'bar',
|
|
484
|
+
iss: 'Issuer',
|
|
485
|
+
iat: new Date().getTime(),
|
|
486
|
+
vct: '',
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
_sd: ['foo'],
|
|
490
|
+
},
|
|
491
|
+
);
|
|
492
|
+
const keys = await sdjwt.presentableKeys(credential);
|
|
493
|
+
expect(keys).toBeDefined();
|
|
494
|
+
expect(keys).toEqual(['foo']);
|
|
495
|
+
});
|
|
373
496
|
});
|
package/test/app-e2e.spec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Crypto from 'node:crypto';
|
|
2
|
-
import { SDJwtInstance } from '../src';
|
|
2
|
+
import { SDJwtInstance, SdJwtPayload } from '../src';
|
|
3
3
|
import { DisclosureFrame, Signer, Verifier } from '@sd-jwt/types';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
@@ -26,7 +26,7 @@ export const createSignerVerifier = () => {
|
|
|
26
26
|
describe('App', () => {
|
|
27
27
|
test('Example', async () => {
|
|
28
28
|
const { signer, verifier } = createSignerVerifier();
|
|
29
|
-
const sdjwt = new SDJwtInstance({
|
|
29
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
30
30
|
signer,
|
|
31
31
|
signAlg: 'EdDSA',
|
|
32
32
|
verifier,
|
|
@@ -192,7 +192,7 @@ describe('App', () => {
|
|
|
192
192
|
async function JSONtest(filename: string) {
|
|
193
193
|
const test = loadTestJsonFile(filename);
|
|
194
194
|
const { signer, verifier } = createSignerVerifier();
|
|
195
|
-
const sdjwt = new SDJwtInstance({
|
|
195
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
196
196
|
signer,
|
|
197
197
|
signAlg: 'EdDSA',
|
|
198
198
|
verifier,
|
|
@@ -209,7 +209,7 @@ async function JSONtest(filename: string) {
|
|
|
209
209
|
|
|
210
210
|
expect(validated).toBeDefined();
|
|
211
211
|
expect(validated).toStrictEqual({
|
|
212
|
-
header: { alg: 'EdDSA'
|
|
212
|
+
header: { alg: 'EdDSA' },
|
|
213
213
|
payload: test.claims,
|
|
214
214
|
});
|
|
215
215
|
|
|
@@ -228,14 +228,14 @@ async function JSONtest(filename: string) {
|
|
|
228
228
|
|
|
229
229
|
expect(verified).toBeDefined();
|
|
230
230
|
expect(verified).toStrictEqual({
|
|
231
|
-
header: { alg: 'EdDSA'
|
|
231
|
+
header: { alg: 'EdDSA' },
|
|
232
232
|
payload: test.claims,
|
|
233
233
|
});
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
type TestJson = {
|
|
237
|
-
claims:
|
|
238
|
-
disclosureFrame: DisclosureFrame<
|
|
237
|
+
claims: SdJwtPayload;
|
|
238
|
+
disclosureFrame: DisclosureFrame<SdJwtPayload>;
|
|
239
239
|
presentationKeys: string[];
|
|
240
240
|
presenatedClaims: object;
|
|
241
241
|
requiredClaimKeys: string[];
|