Skip to content

Commit 3692498

Browse files
lukasjhancre8
authored andcommitted
Merging Process #1 from sd-jwt-ts (#60)
Signed-off-by: Lukas.J.Han <lukas.j.han@gmail.com> Signed-off-by: Lukas <Lukas@hopae.io> Signed-off-by: Mirko Mollik <mirko.mollik@fit.fraunhofer.de>
1 parent a07fa74 commit 3692498

35 files changed

+1247
-853
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ Check out more details in our [documentation](https://github.com/openwallet-foun
9191

9292
## Dependencies
9393

94-
- [jose](https://github.com/panva/jose)
94+
- "@noble/hashes": "1.0.0",
95+
- pure js hash algorithm implementation with security audit (v1.0.0)
96+
- "js-base64": "^3.7.6"
97+
- pure js base64 implementation
9598

9699
## Build
97100

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pnpm run all
2626
- sdjwtobject: Example of using SD JWT Object
2727
- decoy: Example of adding decoy digest in SD JWT
2828
- kb: key binding example in SD JWT
29+
- decode: Decoding example of a SD JWT sample
2930

3031
### Variables In Examples
3132

examples/all.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
import sdjwt, { DisclosureFrame } from '@hopae/sd-jwt';
2-
import Crypto from 'node:crypto';
3-
4-
export const createKeyPair = () => {
5-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
6-
return { privateKey, publicKey };
7-
};
1+
import { DisclosureFrame, SDJwtInstance } from '@hopae/sd-jwt';
2+
import { createSignerVerifier, digest, generateSalt } from './utils';
83

94
(async () => {
10-
const { privateKey, publicKey } = createKeyPair();
5+
const { signer, verifier } = createSignerVerifier();
6+
7+
// Create SDJwt instance for use
8+
const sdjwt = new SDJwtInstance({
9+
signer,
10+
verifier,
11+
signAlg: 'EdDSA',
12+
hasher: digest,
13+
hashAlg: 'SHA-256',
14+
saltGenerator: generateSalt,
15+
});
1116

1217
// Issuer Define the claims object with the user's information
1318
const claims = {
@@ -47,26 +52,26 @@ export const createKeyPair = () => {
4752

4853
// Issue a signed JWT credential with the specified claims and disclosures
4954
// Return a Encoded SD JWT. Issuer send the credential to the holder
50-
const credential = await sdjwt.issue(claims, { privateKey }, disclosureFrame);
55+
const credential = await sdjwt.issue(claims, disclosureFrame);
5156
console.log('encodedJwt:', credential);
5257

5358
// Holder Receive the credential from the issuer and validate it
5459
// Return a boolean result
55-
const validated = await sdjwt.validate(credential, { publicKey });
60+
const validated = await sdjwt.validate(credential);
5661
console.log('validated:', validated);
5762

5863
// You can decode the SD JWT to get the payload and the disclosures
59-
const sdJwtToken = sdjwt.decode(credential);
64+
const sdJwtToken = await sdjwt.decode(credential);
6065

6166
// You can get the keys of the claims from the decoded SD JWT
62-
const keys = await sdJwtToken.keys();
67+
const keys = await sdJwtToken.keys(digest);
6368
console.log({ keys });
6469

6570
// You can get the claims from the decoded SD JWT
66-
const payloads = await sdJwtToken.getClaims();
71+
const payloads = await sdJwtToken.getClaims(digest);
6772

6873
// You can get the presentable keys from the decoded SD JWT
69-
const presentableKeys = await sdJwtToken.presentableKeys();
74+
const presentableKeys = await sdJwtToken.presentableKeys(digest);
7075

7176
console.log({
7277
payloads: JSON.stringify(payloads, null, 2),
@@ -94,10 +99,6 @@ export const createKeyPair = () => {
9499

95100
// Verify the presentation using the public key and the required claims
96101
// return a boolean result
97-
const verified = await sdjwt.verify(
98-
credential,
99-
{ publicKey },
100-
requiredClaims,
101-
);
102+
const verified = await sdjwt.verify(credential, requiredClaims);
102103
console.log('verified:', verified);
103104
})();

examples/basic.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
import sdjwt, { DisclosureFrame } from '@hopae/sd-jwt';
2-
import Crypto from 'node:crypto';
3-
4-
export const createKeyPair = () => {
5-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
6-
return { privateKey, publicKey };
7-
};
1+
import { DisclosureFrame, SDJwtInstance } from '@hopae/sd-jwt';
2+
import { createSignerVerifier, digest, generateSalt } from './utils';
83

94
(async () => {
10-
const { privateKey, publicKey } = createKeyPair();
5+
const { signer, verifier } = createSignerVerifier();
6+
7+
// Create SDJwt instance for use
8+
const sdjwt = new SDJwtInstance({
9+
signer,
10+
verifier,
11+
signAlg: 'EdDSA',
12+
hasher: digest,
13+
hashAlg: 'SHA-256',
14+
saltGenerator: generateSalt,
15+
});
16+
1117
// Issuer Define the claims object with the user's information
1218
const claims = {
1319
firstname: 'John',
@@ -23,11 +29,11 @@ export const createKeyPair = () => {
2329

2430
// Issue a signed JWT credential with the specified claims and disclosures
2531
// Return a Encoded SD JWT. Issuer send the credential to the holder
26-
const credential = await sdjwt.issue(claims, { privateKey }, disclosureFrame);
32+
const credential = await sdjwt.issue(claims, disclosureFrame);
2733

2834
// Holder Receive the credential from the issuer and validate it
2935
// Return a boolean result
30-
const valid = await sdjwt.validate(credential, { publicKey });
36+
const valid = await sdjwt.validate(credential);
3137

3238
// Holder Define the presentation frame to specify which claims should be presented
3339
// The list of presented claims must be a subset of the disclosed claims
@@ -43,10 +49,6 @@ export const createKeyPair = () => {
4349

4450
// Verify the presentation using the public key and the required claims
4551
// return a boolean result
46-
const verified = await sdjwt.verify(
47-
presentation,
48-
{ publicKey },
49-
requiredClaims,
50-
);
52+
const verified = await sdjwt.verify(presentation, requiredClaims);
5153
console.log(verified);
5254
})();

examples/custom.ts

Lines changed: 21 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,18 @@
1-
import sdjwt, { DisclosureFrame } from '@hopae/sd-jwt';
2-
import Crypto from 'node:crypto';
3-
4-
export const salt = (length: number): string => {
5-
const saltBytes = Crypto.randomBytes(length);
6-
const salt = saltBytes.toString('hex');
7-
return salt;
8-
};
9-
10-
export const digest = async (
11-
data: string,
12-
algorithm: string = 'SHA-256',
13-
): Promise<string> => {
14-
const hash = Crypto.createHash(algorithm);
15-
hash.update(data);
16-
return hash.digest('hex');
17-
};
18-
19-
export const createKeyPair = () => {
20-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
21-
return { privateKey, publicKey };
22-
};
1+
import { DisclosureFrame, SDJwtInstance } from '@hopae/sd-jwt';
2+
import { createSignerVerifier, digest, generateSalt } from './utils';
233

244
(async () => {
25-
// You can create a custom SDJwt instance with your own hasher and salt generator
26-
const SDJwtInstance = sdjwt.create({ hasher: digest, saltGenerator: salt });
27-
28-
const { privateKey, publicKey } = createKeyPair();
5+
const { signer, verifier } = createSignerVerifier();
6+
7+
// Create SDJwt instance for use
8+
const sdjwt = new SDJwtInstance({
9+
signer,
10+
verifier,
11+
signAlg: 'EdDSA',
12+
hasher: digest,
13+
hashAlg: 'SHA-256',
14+
saltGenerator: generateSalt,
15+
});
2916

3017
// Issuer Define the claims object with the user's information
3118
const claims = {
@@ -42,30 +29,26 @@ export const createKeyPair = () => {
4229

4330
// Issue a signed JWT credential with the specified claims and disclosures
4431
// Return a Encoded SD JWT. Issuer send the credential to the holder
45-
const credential = await SDJwtInstance.issue(
46-
claims,
47-
{ privateKey },
48-
disclosureFrame,
49-
);
32+
const credential = await sdjwt.issue(claims, disclosureFrame);
5033
console.log('encodedJwt:', credential);
5134

5235
// Holder Receive the credential from the issuer and validate it
5336
// Return a boolean result
54-
const validated = await SDJwtInstance.validate(credential, { publicKey });
37+
const validated = await sdjwt.validate(credential);
5538
console.log('validated:', validated);
5639

5740
// You can decode the SD JWT to get the payload and the disclosures
58-
const sdJwtToken = SDJwtInstance.decode(credential);
41+
const sdJwtToken = await sdjwt.decode(credential);
5942

6043
// You can get the keys of the claims from the decoded SD JWT
61-
const keys = await sdJwtToken.keys();
44+
const keys = await sdJwtToken.keys(digest);
6245
console.log({ keys });
6346

6447
// You can get the claims from the decoded SD JWT
65-
const payloads = await sdJwtToken.getClaims();
48+
const payloads = await sdJwtToken.getClaims(digest);
6649

6750
// You can get the presentable keys from the decoded SD JWT
68-
const presentableKeys = await sdJwtToken.presentableKeys();
51+
const presentableKeys = await sdJwtToken.presentableKeys(digest);
6952

7053
console.log({
7154
payloads: JSON.stringify(payloads, null, 2),
@@ -85,21 +68,14 @@ export const createKeyPair = () => {
8568

8669
// Create a presentation using the issued credential and the presentation frame
8770
// return a Encoded SD JWT. Holder send the presentation to the verifier
88-
const presentation = await SDJwtInstance.present(
89-
credential,
90-
presentationFrame,
91-
);
71+
const presentation = await sdjwt.present(credential, presentationFrame);
9272
console.log('presentedSDJwt:', presentation);
9373

9474
// Verifier Define the required claims that need to be verified in the presentation
9575
const requiredClaims = ['firstname', 'id'];
9676

9777
// Verify the presentation using the public key and the required claims
9878
// return a boolean result
99-
const verified = await SDJwtInstance.verify(
100-
presentation,
101-
{ publicKey },
102-
requiredClaims,
103-
);
79+
const verified = await sdjwt.verify(presentation, requiredClaims);
10480
console.log('verified:', verified);
10581
})();

examples/custom_header.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
import sdjwt, { DisclosureFrame } from '@hopae/sd-jwt';
2-
import Crypto from 'node:crypto';
3-
4-
export const createKeyPair = () => {
5-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
6-
return { privateKey, publicKey };
7-
};
1+
import { DisclosureFrame, SDJwtInstance } from '@hopae/sd-jwt';
2+
import { createSignerVerifier, digest, generateSalt } from './utils';
83

94
(async () => {
10-
const { privateKey, publicKey } = createKeyPair();
5+
const { signer, verifier } = createSignerVerifier();
6+
7+
// Create SDJwt instance for use
8+
const sdjwt = new SDJwtInstance({
9+
signer,
10+
verifier,
11+
signAlg: 'EdDSA',
12+
hasher: digest,
13+
hashAlg: 'SHA-256',
14+
saltGenerator: generateSalt,
15+
});
16+
1117
// Issuer Define the claims object with the user's information
1218
const claims = {
1319
firstname: 'John',
@@ -23,17 +29,12 @@ export const createKeyPair = () => {
2329

2430
// Issue a signed JWT credential with the specified claims and disclosures
2531
// Return a Encoded SD JWT. Issuer send the credential to the holder
26-
const credential = await sdjwt.issue(
27-
claims,
28-
{ privateKey },
29-
disclosureFrame,
30-
{
31-
header: { typ: 'vc+sd-jwt', custom: 'data' }, // You can add custom header data to the SD JWT
32-
},
33-
);
32+
const credential = await sdjwt.issue(claims, disclosureFrame, {
33+
header: { typ: 'vc+sd-jwt', custom: 'data' }, // You can add custom header data to the SD JWT
34+
});
3435
console.log('encodedSdjwt:', credential);
3536

3637
// You can check the custom header data by decoding the SD JWT
37-
const sdJwtToken = sdjwt.decode(credential);
38+
const sdJwtToken = await sdjwt.decode(credential);
3839
console.log(sdJwtToken);
3940
})();

examples/decode.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { SDJwtInstance } from '@hopae/sd-jwt';
2+
import { createSignerVerifier, digest, generateSalt } from './utils';
3+
4+
(async () => {
5+
const { signer, verifier } = createSignerVerifier();
6+
7+
// Create SDJwt instance for use
8+
const sdjwt = new SDJwtInstance({
9+
signer,
10+
signAlg: 'EdDSA',
11+
verifier,
12+
hasher: digest,
13+
saltGenerator: generateSalt,
14+
kbSigner: signer,
15+
kbSignAlg: 'EdDSA',
16+
kbVerifier: verifier,
17+
});
18+
19+
// this is an example of SD JWT
20+
const data = `eyJhbGciOiAiRVMyNTYiLCAia2lkIjogImRvYy1zaWduZXItMDUtMjUtMjAyMiIsICJ0eXAiOiAidmMrc2Qtand0In0.eyJfc2QiOiBbIjA5dktySk1PbHlUV00wc2pwdV9wZE9CVkJRMk0xeTNLaHBINTE1blhrcFkiLCAiMnJzakdiYUMwa3k4bVQwcEpyUGlvV1RxMF9kYXcxc1g3NnBvVWxnQ3diSSIsICJFa084ZGhXMGRIRUpidlVIbEVfVkNldUM5dVJFTE9pZUxaaGg3WGJVVHRBIiwgIklsRHpJS2VpWmREd3BxcEs2WmZieXBoRnZ6NUZnbldhLXNONndxUVhDaXciLCAiSnpZakg0c3ZsaUgwUjNQeUVNZmVadTZKdDY5dTVxZWhabzdGN0VQWWxTRSIsICJQb3JGYnBLdVZ1Nnh5bUphZ3ZrRnNGWEFiUm9jMkpHbEFVQTJCQTRvN2NJIiwgIlRHZjRvTGJnd2Q1SlFhSHlLVlFaVTlVZEdFMHc1cnREc3JaemZVYW9tTG8iLCAiamRyVEU4WWNiWTRFaWZ1Z2loaUFlX0JQZWt4SlFaSUNlaVVRd1k5UXF4SSIsICJqc3U5eVZ1bHdRUWxoRmxNXzNKbHpNYVNGemdsaFFHMERwZmF5UXdMVUs0Il0sICJpc3MiOiAiaHR0cHM6Ly9leGFtcGxlLmNvbS9pc3N1ZXIiLCAiaWF0IjogMTY4MzAwMDAwMCwgImV4cCI6IDE4ODMwMDAwMDAsICJkY3QiOiAiaHR0cHM6Ly9jcmVkZW50aWFscy5leGFtcGxlLmNvbS9pZGVudGl0eV9jcmVkZW50aWFsIiwgIl9zZF9hbGciOiAic2hhLTI1NiIsICJjbmYiOiB7Imp3ayI6IHsia3R5IjogIkVDIiwgImNydiI6ICJQLTI1NiIsICJ4IjogIlRDQUVSMTladnUzT0hGNGo0VzR2ZlNWb0hJUDFJTGlsRGxzN3ZDZUdlbWMiLCAieSI6ICJaeGppV1diWk1RR0hWV0tWUTRoYlNJaXJzVmZ1ZWNDRTZ0NGpUOUYySFpRIn19fQ.b036DutqQ72WszrCq0GuqZnbws3MApQyzA41I5DSJmenUfsADtqW8FbI_N04FP1wZDF_JtV6a6Ke3Z7apkoTLA~WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3IiwgImdpdmVuX25hbWUiLCAiSm9obiJd~WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwgImZhbWlseV9uYW1lIiwgIkRvZSJd~WyI2SWo3dE0tYTVpVlBHYm9TNXRtdlZBIiwgImVtYWlsIiwgImpvaG5kb2VAZXhhbXBsZS5jb20iXQ~WyJlSThaV205UW5LUHBOUGVOZW5IZGhRIiwgInBob25lX251bWJlciIsICIrMS0yMDItNTU1LTAxMDEiXQ~WyJRZ19PNjR6cUF4ZTQxMmExMDhpcm9BIiwgImFkZHJlc3MiLCB7InN0cmVldF9hZGRyZXNzIjogIjEyMyBNYWluIFN0IiwgImxvY2FsaXR5IjogIkFueXRvd24iLCAicmVnaW9uIjogIkFueXN0YXRlIiwgImNvdW50cnkiOiAiVVMifV0~WyJBSngtMDk1VlBycFR0TjRRTU9xUk9BIiwgImJpcnRoZGF0ZSIsICIxOTQwLTAxLTAxIl0~WyJQYzMzSk0yTGNoY1VfbEhnZ3ZfdWZRIiwgImlzX292ZXJfMTgiLCB0cnVlXQ~WyJHMDJOU3JRZmpGWFE3SW8wOXN5YWpBIiwgImlzX292ZXJfMjEiLCB0cnVlXQ~WyJsa2x4RjVqTVlsR1RQVW92TU5JdkNBIiwgImlzX292ZXJfNjUiLCB0cnVlXQ~`;
21+
const decodedObject = await sdjwt.decode(data);
22+
console.log(decodedObject);
23+
24+
const claims = await sdjwt.getClaims(data);
25+
console.log(claims);
26+
})();

examples/decoy.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
import sdjwt, { DisclosureFrame } from '@hopae/sd-jwt';
2-
import Crypto from 'node:crypto';
3-
4-
export const createKeyPair = () => {
5-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
6-
return { privateKey, publicKey };
7-
};
1+
import { DisclosureFrame, SDJwtInstance } from '@hopae/sd-jwt';
2+
import { createSignerVerifier, digest, generateSalt } from './utils';
83

94
(async () => {
10-
const { privateKey, publicKey } = createKeyPair();
5+
const { signer, verifier } = createSignerVerifier();
6+
7+
// Create SDJwt instance for use
8+
const sdjwt = new SDJwtInstance({
9+
signer,
10+
verifier,
11+
signAlg: 'EdDSA',
12+
hasher: digest,
13+
hashAlg: 'SHA-256',
14+
saltGenerator: generateSalt,
15+
});
1116
// Issuer Define the claims object with the user's information
1217
const claims = {
1318
lastname: 'Doe',
@@ -20,10 +25,10 @@ export const createKeyPair = () => {
2025
_sd: ['id'],
2126
_sd_decoy: 1, // 1 decoy digest will be added in SD JWT
2227
};
23-
const credential = await sdjwt.issue(claims, { privateKey }, disclosureFrame);
28+
const credential = await sdjwt.issue(claims, disclosureFrame);
2429
console.log('encodedSdjwt:', credential);
2530

2631
// You can check the decoy digest in the SD JWT by decoding it
27-
const sdJwtToken = sdjwt.decode(credential);
32+
const sdJwtToken = await sdjwt.decode(credential);
2833
console.log(sdJwtToken);
2934
})();

0 commit comments

Comments
 (0)