Skip to content

Commit

Permalink
fix: convert any usage into or typed version (#80)
Browse files Browse the repository at this point in the history
Signed-off-by: Berend Sliedrecht <sliedrecht@berend.io>
Co-authored-by: Lukas.J.Han <lukas.j.han@gmail.com>
  • Loading branch information
berendsliedrecht and lukasjhan committed Feb 22, 2024
1 parent 913b446 commit 30ba30b
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 83 deletions.
5 changes: 1 addition & 4 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "off"
}
"recommended": true
}
}
}
2 changes: 1 addition & 1 deletion examples/core-example/decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { createSignerVerifier, digest, generateSalt } from './utils';
});

// this is an example of SD JWT
const data = `eyJhbGciOiAiRVMyNTYiLCAia2lkIjogImRvYy1zaWduZXItMDUtMjUtMjAyMiIsICJ0eXAiOiAidmMrc2Qtand0In0.eyJfc2QiOiBbIjA5dktySk1PbHlUV00wc2pwdV9wZE9CVkJRMk0xeTNLaHBINTE1blhrcFkiLCAiMnJzakdiYUMwa3k4bVQwcEpyUGlvV1RxMF9kYXcxc1g3NnBvVWxnQ3diSSIsICJFa084ZGhXMGRIRUpidlVIbEVfVkNldUM5dVJFTE9pZUxaaGg3WGJVVHRBIiwgIklsRHpJS2VpWmREd3BxcEs2WmZieXBoRnZ6NUZnbldhLXNONndxUVhDaXciLCAiSnpZakg0c3ZsaUgwUjNQeUVNZmVadTZKdDY5dTVxZWhabzdGN0VQWWxTRSIsICJQb3JGYnBLdVZ1Nnh5bUphZ3ZrRnNGWEFiUm9jMkpHbEFVQTJCQTRvN2NJIiwgIlRHZjRvTGJnd2Q1SlFhSHlLVlFaVTlVZEdFMHc1cnREc3JaemZVYW9tTG8iLCAiamRyVEU4WWNiWTRFaWZ1Z2loaUFlX0JQZWt4SlFaSUNlaVVRd1k5UXF4SSIsICJqc3U5eVZ1bHdRUWxoRmxNXzNKbHpNYVNGemdsaFFHMERwZmF5UXdMVUs0Il0sICJpc3MiOiAiaHR0cHM6Ly9leGFtcGxlLmNvbS9pc3N1ZXIiLCAiaWF0IjogMTY4MzAwMDAwMCwgImV4cCI6IDE4ODMwMDAwMDAsICJkY3QiOiAiaHR0cHM6Ly9jcmVkZW50aWFscy5leGFtcGxlLmNvbS9pZGVudGl0eV9jcmVkZW50aWFsIiwgIl9zZF9hbGciOiAic2hhLTI1NiIsICJjbmYiOiB7Imp3ayI6IHsia3R5IjogIkVDIiwgImNydiI6ICJQLTI1NiIsICJ4IjogIlRDQUVSMTladnUzT0hGNGo0VzR2ZlNWb0hJUDFJTGlsRGxzN3ZDZUdlbWMiLCAieSI6ICJaeGppV1diWk1RR0hWV0tWUTRoYlNJaXJzVmZ1ZWNDRTZ0NGpUOUYySFpRIn19fQ.b036DutqQ72WszrCq0GuqZnbws3MApQyzA41I5DSJmenUfsADtqW8FbI_N04FP1wZDF_JtV6a6Ke3Z7apkoTLA~WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3IiwgImdpdmVuX25hbWUiLCAiSm9obiJd~WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwgImZhbWlseV9uYW1lIiwgIkRvZSJd~WyI2SWo3dE0tYTVpVlBHYm9TNXRtdlZBIiwgImVtYWlsIiwgImpvaG5kb2VAZXhhbXBsZS5jb20iXQ~WyJlSThaV205UW5LUHBOUGVOZW5IZGhRIiwgInBob25lX251bWJlciIsICIrMS0yMDItNTU1LTAxMDEiXQ~WyJRZ19PNjR6cUF4ZTQxMmExMDhpcm9BIiwgImFkZHJlc3MiLCB7InN0cmVldF9hZGRyZXNzIjogIjEyMyBNYWluIFN0IiwgImxvY2FsaXR5IjogIkFueXRvd24iLCAicmVnaW9uIjogIkFueXN0YXRlIiwgImNvdW50cnkiOiAiVVMifV0~WyJBSngtMDk1VlBycFR0TjRRTU9xUk9BIiwgImJpcnRoZGF0ZSIsICIxOTQwLTAxLTAxIl0~WyJQYzMzSk0yTGNoY1VfbEhnZ3ZfdWZRIiwgImlzX292ZXJfMTgiLCB0cnVlXQ~WyJHMDJOU3JRZmpGWFE3SW8wOXN5YWpBIiwgImlzX292ZXJfMjEiLCB0cnVlXQ~WyJsa2x4RjVqTVlsR1RQVW92TU5JdkNBIiwgImlzX292ZXJfNjUiLCB0cnVlXQ~`;
const data = "eyJhbGciOiAiRVMyNTYiLCAia2lkIjogImRvYy1zaWduZXItMDUtMjUtMjAyMiIsICJ0eXAiOiAidmMrc2Qtand0In0.eyJfc2QiOiBbIjA5dktySk1PbHlUV00wc2pwdV9wZE9CVkJRMk0xeTNLaHBINTE1blhrcFkiLCAiMnJzakdiYUMwa3k4bVQwcEpyUGlvV1RxMF9kYXcxc1g3NnBvVWxnQ3diSSIsICJFa084ZGhXMGRIRUpidlVIbEVfVkNldUM5dVJFTE9pZUxaaGg3WGJVVHRBIiwgIklsRHpJS2VpWmREd3BxcEs2WmZieXBoRnZ6NUZnbldhLXNONndxUVhDaXciLCAiSnpZakg0c3ZsaUgwUjNQeUVNZmVadTZKdDY5dTVxZWhabzdGN0VQWWxTRSIsICJQb3JGYnBLdVZ1Nnh5bUphZ3ZrRnNGWEFiUm9jMkpHbEFVQTJCQTRvN2NJIiwgIlRHZjRvTGJnd2Q1SlFhSHlLVlFaVTlVZEdFMHc1cnREc3JaemZVYW9tTG8iLCAiamRyVEU4WWNiWTRFaWZ1Z2loaUFlX0JQZWt4SlFaSUNlaVVRd1k5UXF4SSIsICJqc3U5eVZ1bHdRUWxoRmxNXzNKbHpNYVNGemdsaFFHMERwZmF5UXdMVUs0Il0sICJpc3MiOiAiaHR0cHM6Ly9leGFtcGxlLmNvbS9pc3N1ZXIiLCAiaWF0IjogMTY4MzAwMDAwMCwgImV4cCI6IDE4ODMwMDAwMDAsICJkY3QiOiAiaHR0cHM6Ly9jcmVkZW50aWFscy5leGFtcGxlLmNvbS9pZGVudGl0eV9jcmVkZW50aWFsIiwgIl9zZF9hbGciOiAic2hhLTI1NiIsICJjbmYiOiB7Imp3ayI6IHsia3R5IjogIkVDIiwgImNydiI6ICJQLTI1NiIsICJ4IjogIlRDQUVSMTladnUzT0hGNGo0VzR2ZlNWb0hJUDFJTGlsRGxzN3ZDZUdlbWMiLCAieSI6ICJaeGppV1diWk1RR0hWV0tWUTRoYlNJaXJzVmZ1ZWNDRTZ0NGpUOUYySFpRIn19fQ.b036DutqQ72WszrCq0GuqZnbws3MApQyzA41I5DSJmenUfsADtqW8FbI_N04FP1wZDF_JtV6a6Ke3Z7apkoTLA~WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3IiwgImdpdmVuX25hbWUiLCAiSm9obiJd~WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwgImZhbWlseV9uYW1lIiwgIkRvZSJd~WyI2SWo3dE0tYTVpVlBHYm9TNXRtdlZBIiwgImVtYWlsIiwgImpvaG5kb2VAZXhhbXBsZS5jb20iXQ~WyJlSThaV205UW5LUHBOUGVOZW5IZGhRIiwgInBob25lX251bWJlciIsICIrMS0yMDItNTU1LTAxMDEiXQ~WyJRZ19PNjR6cUF4ZTQxMmExMDhpcm9BIiwgImFkZHJlc3MiLCB7InN0cmVldF9hZGRyZXNzIjogIjEyMyBNYWluIFN0IiwgImxvY2FsaXR5IjogIkFueXRvd24iLCAicmVnaW9uIjogIkFueXN0YXRlIiwgImNvdW50cnkiOiAiVVMifV0~WyJBSngtMDk1VlBycFR0TjRRTU9xUk9BIiwgImJpcnRoZGF0ZSIsICIxOTQwLTAxLTAxIl0~WyJQYzMzSk0yTGNoY1VfbEhnZ3ZfdWZRIiwgImlzX292ZXJfMTgiLCB0cnVlXQ~WyJHMDJOU3JRZmpGWFE3SW8wOXN5YWpBIiwgImlzX292ZXJfMjEiLCB0cnVlXQ~WyJsa2x4RjVqTVlsR1RQVW92TU5JdkNBIiwgImlzX292ZXJfNjUiLCB0cnVlXQ~";
const decodedObject = await sdjwt.decode(data);
console.log(decodedObject);

