@credo-ts/core 0.7.1-pr-2945-20260917131913 → 0.7.1

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.
@@ -30,7 +30,7 @@ declare class CredoWalletWebCrypto {
30
30
  modulusLength?: undefined;
31
31
  } | {
32
32
  kty: "RSA";
33
- modulusLength: 2048 | 3072 | 4096;
33
+ modulusLength: 4096 | 3072 | 2048;
34
34
  crv?: undefined;
35
35
  }>>;
36
36
  importKey(format: KeyFormat, keyData: Uint8Array | JsonWebKey, algorithm: KeyImportParams, extractable: boolean, keyUsages: Array<KeyUsage>): Promise<CredoWebCryptoKey>;
@@ -125,7 +125,7 @@ function getClaimsBelow(value, disclosuresByDigest) {
125
125
  const claims = [];
126
126
  value.forEach((item, frameKey) => {
127
127
  const digest = isObject(item) ? item[SD_LIST_KEY] : void 0;
128
- if (typeof digest !== "string") {
128
+ if (digest === void 0) {
129
129
  claims.push({
130
130
  key: claims.length,
131
131
  frameKey,
@@ -152,10 +152,9 @@ function getClaimsBelow(value, disclosuresByDigest) {
152
152
  })), ...(digests ?? []).flatMap((digest) => {
153
153
  const disclosure = disclosuresByDigest[digest];
154
154
  if (!disclosure?.key) return [];
155
- const key = String(disclosure.key);
156
155
  return [{
157
- key,
158
- frameKey: key,
156
+ key: disclosure.key,
157
+ frameKey: disclosure.key,
159
158
  value: disclosure.value,
160
159
  digest
161
160
  }];
@@ -1 +1 @@
1
- {"version":3,"file":"disclosureFrame.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/disclosureFrame.ts"],"sourcesContent":["import {\n createHashMappingSync,\n decodeSdJwtSync,\n getClaimsSync,\n getSDAlgAndPayload,\n SD_DIGEST,\n SD_LIST_KEY,\n selectDisclosures,\n} from '@sd-jwt/core'\nimport { isObject } from 'class-validator'\nimport { Hasher } from '../../crypto'\nimport type { JsonObject } from '../../types'\nimport { SdJwtVcError } from './SdJwtVcError'\n\ntype DisclosureFrame = {\n [key: string]: boolean | DisclosureFrame\n}\n\n/**\n * @deprecated use `buildPresentationFrameForPaths` instead\n */\nexport function buildDisclosureFrameForPayload(input: JsonObject): DisclosureFrame {\n return Object.fromEntries(\n Object.entries(input).map(([key, value]) => {\n // TODO: Array disclosure frames are not yet supported - treating entire array as disclosed\n if (Array.isArray(value)) {\n return [key, true]\n }\n if (isObject(value)) {\n if (Object.keys.length === 0) return [key, false]\n return [key, buildDisclosureFrameForPayload(value)]\n }\n return [key, true]\n })\n )\n}\n\n/**\n * @deprecated use `applyDisclosuresForPaths` instead\n */\nexport function applyDisclosuresForPayload(compactSdJwt: string, requestedPayload: JsonObject) {\n const decoded = decodeSdJwtSync(compactSdJwt, Hasher.hash)\n const presentationFrame = buildDisclosureFrameForPayload(requestedPayload) ?? {}\n\n if (decoded.kbJwt) {\n throw new SdJwtVcError('Cannot apply limit disclosure on an sd-jwt with key binding jwt')\n }\n\n const requiredDisclosures = selectDisclosures(\n decoded.jwt.payload,\n // Map to sd-jwt disclosure format\n decoded.disclosures.map((d) => ({\n digest: d.digestSync({ alg: 'sha-256', hasher: Hasher.hash }),\n encoded: d.encode(),\n key: d.key,\n salt: d.salt,\n value: d.value,\n })),\n presentationFrame as { [key: string]: boolean }\n )\n const [jwt] = compactSdJwt.split('~')\n const disclosuresString =\n requiredDisclosures.length > 0 ? `${requiredDisclosures.map((d) => d.encoded).join('~')}~` : ''\n const sdJwt = `${jwt}~${disclosuresString}`\n return sdJwt\n}\n\n/**\n * The path to a claim, with property names for objects and element positions for arrays.\n *\n * An element has the position it has in the claims of the SD-JWT, as DCQL gives it. Decoy digests in an\n * array are not elements, and have no position.\n *\n * A path stands for the claim and everything below it, as a claims path does in DCQL.\n */\nexport type ClaimPath = Array<string | number>\n\n/**\n * The paths to the claims a DCQL claim set selects, from the paths of its claims queries and its output.\n *\n * A claims query path stands for the claim and everything below it, so it gives a single path however\n * much is below the claim. A `null` in the path selects the array elements that matched, which are the\n * ones the output holds: for an element that did not match, DCQL leaves `null` in the output of a claims\n * query, and `undefined` or nothing in the output of a claim set.\n *\n * The output of a claim set merges the output of its claims queries, so an element can be in it for\n * another claims query of the claim set. Its path is then selected by that claims query anyway.\n */\nexport function getClaimPathsForDcqlClaimSet(\n claimsQueryPaths: Array<Array<string | number | null>>,\n output: unknown\n): ClaimPath[] {\n const getPaths = (queryPath: Array<string | number | null>, value: unknown, path: ClaimPath): ClaimPath[] => {\n // FIXME: logic should be updated once this PR is released:\n // https://github.com/openwallet-foundation-labs/identity-common-ts/pull/261\n // DCQL leaves `null`, `undefined` or nothing where no claim is selected\n if (value === null || value === undefined) return []\n // The end of the query path selects the claim with everything below it\n if (queryPath.length === 0) return [path]\n\n const [pathElement, ...rest] = queryPath\n\n // `null` goes into every element of an array, and a position into one\n if (pathElement === null || typeof pathElement === 'number') {\n if (!Array.isArray(value)) return []\n if (pathElement !== null) return getPaths(rest, value[pathElement], [...path, pathElement])\n return value.flatMap((item, index) => getPaths(rest, item, [...path, index]))\n }\n\n // A property name goes into the claim of an object\n if (!isObject(value)) return []\n return getPaths(rest, (value as Record<string, unknown>)[pathElement], [...path, pathElement])\n }\n\n return claimsQueryPaths.flatMap((queryPath) => getPaths(queryPath, output, []))\n}\n\n/**\n * Builds the presentation frame that discloses the claims at the given paths of an SD-JWT, including\n * everything below them.\n *\n * Unlike {@link buildDisclosureFrameForPayload}, array elements are selected by their position, so an\n * element that is selectively disclosable on its own is disclosed when a path selects it, and only then.\n */\nexport function buildPresentationFrameForPaths(compactSdJwt: string, paths: ClaimPath[]): DisclosureFrame {\n const { payload, disclosuresByDigest } = decodeForPaths(compactSdJwt)\n // Only the frame is needed, the digests are for applyDisclosuresForPaths\n return selectClaimsAtPaths(payload, disclosuresByDigest, paths).frame\n}\n\n/**\n * Discloses the claims at the given paths of an SD-JWT, including everything below them.\n *\n * Besides the compact SD-JWT holding only the disclosures for those claims, returns what it discloses:\n * - `prettyClaims`, the claims as a verifier receives them.\n * - `disclosedPaths`, the paths to the claims it discloses. These are not only the given paths: a\n * claim that is not selectively disclosable is always disclosed. A claim that is disclosed with\n * everything below it has a single path, so a path only goes deeper where something below it is not\n * disclosed. And unlike in the pretty claims, where an element that is not disclosed is left out,\n * an array element has the position it has in the credential.\n */\nexport function applyDisclosuresForPaths(\n compactSdJwt: string,\n paths: ClaimPath[]\n): { compact: string; prettyClaims: JsonObject; disclosedPaths: ClaimPath[] } {\n const { signedPayload, payload, disclosures, disclosuresByDigest, hasher } = decodeForPaths(compactSdJwt)\n // Find the digests of the disclosures needed for the paths\n const { digests } = selectClaimsAtPaths(payload, disclosuresByDigest, paths)\n\n // Keep only those disclosures, in the order of the SD-JWT\n const selectedDisclosures = disclosures.filter((disclosure) => digests.has(disclosure.digestSync(hasher)))\n const [jwt] = compactSdJwt.split('~')\n\n // Before getClaimsSync, which replaces the `_sd` in the values of nested disclosures with their claims\n const disclosedPaths = getDisclosedClaimPaths(payload, disclosuresByDigest, digests)\n\n // Rebuild the SD-JWT and its claims from the selected disclosures\n return {\n compact: `${jwt}~${selectedDisclosures.map((disclosure) => `${disclosure.encode()}~`).join('')}`,\n prettyClaims: getClaimsSync(signedPayload, selectedDisclosures, Hasher.hash) as JsonObject,\n disclosedPaths,\n }\n}\n\nfunction decodeForPaths(compactSdJwt: string) {\n const decoded = decodeSdJwtSync(compactSdJwt, Hasher.hash)\n\n if (decoded.kbJwt) {\n throw new SdJwtVcError('Cannot apply limit disclosure on an sd-jwt with key binding jwt')\n }\n\n // Split off `_sd_alg`, so it is not taken for a claim\n const { _sd_alg: alg, payload } = getSDAlgAndPayload(decoded.jwt.payload)\n const hasher = { alg, hasher: Hasher.hash }\n\n return {\n // With `_sd_alg`, which the functions of @sd-jwt/core read the hash algorithm from\n signedPayload: decoded.jwt.payload,\n payload,\n hasher,\n disclosures: decoded.disclosures,\n // To look up the disclosure for a digest in the payload\n disclosuresByDigest: createHashMappingSync(decoded.disclosures, hasher),\n }\n}\n\ntype DisclosuresByDigest = ReturnType<typeof createHashMappingSync>\n\n/**\n * A claim directly below a value of a signed SD-JWT payload.\n *\n * `key` is the property name or element position of the claim, and `frameKey` the one to use in a\n * presentation frame. These differ for an array element after a decoy digest: its position leaves out\n * the decoys, as in the claims of the SD-JWT, while @sd-jwt/core counts them in a presentation frame.\n */\ninterface ClaimBelow {\n key: string | number\n frameKey: string | number\n value: unknown\n // The digest of the disclosure, for a selectively disclosable claim\n digest?: string\n}\n\n/**\n * The claims directly below a value of a signed SD-JWT payload, or `undefined` for a value that is not\n * an object or array. A digest without a disclosure is a decoy, and not a claim.\n */\nfunction getClaimsBelow(value: unknown, disclosuresByDigest: DisclosuresByDigest): ClaimBelow[] | undefined {\n if (Array.isArray(value)) {\n const claims: ClaimBelow[] = []\n\n // `frameKey` counts every element, `key` (the length so far) only the claims\n value.forEach((item, frameKey) => {\n // As in @sd-jwt/core, an element is only a digest when it is an object with a string under `...`\n const digest = isObject(item) ? (item as Record<string, unknown>)[SD_LIST_KEY] : undefined\n // A plain element is a claim that is always disclosed\n if (typeof digest !== 'string') {\n claims.push({ key: claims.length, frameKey, value: item })\n return\n }\n\n // A digest is a selectively disclosable element, or a decoy when it has no disclosure\n const disclosure = disclosuresByDigest[digest]\n if (disclosure) claims.push({ key: claims.length, frameKey, value: disclosure.value, digest })\n })\n\n return claims\n }\n\n if (isObject(value)) {\n const { [SD_DIGEST]: digests, ...claims } = value as Record<string, unknown>\n\n return [\n // The properties next to `_sd` are always disclosed\n ...Object.entries(claims).map(([key, claim]) => ({ key, frameKey: key, value: claim })),\n // The digests in `_sd` are selectively disclosable properties, or decoys when they have no disclosure\n ...((digests as string[] | undefined) ?? []).flatMap((digest) => {\n const disclosure = disclosuresByDigest[digest]\n if (!disclosure?.key) return []\n\n // A property name is a string, as in the claims, even in a disclosure that gives it as another value\n const key = String(disclosure.key)\n return [{ key, frameKey: key, value: disclosure.value, digest }]\n }),\n ]\n }\n\n return undefined\n}\n\n/**\n * The disclosures, and the presentation frame, for the claims at the given paths and everything below\n * them. A selectively disclosable claim on the way to a path is disclosed as well, as the claim below\n * it is not reachable otherwise, but only when there is a claim at the path.\n */\nfunction selectClaimsAtPaths(payload: unknown, disclosuresByDigest: DisclosuresByDigest, paths: ClaimPath[]) {\n // A path as a string, to look it up in a set. A position stays a number, so it only selects an array element\n const toKey = (path: ClaimPath) => JSON.stringify(path)\n // The claims at the paths, which are disclosed with everything below them\n const selectedPaths = new Set(paths.map(toKey))\n // The claims above the paths, which are disclosed when there is a claim at a path below them\n const pathsOnTheWay = new Set(\n paths.flatMap((path) => path.slice(0, -1).map((_, index) => toKey(path.slice(0, index + 1))))\n )\n\n // Collects the digests of the disclosures to present, while building the frame\n const digests = new Set<string>()\n\n // The frame for the claims below a value, or `undefined` for a value that is not an object or array\n const select = (value: unknown, path: ClaimPath, isSelected: boolean): DisclosureFrame | undefined => {\n const claims = getClaimsBelow(value, disclosuresByDigest)\n // A value that is not an object or array has no frame, it is disclosed as `true`\n if (!claims) return undefined\n\n const frame: DisclosureFrame = {}\n\n for (const claim of claims) {\n const claimPath = [...path, claim.key]\n // A claim is selected when it is at a path, or below a selected claim\n const isClaimSelected = isSelected || selectedPaths.has(toKey(claimPath))\n // Skip claims that are neither selected nor on the way to a path\n if (!isClaimSelected && !pathsOnTheWay.has(toKey(claimPath))) continue\n\n // Go down first, to know whether a claim on the way leads to a claim at a path\n const claimFrame = select(claim.value, claimPath, isClaimSelected)\n // Nothing below a claim on the way is selected when there is no claim at the path\n if (!isClaimSelected && (!claimFrame || Object.keys(claimFrame).length === 0)) continue\n\n // Disclose the claim, and add it to the frame under the key @sd-jwt/core uses\n if (claim.digest) digests.add(claim.digest)\n frame[String(claim.frameKey)] = claimFrame ?? true\n }\n\n return frame\n }\n\n // An empty path selects the whole payload\n return { frame: select(payload, [], false) ?? {}, digests }\n}\n\n/**\n * The shortest paths to the claims of a signed SD-JWT payload that the given disclosures disclose: a\n * claim that is disclosed with everything below it has a single path. An object or array none of whose\n * claims is disclosed has no path.\n */\nfunction getDisclosedClaimPaths(\n payload: unknown,\n disclosuresByDigest: DisclosuresByDigest,\n disclosedDigests: Set<string>\n): ClaimPath[] {\n const getDisclosed = (value: unknown, path: ClaimPath): { paths: ClaimPath[]; isComplete: boolean } => {\n const claims = getClaimsBelow(value, disclosuresByDigest)\n // A value that is not an object or array is disclosed as a whole\n if (!claims) return { paths: [path], isComplete: true }\n\n // Go down into the claims that are disclosed: always, or by one of the digests\n const disclosed = claims\n .filter((claim) => !claim.digest || disclosedDigests.has(claim.digest))\n .map((claim) => getDisclosed(claim.value, [...path, claim.key]))\n\n // Complete when every claim below is disclosed, with everything below it\n const isComplete = disclosed.length === claims.length && disclosed.every((claim) => claim.isComplete)\n // A complete claim has a single path, except the payload, which has a path per claim\n if (isComplete && path.length > 0) return { paths: [path], isComplete }\n\n // Otherwise the paths of the disclosed claims below\n return { paths: disclosed.flatMap((claim) => claim.paths), isComplete }\n }\n\n return getDisclosed(payload, []).paths\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"disclosureFrame.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/disclosureFrame.ts"],"sourcesContent":["import {\n createHashMappingSync,\n decodeSdJwtSync,\n getClaimsSync,\n getSDAlgAndPayload,\n SD_DIGEST,\n SD_LIST_KEY,\n selectDisclosures,\n} from '@sd-jwt/core'\nimport { isObject } from 'class-validator'\nimport { Hasher } from '../../crypto'\nimport type { JsonObject } from '../../types'\nimport { SdJwtVcError } from './SdJwtVcError'\n\ntype DisclosureFrame = {\n [key: string]: boolean | DisclosureFrame\n}\n\n/**\n * @deprecated use `buildPresentationFrameForPaths` instead\n */\nexport function buildDisclosureFrameForPayload(input: JsonObject): DisclosureFrame {\n return Object.fromEntries(\n Object.entries(input).map(([key, value]) => {\n // TODO: Array disclosure frames are not yet supported - treating entire array as disclosed\n if (Array.isArray(value)) {\n return [key, true]\n }\n if (isObject(value)) {\n if (Object.keys.length === 0) return [key, false]\n return [key, buildDisclosureFrameForPayload(value)]\n }\n return [key, true]\n })\n )\n}\n\n/**\n * @deprecated use `applyDisclosuresForPaths` instead\n */\nexport function applyDisclosuresForPayload(compactSdJwt: string, requestedPayload: JsonObject) {\n const decoded = decodeSdJwtSync(compactSdJwt, Hasher.hash)\n const presentationFrame = buildDisclosureFrameForPayload(requestedPayload) ?? {}\n\n if (decoded.kbJwt) {\n throw new SdJwtVcError('Cannot apply limit disclosure on an sd-jwt with key binding jwt')\n }\n\n const requiredDisclosures = selectDisclosures(\n decoded.jwt.payload,\n // Map to sd-jwt disclosure format\n decoded.disclosures.map((d) => ({\n digest: d.digestSync({ alg: 'sha-256', hasher: Hasher.hash }),\n encoded: d.encode(),\n key: d.key,\n salt: d.salt,\n value: d.value,\n })),\n presentationFrame as { [key: string]: boolean }\n )\n const [jwt] = compactSdJwt.split('~')\n const disclosuresString =\n requiredDisclosures.length > 0 ? `${requiredDisclosures.map((d) => d.encoded).join('~')}~` : ''\n const sdJwt = `${jwt}~${disclosuresString}`\n return sdJwt\n}\n\n/**\n * The path to a claim, with property names for objects and element positions for arrays.\n *\n * An element has the position it has in the claims of the SD-JWT, as DCQL gives it. Decoy digests in an\n * array are not elements, and have no position.\n *\n * A path stands for the claim and everything below it, as a claims path does in DCQL.\n */\nexport type ClaimPath = Array<string | number>\n\n/**\n * The paths to the claims a DCQL claim set selects, from the paths of its claims queries and its output.\n *\n * A claims query path stands for the claim and everything below it, so it gives a single path however\n * much is below the claim. A `null` in the path selects the array elements that matched, which are the\n * ones the output holds: for an element that did not match, DCQL leaves `null` in the output of a claims\n * query, and `undefined` or nothing in the output of a claim set.\n *\n * The output of a claim set merges the output of its claims queries, so an element can be in it for\n * another claims query of the claim set. Its path is then selected by that claims query anyway.\n */\nexport function getClaimPathsForDcqlClaimSet(\n claimsQueryPaths: Array<Array<string | number | null>>,\n output: unknown\n): ClaimPath[] {\n const getPaths = (queryPath: Array<string | number | null>, value: unknown, path: ClaimPath): ClaimPath[] => {\n // FIXME: logic should be updated once this PR is released:\n // https://github.com/openwallet-foundation-labs/identity-common-ts/pull/261\n // DCQL leaves `null`, `undefined` or nothing where no claim is selected\n if (value === null || value === undefined) return []\n // The end of the query path selects the claim with everything below it\n if (queryPath.length === 0) return [path]\n\n const [pathElement, ...rest] = queryPath\n\n // `null` goes into every element of an array, and a position into one\n if (pathElement === null || typeof pathElement === 'number') {\n if (!Array.isArray(value)) return []\n if (pathElement !== null) return getPaths(rest, value[pathElement], [...path, pathElement])\n return value.flatMap((item, index) => getPaths(rest, item, [...path, index]))\n }\n\n // A property name goes into the claim of an object\n if (!isObject(value)) return []\n return getPaths(rest, (value as Record<string, unknown>)[pathElement], [...path, pathElement])\n }\n\n return claimsQueryPaths.flatMap((queryPath) => getPaths(queryPath, output, []))\n}\n\n/**\n * Builds the presentation frame that discloses the claims at the given paths of an SD-JWT, including\n * everything below them.\n *\n * Unlike {@link buildDisclosureFrameForPayload}, array elements are selected by their position, so an\n * element that is selectively disclosable on its own is disclosed when a path selects it, and only then.\n */\nexport function buildPresentationFrameForPaths(compactSdJwt: string, paths: ClaimPath[]): DisclosureFrame {\n const { payload, disclosuresByDigest } = decodeForPaths(compactSdJwt)\n // Only the frame is needed, the digests are for applyDisclosuresForPaths\n return selectClaimsAtPaths(payload, disclosuresByDigest, paths).frame\n}\n\n/**\n * Discloses the claims at the given paths of an SD-JWT, including everything below them.\n *\n * Besides the compact SD-JWT holding only the disclosures for those claims, returns what it discloses:\n * - `prettyClaims`, the claims as a verifier receives them.\n * - `disclosedPaths`, the paths to the claims it discloses. These are not only the given paths: a\n * claim that is not selectively disclosable is always disclosed. A claim that is disclosed with\n * everything below it has a single path, so a path only goes deeper where something below it is not\n * disclosed. And unlike in the pretty claims, where an element that is not disclosed is left out,\n * an array element has the position it has in the credential.\n */\nexport function applyDisclosuresForPaths(\n compactSdJwt: string,\n paths: ClaimPath[]\n): { compact: string; prettyClaims: JsonObject; disclosedPaths: ClaimPath[] } {\n const { signedPayload, payload, disclosures, disclosuresByDigest, hasher } = decodeForPaths(compactSdJwt)\n // Find the digests of the disclosures needed for the paths\n const { digests } = selectClaimsAtPaths(payload, disclosuresByDigest, paths)\n\n // Keep only those disclosures, in the order of the SD-JWT\n const selectedDisclosures = disclosures.filter((disclosure) => digests.has(disclosure.digestSync(hasher)))\n const [jwt] = compactSdJwt.split('~')\n\n // Before getClaimsSync, which replaces the `_sd` in the values of nested disclosures with their claims\n const disclosedPaths = getDisclosedClaimPaths(payload, disclosuresByDigest, digests)\n\n // Rebuild the SD-JWT and its claims from the selected disclosures\n return {\n compact: `${jwt}~${selectedDisclosures.map((disclosure) => `${disclosure.encode()}~`).join('')}`,\n prettyClaims: getClaimsSync(signedPayload, selectedDisclosures, Hasher.hash) as JsonObject,\n disclosedPaths,\n }\n}\n\nfunction decodeForPaths(compactSdJwt: string) {\n const decoded = decodeSdJwtSync(compactSdJwt, Hasher.hash)\n\n if (decoded.kbJwt) {\n throw new SdJwtVcError('Cannot apply limit disclosure on an sd-jwt with key binding jwt')\n }\n\n // Split off `_sd_alg`, so it is not taken for a claim\n const { _sd_alg: alg, payload } = getSDAlgAndPayload(decoded.jwt.payload)\n const hasher = { alg, hasher: Hasher.hash }\n\n return {\n // With `_sd_alg`, which the functions of @sd-jwt/core read the hash algorithm from\n signedPayload: decoded.jwt.payload,\n payload,\n hasher,\n disclosures: decoded.disclosures,\n // To look up the disclosure for a digest in the payload\n disclosuresByDigest: createHashMappingSync(decoded.disclosures, hasher),\n }\n}\n\ntype DisclosuresByDigest = ReturnType<typeof createHashMappingSync>\n\n/**\n * A claim directly below a value of a signed SD-JWT payload.\n *\n * `key` is the property name or element position of the claim, and `frameKey` the one to use in a\n * presentation frame. These differ for an array element after a decoy digest: its position leaves out\n * the decoys, as in the claims of the SD-JWT, while @sd-jwt/core counts them in a presentation frame.\n */\ninterface ClaimBelow {\n key: string | number\n frameKey: string | number\n value: unknown\n // The digest of the disclosure, for a selectively disclosable claim\n digest?: string\n}\n\n/**\n * The claims directly below a value of a signed SD-JWT payload, or `undefined` for a value that is not\n * an object or array. A digest without a disclosure is a decoy, and not a claim.\n */\nfunction getClaimsBelow(value: unknown, disclosuresByDigest: DisclosuresByDigest): ClaimBelow[] | undefined {\n if (Array.isArray(value)) {\n const claims: ClaimBelow[] = []\n\n // `frameKey` counts every element, `key` (the length so far) only the claims\n value.forEach((item, frameKey) => {\n // An element is a digest when it is an object with `...`, which @sd-jwt/core checks is a string\n const digest = isObject(item) ? (item as Record<string, string | undefined>)[SD_LIST_KEY] : undefined\n // A plain element is a claim that is always disclosed\n if (digest === undefined) {\n claims.push({ key: claims.length, frameKey, value: item })\n return\n }\n\n // A digest is a selectively disclosable element, or a decoy when it has no disclosure\n const disclosure = disclosuresByDigest[digest]\n if (disclosure) claims.push({ key: claims.length, frameKey, value: disclosure.value, digest })\n })\n\n return claims\n }\n\n if (isObject(value)) {\n const { [SD_DIGEST]: digests, ...claims } = value as Record<string, unknown>\n\n return [\n // The properties next to `_sd` are always disclosed\n ...Object.entries(claims).map(([key, claim]) => ({ key, frameKey: key, value: claim })),\n // The digests in `_sd` are selectively disclosable properties, or decoys when they have no disclosure\n ...((digests as string[] | undefined) ?? []).flatMap((digest) => {\n const disclosure = disclosuresByDigest[digest]\n if (!disclosure?.key) return []\n\n return [{ key: disclosure.key, frameKey: disclosure.key, value: disclosure.value, digest }]\n }),\n ]\n }\n\n return undefined\n}\n\n/**\n * The disclosures, and the presentation frame, for the claims at the given paths and everything below\n * them. A selectively disclosable claim on the way to a path is disclosed as well, as the claim below\n * it is not reachable otherwise, but only when there is a claim at the path.\n */\nfunction selectClaimsAtPaths(payload: unknown, disclosuresByDigest: DisclosuresByDigest, paths: ClaimPath[]) {\n // A path as a string, to look it up in a set. A position stays a number, so it only selects an array element\n const toKey = (path: ClaimPath) => JSON.stringify(path)\n // The claims at the paths, which are disclosed with everything below them\n const selectedPaths = new Set(paths.map(toKey))\n // The claims above the paths, which are disclosed when there is a claim at a path below them\n const pathsOnTheWay = new Set(\n paths.flatMap((path) => path.slice(0, -1).map((_, index) => toKey(path.slice(0, index + 1))))\n )\n\n // Collects the digests of the disclosures to present, while building the frame\n const digests = new Set<string>()\n\n // The frame for the claims below a value, or `undefined` for a value that is not an object or array\n const select = (value: unknown, path: ClaimPath, isSelected: boolean): DisclosureFrame | undefined => {\n const claims = getClaimsBelow(value, disclosuresByDigest)\n // A value that is not an object or array has no frame, it is disclosed as `true`\n if (!claims) return undefined\n\n const frame: DisclosureFrame = {}\n\n for (const claim of claims) {\n const claimPath = [...path, claim.key]\n // A claim is selected when it is at a path, or below a selected claim\n const isClaimSelected = isSelected || selectedPaths.has(toKey(claimPath))\n // Skip claims that are neither selected nor on the way to a path\n if (!isClaimSelected && !pathsOnTheWay.has(toKey(claimPath))) continue\n\n // Go down first, to know whether a claim on the way leads to a claim at a path\n const claimFrame = select(claim.value, claimPath, isClaimSelected)\n // Nothing below a claim on the way is selected when there is no claim at the path\n if (!isClaimSelected && (!claimFrame || Object.keys(claimFrame).length === 0)) continue\n\n // Disclose the claim, and add it to the frame under the key @sd-jwt/core uses\n if (claim.digest) digests.add(claim.digest)\n frame[String(claim.frameKey)] = claimFrame ?? true\n }\n\n return frame\n }\n\n // An empty path selects the whole payload\n return { frame: select(payload, [], false) ?? {}, digests }\n}\n\n/**\n * The shortest paths to the claims of a signed SD-JWT payload that the given disclosures disclose: a\n * claim that is disclosed with everything below it has a single path. An object or array none of whose\n * claims is disclosed has no path.\n */\nfunction getDisclosedClaimPaths(\n payload: unknown,\n disclosuresByDigest: DisclosuresByDigest,\n disclosedDigests: Set<string>\n): ClaimPath[] {\n const getDisclosed = (value: unknown, path: ClaimPath): { paths: ClaimPath[]; isComplete: boolean } => {\n const claims = getClaimsBelow(value, disclosuresByDigest)\n // A value that is not an object or array is disclosed as a whole\n if (!claims) return { paths: [path], isComplete: true }\n\n // Go down into the claims that are disclosed: always, or by one of the digests\n const disclosed = claims\n .filter((claim) => !claim.digest || disclosedDigests.has(claim.digest))\n .map((claim) => getDisclosed(claim.value, [...path, claim.key]))\n\n // Complete when every claim below is disclosed, with everything below it\n const isComplete = disclosed.length === claims.length && disclosed.every((claim) => claim.isComplete)\n // A complete claim has a single path, except the payload, which has a path per claim\n if (isComplete && path.length > 0) return { paths: [path], isComplete }\n\n // Otherwise the paths of the disclosed claims below\n return { paths: disclosed.flatMap((claim) => claim.paths), isComplete }\n }\n\n return getDisclosed(payload, []).paths\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "types": "./build/modules/kms/index.d.mts"
10
10
  }
11
11
  },
12
- "version": "0.7.1-pr-2945-20260917131913",
12
+ "version": "0.7.1",
13
13
  "files": [
14
14
  "build"
15
15
  ],