@sd-jwt/present
Advanced tools
Comparing version 0.4.0 to 0.4.1-next.2
@@ -16,3 +16,19 @@ import { Hasher, PresentationFrame } from '@sd-jwt/types'; | ||
declare const transformPresentationFrame: <T extends object>(obj: PresentationFrame<T>, prefix?: string) => string[]; | ||
type SerializedDisclosure = { | ||
digest: string; | ||
encoded: string; | ||
salt: string; | ||
key: string | undefined; | ||
value: unknown; | ||
}; | ||
/** | ||
* This function selects the serialized disclosures from the payload | ||
* and array of serialized disclosure based on the presentation frame. | ||
* If you want to know what is serialized disclosures, check type SerializedDisclosure. | ||
* @param payload: Record<string, unknown> | ||
* @param disclosures: SerializedDisclosure[] | ||
* @param presentationFrame: PresentationFrame<T> | ||
*/ | ||
declare const selectDisclosures: <T extends Record<string, unknown>>(payload: Record<string, unknown>, disclosures: SerializedDisclosure[], presentationFrame: PresentationFrame<T>) => SerializedDisclosure[]; | ||
export { present, presentSync, presentableKeys, presentableKeysSync, transformPresentationFrame }; | ||
export { type SerializedDisclosure, present, presentSync, presentableKeys, presentableKeysSync, selectDisclosures, transformPresentationFrame }; |
@@ -47,2 +47,3 @@ "use strict"; | ||
presentableKeysSync: () => presentableKeysSync, | ||
selectDisclosures: () => selectDisclosures, | ||
transformPresentationFrame: () => transformPresentationFrame | ||
@@ -54,2 +55,3 @@ }); | ||
var import_types = require("@sd-jwt/types"); | ||
var import_utils = require("@sd-jwt/utils"); | ||
var import_decode = require("@sd-jwt/decode"); | ||
@@ -116,2 +118,41 @@ var presentableKeys = (rawPayload, disclosures, hasher) => __async(void 0, null, function* () { | ||
}; | ||
var createHashMappingForSerializedDisclosure = (disclosures) => { | ||
const map = {}; | ||
for (let i = 0; i < disclosures.length; i++) { | ||
const disclosure = disclosures[i]; | ||
const { digest, encoded, key, salt, value } = disclosure; | ||
map[digest] = import_utils.Disclosure.fromArray( | ||
key ? [salt, key, value] : [salt, value], | ||
{ digest, encoded } | ||
); | ||
} | ||
return map; | ||
}; | ||
var selectDisclosures = (payload, disclosures, presentationFrame) => { | ||
if (disclosures.length === 0) { | ||
return []; | ||
} | ||
const hashmap = createHashMappingForSerializedDisclosure(disclosures); | ||
const { disclosureKeymap } = (0, import_decode.unpackObj)(payload, hashmap); | ||
const keys = transformPresentationFrame(presentationFrame); | ||
const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0); | ||
const selectedDisclosures = presentedDisclosures.map( | ||
(d) => { | ||
const { salt, key, value, _digest } = d; | ||
if (!_digest) { | ||
throw new import_utils.SDJWTException( | ||
"Implementation error: _digest is not defined" | ||
); | ||
} | ||
return { | ||
digest: _digest, | ||
encoded: d.encode(), | ||
salt, | ||
key, | ||
value | ||
}; | ||
} | ||
); | ||
return selectedDisclosures; | ||
}; | ||
// Annotate the CommonJS export names for ESM import in node: | ||
@@ -123,3 +164,4 @@ 0 && (module.exports = { | ||
presentableKeysSync, | ||
selectDisclosures, | ||
transformPresentationFrame | ||
}); |
{ | ||
"name": "@sd-jwt/present", | ||
"version": "0.4.0", | ||
"version": "0.4.1-next.2+b11bedf", | ||
"description": "sd-jwt draft 7 implementation in typescript", | ||
@@ -41,8 +41,8 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@sd-jwt/crypto-nodejs": "0.4.0" | ||
"@sd-jwt/crypto-nodejs": "0.4.1-next.2+b11bedf" | ||
}, | ||
"dependencies": { | ||
"@sd-jwt/decode": "0.4.0", | ||
"@sd-jwt/types": "0.4.0", | ||
"@sd-jwt/utils": "0.4.0" | ||
"@sd-jwt/decode": "0.4.1-next.2+b11bedf", | ||
"@sd-jwt/types": "0.4.1-next.2+b11bedf", | ||
"@sd-jwt/utils": "0.4.1-next.2+b11bedf" | ||
}, | ||
@@ -65,3 +65,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "391a36550a66833b3d393ff0deb699b1b72cca59" | ||
"gitHead": "b11bedfe62dd1827653a76226ebdca3e0da1bbe0" | ||
} |
@@ -1,4 +0,8 @@ | ||
import { Hasher, PresentationFrame, SD_SEPARATOR } from '@sd-jwt/types'; | ||
import { Disclosure } from '@sd-jwt/utils'; | ||
import { | ||
type Hasher, | ||
type PresentationFrame, | ||
SD_SEPARATOR, | ||
} from '@sd-jwt/types'; | ||
import { Disclosure, SDJWTException } from '@sd-jwt/utils'; | ||
import { | ||
createHashMapping, | ||
@@ -12,4 +16,5 @@ decodeSdJwt, | ||
unpackSync, | ||
unpackObj, | ||
} from '@sd-jwt/decode'; | ||
import { HasherSync } from '@sd-jwt/types/src/type'; | ||
import type { HasherSync } from '@sd-jwt/types/src/type'; | ||
@@ -138,1 +143,71 @@ // Presentable keys | ||
}; | ||
export type SerializedDisclosure = { | ||
digest: string; | ||
encoded: string; | ||
salt: string; | ||
key: string | undefined; | ||
value: unknown; | ||
}; | ||
const createHashMappingForSerializedDisclosure = ( | ||
disclosures: SerializedDisclosure[], | ||
) => { | ||
const map: Record<string, Disclosure> = {}; | ||
for (let i = 0; i < disclosures.length; i++) { | ||
const disclosure = disclosures[i]; | ||
const { digest, encoded, key, salt, value } = disclosure; | ||
// we made Disclosure to fit the interface of unpack | ||
map[digest] = Disclosure.fromArray( | ||
key ? [salt, key, value] : [salt, value], | ||
{ digest, encoded }, | ||
); | ||
} | ||
return map; | ||
}; | ||
/** | ||
* This function selects the serialized disclosures from the payload | ||
* and array of serialized disclosure based on the presentation frame. | ||
* If you want to know what is serialized disclosures, check type SerializedDisclosure. | ||
* @param payload: Record<string, unknown> | ||
* @param disclosures: SerializedDisclosure[] | ||
* @param presentationFrame: PresentationFrame<T> | ||
*/ | ||
export const selectDisclosures = <T extends Record<string, unknown>>( | ||
payload: Record<string, unknown>, | ||
disclosures: SerializedDisclosure[], | ||
presentationFrame: PresentationFrame<T>, | ||
) => { | ||
if (disclosures.length === 0) { | ||
return []; | ||
} | ||
const hashmap = createHashMappingForSerializedDisclosure(disclosures); | ||
const { disclosureKeymap } = unpackObj(payload, hashmap); | ||
const keys = transformPresentationFrame(presentationFrame); | ||
const presentedDisclosures = keys | ||
.map((k) => hashmap[disclosureKeymap[k]]) | ||
.filter((d) => d !== undefined); | ||
const selectedDisclosures: SerializedDisclosure[] = presentedDisclosures.map( | ||
(d) => { | ||
const { salt, key, value, _digest } = d; | ||
if (!_digest) { | ||
throw new SDJWTException( | ||
'Implementation error: _digest is not defined', | ||
); | ||
} | ||
return { | ||
digest: _digest, | ||
encoded: d.encode(), | ||
salt, | ||
key, | ||
value, | ||
}; | ||
}, | ||
); | ||
return selectedDisclosures; | ||
}; |
import { describe, expect, test } from 'vitest'; | ||
import { digest } from '@sd-jwt/crypto-nodejs'; | ||
import { | ||
type SerializedDisclosure, | ||
present, | ||
@@ -8,6 +9,7 @@ presentSync, | ||
presentableKeysSync, | ||
selectDisclosures, | ||
transformPresentationFrame, | ||
} from '../index'; | ||
import { decodeSdJwt, decodeSdJwtSync } from '@sd-jwt/decode'; | ||
import { PresentationFrame } from '@sd-jwt/types'; | ||
import type { PresentationFrame } from '@sd-jwt/types'; | ||
@@ -153,2 +155,153 @@ describe('Present tests', () => { | ||
}); | ||
test('select disclosures', () => { | ||
const payload = { | ||
lastname: 'Doe', | ||
_sd: [ | ||
'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU', | ||
'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4', | ||
'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14', | ||
], | ||
_sd_alg: 'SHA-256', | ||
}; | ||
const presentationFrame = { | ||
firstname: true, | ||
//ssn: true, | ||
id: true, | ||
}; | ||
const disclosures: SerializedDisclosure[] = [ | ||
{ | ||
digest: 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU', | ||
encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd', | ||
salt: 'b04760b9810823fa', | ||
key: 'firstname', | ||
value: 'John', | ||
}, | ||
{ | ||
digest: 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4', | ||
encoded: 'WyJjNTQwZWE4YjJhOTNmZDE1Iiwic3NuIiwiMTIzLTQ1LTY3ODkiXQ', | ||
salt: 'c540ea8b2a93fd15', | ||
key: 'ssn', | ||
value: '123-45-6789', | ||
}, | ||
{ | ||
digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14', | ||
encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0', | ||
salt: '97f055de944af729', | ||
key: 'id', | ||
value: '1234', | ||
}, | ||
]; | ||
const selected = selectDisclosures(payload, disclosures, presentationFrame); | ||
expect(selected).toStrictEqual([ | ||
{ | ||
digest: 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU', | ||
encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd', | ||
salt: 'b04760b9810823fa', | ||
key: 'firstname', | ||
value: 'John', | ||
}, | ||
{ | ||
digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14', | ||
encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0', | ||
salt: '97f055de944af729', | ||
key: 'id', | ||
value: '1234', | ||
}, | ||
]); | ||
}); | ||
test('select disclosures no input', () => { | ||
const selected = selectDisclosures({}, [], {}); | ||
expect(selected).toStrictEqual([]); | ||
}); | ||
test('select disclosures noting return', () => { | ||
const payload = { | ||
lastname: 'Doe', | ||
_sd: [ | ||
'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU', | ||
'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4', | ||
'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14', | ||
], | ||
_sd_alg: 'SHA-256', | ||
}; | ||
const presentationFrame = {}; | ||
const disclosures: SerializedDisclosure[] = [ | ||
{ | ||
digest: 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU', | ||
encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd', | ||
salt: 'b04760b9810823fa', | ||
key: 'firstname', | ||
value: 'John', | ||
}, | ||
{ | ||
digest: 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4', | ||
encoded: 'WyJjNTQwZWE4YjJhOTNmZDE1Iiwic3NuIiwiMTIzLTQ1LTY3ODkiXQ', | ||
salt: 'c540ea8b2a93fd15', | ||
key: 'ssn', | ||
value: '123-45-6789', | ||
}, | ||
{ | ||
digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14', | ||
encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0', | ||
salt: '97f055de944af729', | ||
key: 'id', | ||
value: '1234', | ||
}, | ||
]; | ||
const selected = selectDisclosures(payload, disclosures, presentationFrame); | ||
expect(selected).toStrictEqual([]); | ||
}); | ||
test('expect missing digest', () => { | ||
const payload = { | ||
lastname: 'Doe', | ||
_sd: [ | ||
'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU', | ||
'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4', | ||
'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14', | ||
], | ||
_sd_alg: 'SHA-256', | ||
}; | ||
const presentationFrame = { | ||
firstname: true, | ||
//ssn: true, | ||
id: true, | ||
}; | ||
const disclosures: SerializedDisclosure[] = [ | ||
//@ts-ignore | ||
{ | ||
encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd', | ||
salt: 'b04760b9810823fa', | ||
key: 'firstname', | ||
value: 'John', | ||
}, | ||
{ | ||
digest: 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4', | ||
encoded: 'WyJjNTQwZWE4YjJhOTNmZDE1Iiwic3NuIiwiMTIzLTQ1LTY3ODkiXQ', | ||
salt: 'c540ea8b2a93fd15', | ||
key: 'ssn', | ||
value: '123-45-6789', | ||
}, | ||
{ | ||
digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14', | ||
encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0', | ||
salt: '97f055de944af729', | ||
key: 'id', | ||
value: '1234', | ||
}, | ||
]; | ||
expect(() => | ||
selectDisclosures(payload, disclosures, presentationFrame), | ||
).toThrowError('Implementation error: _digest is not defined'); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
47151
831
1
- Removed@sd-jwt/decode@0.4.0(transitive)
- Removed@sd-jwt/types@0.4.0(transitive)
- Removed@sd-jwt/utils@0.4.0(transitive)
- Removedjs-base64@3.7.7(transitive)