Expand Down
2 changes: 1 addition & 1 deletion examples/core-example/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const generateSalt = (length: number): string => {

export const digest = async (
data: string,
algorithm: string = 'SHA-256',
algorithm = 'SHA-256',
): Promise<Uint8Array> => {
const nodeAlg = toNodeCryptoAlg(algorithm);
const hash = Crypto.createHash(nodeAlg);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class SDJwtInstance {
return jwt.verify(this.userConfig.verifier);
}

public async issue<Payload extends object>(
public async issue<Payload extends Record<string, unknown>>(
payload: Payload,
disclosureFrame?: DisclosureFrame<Payload>,
options?: {
Expand Down
16 changes: 8 additions & 8 deletions packages/core/src/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Base64urlString, Signer, Verifier } from '@sd-jwt/types';
import { decodeJwt } from '@sd-jwt/decode';

export type JwtData<
Header extends Record<string, any>,
Payload extends Record<string, any>,
Header extends Record<string, unknown>,
Payload extends Record<string, unknown>,
> = {
header?: Header;
payload?: Payload;
Expand All @@ -14,8 +14,8 @@ export type JwtData<
// This class is used to create and verify JWT
// Contains header, payload, and signature
export class Jwt<
Header extends Record<string, any> = Record<string, any>,
Payload extends Record<string, any> = Record<string, any>,
Header extends Record<string, unknown> = Record<string, unknown>,
Payload extends Record<string, unknown> = Record<string, unknown>,
> {
public header?: Header;
public payload?: Payload;
Expand All @@ -28,17 +28,17 @@ export class Jwt<
}

public static decodeJWT<
Header extends Record<string, any> = Record<string, any>,
Payload extends Record<string, any> = Record<string, any>,
Header extends Record<string, unknown> = Record<string, unknown>,
Payload extends Record<string, unknown> = Record<string, unknown>,
>(
jwt: string,
): { header: Header; payload: Payload; signature: Base64urlString } {
return decodeJwt(jwt);
}

public static fromEncode<
Header extends Record<string, any> = Record<string, any>,
Payload extends Record<string, any> = Record<string, any>,
Header extends Record<string, unknown> = Record<string, unknown>,
Payload extends Record<string, unknown> = Record<string, unknown>,
>(encodedJwt: string): Jwt<Header, Payload> {
const { header, payload, signature } = Jwt.decodeJWT<Header, Payload>(
encodedJwt,
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/kbjwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ export class KBJwt<
!this.payload?.aud ||
!this.payload?.nonce ||
// this is for backward compatibility with version 06
!(this.payload?.sd_hash || (this.payload as any)?._sd_hash)
!(
this.payload?.sd_hash ||
(this.payload as Record<string, unknown> | undefined)?._sd_hash
)
) {
throw new SDJWTException('Invalid Key Binding Jwt');
}
Expand Down
56 changes: 32 additions & 24 deletions packages/core/src/sdjwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ import {
import { createHashMapping, getSDAlgAndPayload, unpack } from '@sd-jwt/decode';

export type SDJwtData<
Header extends Record<string, any>,
Payload extends Record<string, any>,
Header extends Record<string, unknown>,
Payload extends Record<string, unknown>,
KBHeader extends kbHeader = kbHeader,
KBPayload extends kbPayload = kbPayload,
> = {
jwt?: Jwt<Header, Payload>;
disclosures?: Array<Disclosure<any>>;
disclosures?: Array<Disclosure>;
kbJwt?: KBJwt<KBHeader, KBPayload>;
};

export class SDJwt<
Header extends Record<string, any> = Record<string, any>,
Payload extends Record<string, any> = Record<string, any>,
Header extends Record<string, unknown> = Record<string, unknown>,
Payload extends Record<string, unknown> = Record<string, unknown>,
KBHeader extends kbHeader = kbHeader,
KBPayload extends kbPayload = kbPayload,
> {
public jwt?: Jwt<Header, Payload>;
public disclosures?: Array<Disclosure<any>>;
public disclosures?: Array<Disclosure>;
public kbJwt?: KBJwt<KBHeader, KBPayload>;

constructor(data?: SDJwtData<Header, Payload, KBHeader, KBPayload>) {
Expand All @@ -45,21 +45,25 @@ export class SDJwt<
}

public static async decodeSDJwt<
Header extends Record<string, any> = Record<string, any>,
Payload extends Record<string, any> = Record<string, any>,
Header extends Record<string, unknown> = Record<string, unknown>,
Payload extends Record<string, unknown> = Record<string, unknown>,
KBHeader extends kbHeader = kbHeader,
KBPayload extends kbPayload = kbPayload,
>(
sdjwt: SDJWTCompact,
hasher: Hasher,
): Promise<{
jwt: Jwt<Header, Payload>;
disclosures: Array<Disclosure<any>>;
disclosures: Array<Disclosure>;
kbJwt?: KBJwt<KBHeader, KBPayload>;
}> {
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
const jwt = Jwt.fromEncode<Header, Payload>(encodedJwt);

if (!jwt.payload) {
throw new Error('Payload is undefined on the JWT. Invalid state reached');
}

if (encodedDisclosures.length === 0) {
return {
jwt,
Expand All @@ -75,7 +79,7 @@ export class SDJwt<
const { _sd_alg } = getSDAlgAndPayload(jwt.payload);

const disclosures = await Promise.all(
encodedDisclosures.map((ed) =>
(encodedDisclosures as Array<string>).map((ed) =>
Disclosure.fromEncode(ed, { alg: _sd_alg, hasher }),
),
);
Expand All @@ -88,8 +92,8 @@ export class SDJwt<
}

public static async fromEncode<
Header extends Record<string, any> = Record<string, any>,
Payload extends Record<string, any> = Record<string, any>,
Header extends Record<string, unknown> = Record<string, unknown>,
Payload extends Record<string, unknown> = Record<string, unknown>,
KBHeader extends kbHeader = kbHeader,
KBPayload extends kbPayload = kbPayload,
>(
Expand Down Expand Up @@ -190,26 +194,29 @@ export class SDJwt<
}
}

export const listKeys = (obj: any, prefix = '') => {
export const listKeys = (obj: Record<string, unknown>, prefix = '') => {
const keys: string[] = [];
for (const key in obj) {
if (obj[key] === undefined) continue;
const newKey = prefix ? `${prefix}.${key}` : key;
keys.push(newKey);

if (obj[key] && typeof obj[key] === 'object' && obj[key] !== null) {
keys.push(...listKeys(obj[key], newKey));
keys.push(...listKeys(obj[key] as Record<string, unknown>, newKey));
}
}
return keys;
};

export const pack = async <T extends object>(
export const pack = async <T extends Record<string, unknown>>(
claims: T,
disclosureFrame: DisclosureFrame<T> | undefined,
hash: HasherAndAlg,
saltGenerator: SaltGenerator,
): Promise<{ packedClaims: any; disclosures: Array<Disclosure<any>> }> => {
): Promise<{
packedClaims: Record<string, unknown> | Array<Record<string, unknown>>;
disclosures: Array<Disclosure>;
}> => {
if (!disclosureFrame) {
return {
packedClaims: claims,
Expand All @@ -221,16 +228,15 @@ export const pack = async <T extends object>(
const decoyCount = disclosureFrame[SD_DECOY] ?? 0;

if (Array.isArray(claims)) {
const packedClaims: any[] = [];
const disclosures: any[] = [];
const recursivePackedClaims: any = {};
const packedClaims: Array<Record<typeof SD_LIST_KEY, string>> = [];
const disclosures: Array<Disclosure> = [];
const recursivePackedClaims: Record<number, unknown> = {};

for (const key in disclosureFrame) {
if (key !== SD_DIGEST) {
const idx = parseInt(key);
const packed = await pack(
claims[idx],
// @ts-ignore
disclosureFrame[idx],
hash,
saltGenerator,
Expand All @@ -240,10 +246,11 @@ export const pack = async <T extends object>(
}
}

for (let i = 0; i < (claims as any[]).length; i++) {
for (let i = 0; i < claims.length; i++) {
const claim = recursivePackedClaims[i]
? recursivePackedClaims[i]
: claims[i];
// TODO: should this actually be the `i` or `claim`?
// @ts-ignore
if (sd.includes(i)) {
const salt = await saltGenerator(16);
Expand All @@ -262,9 +269,10 @@ export const pack = async <T extends object>(
return { packedClaims, disclosures };
}

const packedClaims: any = {};
const disclosures: any[] = [];
const recursivePackedClaims: any = {};
const packedClaims: Record<string, unknown> = {};
const disclosures: Array<Disclosure> = [];
const recursivePackedClaims: Record<string, unknown> = {};

for (const key in disclosureFrame) {
if (key !== SD_DIGEST) {
const packed = await pack(
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/test/kbjwt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ describe('KB JWT', () => {
},
});

(kbJwt.payload as any)._sd_hash = 'hash';
(kbJwt.payload as any).sd_hash = undefined;
(kbJwt.payload as Record<string, unknown>)._sd_hash = 'hash';
(kbJwt.payload as Record<string, unknown>).sd_hash = undefined;

const encodedKbJwt = await kbJwt.sign(testSigner);
const decoded = KBJwt.fromKBEncode(encodedKbJwt);
Expand Down
Loading

0 comments on commit 30ba30b

Please sign in to comment.