diff --git a/plugin/dist/main.js b/plugin/dist/main.js
index 344f1bf..93d2faa 100644
--- a/plugin/dist/main.js
+++ b/plugin/dist/main.js
@@ -16,7 +16,7 @@
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ processCombinedExample: () => (/* binding */ processCombinedExample),\n/* harmony export */ processCoseExample: () => (/* binding */ processCoseExample),\n/* harmony export */ processJwtExample: () => (/* binding */ processJwtExample),\n/* harmony export */ processSdJwtExample: () => (/* binding */ processSdJwtExample)\n/* harmony export */ });\n/* harmony import */ var _src_getHtml__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/getHtml */ \"./src/getHtml.js\");\n/* harmony import */ var _src_exampleKey__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./src/exampleKey */ \"./src/exampleKey.js\");\n/* harmony import */ var _src_exampleCose__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./src/exampleCose */ \"./src/exampleCose.js\");\n/* harmony import */ var _src_exampleJwt__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./src/exampleJwt */ \"./src/exampleJwt.js\");\n/* harmony import */ var _src_exampleSdJwt__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./src/exampleSdJwt */ \"./src/exampleSdJwt.js\");\n\n\n\n\n\n\nasync function processVcJoseCose() {\n // add styling for examples\n addVcJoseStyles();\n\n // handle full vc-jose-cose examples\n const examples = Array.from(document.querySelectorAll(\".vc-jose-cose\")).filter((e) => !!e.innerText)\n for (const index in examples) {\n const example = examples[index]\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''))\n const processedData = await processCombinedExample(index, json);\n example.outerHTML = processedData.html\n }\n\n // handle jwt examples\n const jwtExamples = Array.from(document.querySelectorAll(\".vc-jose-cose-jwt\")).filter((e) => !!e.innerText)\n for (const index in jwtExamples) {\n const example = jwtExamples[index]\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''))\n const processedData = await processJwtExample(index, json);\n example.outerHTML = processedData.html\n }\n\n // handle sd-jwt examples\n const sdJwtExamples = Array.from(document.querySelectorAll(\".vc-jose-cose-sd-jwt\")).filter((e) => !!e.innerText)\n for (const index in sdJwtExamples) {\n const example = sdJwtExamples[index]\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''))\n const processedData = await processSdJwtExample(index, json);\n example.outerHTML = processedData.html\n }\n\n // handle cose examples\n const coseExamples = Array.from(document.querySelectorAll(\".vc-jose-cose-cose\")).filter((e) => !!e.innerText)\n for (const index in coseExamples) {\n const example = coseExamples[index]\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''))\n const processedData = await processCoseExample(index, json);\n example.outerHTML = processedData.html\n }\n}\n\nfunction addVcJoseStyles() {\n const styles = document.createElement('style');\n\n styles.innerHTML += `\n .vc-jose-cose-tabbed, .vc-jose-cose-tabbed-jwt, .vc-jose-cose-tabbed-sd-jwt, .vc-jose-cose-tabbed-cose {\n overflow-x: hidden;\n margin: 0 0;\n}\n\n.vc-jose-cose-tabbed h1, .vc-jose-cose-jwt-tabbed h1, .vc-jose-cose-sd-jwt-tabbed h1, .vc-jose-cose-cose-tabbed h1 {\n font-size: 1em;\n margin: 0 0;\n}\n\n.vc-jose-cose-tabbed [type=\"radio\"], .vc-jose-cose-tabbed-jwt [type=\"radio\"], .vc-jose-cose-tabbed-sd-jwt [type=\"radio\"], .vc-jose-cose-tabbed-cose [type=\"radio\"] {\n display: none;\n}\n\n.vc-jose-cose-tabs, .vc-jose-cose-jwt-tabs, .vc-jose-cose-sd-jwt-tabs, .vc-jose-cose-cose-tabs {\n display: flex;\n align-items: stretch;\n list-style: none;\n padding: 0;\n border-bottom: 1px solid #ccc;\n}\n\nli.vc-jose-cose-tab, li.vc-jose-cose-jwt-tab, li.vc-jose-cose-sd-jwt-tab, li.vc-jose-cose-cose-tab {\n margin: 0 0;\n margin-left: 8px;\n}\n\n.vc-jose-cose-tab>label, .vc-jose-cose-jwt-tab>label, .vc-jose-cose-sd-jwt-tab>label, .vc-jose-cose-cose-tab>label {\n display: block;\n margin-bottom: -1px;\n padding: .4em .5em;\n border: 1px solid #ccc;\n border-top-right-radius: .4em;\n border-top-left-radius: .4em;\n background: #eee;\n color: #666;\n cursor: pointer;\n transition: all 0.3s;\n}\n\n.vc-jose-cose-tab:hover label, .vc-jose-cose-jwt-tab:hover label, .vc-jose-cose-sd-jwt-tab:hover label, .vc-jose-cose-cose-tab:hover label {\n border-left-color: #333;\n border-top-color: #333;\n border-right-color: #333;\n color: #333;\n}\n\n.vc-jose-cose-tab-content {\n display: none;\n}\n\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(1):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(1) label,\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(2):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(2) label,\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(3):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(3) label {\n border-bottom-color: #fff;\n background: #fff;\n color: #222;\n}\n\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(1):checked~.vc-jose-cose-tab-content:nth-of-type(1),\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(2):checked~.vc-jose-cose-tab-content:nth-of-type(2),\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(3):checked~.vc-jose-cose-tab-content:nth-of-type(3) {\n display: block;\n}\n\n.sd-jwt-header, .jwt-header, .vc-jose-cose-jwt .header, .vc-jose-cose-sd-jwt .header, .vc-jose-cose-cose .header {\n color: red;\n}\n\n.sd-jwt-payload, .jwt-payload, .vc-jose-cose-jwt .payload, .vc-jose-cose-sd-jwt .payload, .vc-jose-cose-cose .payload {\n color: green;\n}\n\n.sd-jwt-signature, .jwt-signature, .vc-jose-cose-jwt .signature, .vc-jose-cose-sd-jwt .signature, .vc-jose-cose-cose .signature {\n color: blue;\n}\n\n.sd-jwt-disclosure, .vc-jose-cose-jwt .disclosure, .vc-jose-cose-sd-jwt .disclosure, .vc-jose-cose-cose .disclosure {\n color: purple;\n}\n\n.sd-jwt-compact, .jwt-compact, .vc-jose-cose-jwt .compact, .vc-jose-cose-sd-jwt .compact, .vc-jose-cose-cose .compact {\n background-color: rgba(0,0,0,.03);\n}\n\n.cose-text, .jose-text, .vc-jose-cose-jwt .text, .vc-jose-cose-sd-jwt .text, .vc-jose-cose-cose .text {\n font-family: monospace;\n color: green;\n}`;\n\n document.head.appendChild(styles);\n}\n\nasync function processCombinedExample(index, json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const coseExample = await (0,_src_exampleCose__WEBPACK_IMPORTED_MODULE_2__.getCoseExample)(privateKey, json);\n const jwtExample = await (0,_src_exampleJwt__WEBPACK_IMPORTED_MODULE_3__.getJwtExample)(privateKey, json);\n const sdJwtExample = await (0,_src_exampleSdJwt__WEBPACK_IMPORTED_MODULE_4__.getSdJwtExample)(privateKey, json);\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getCombinedHtml)({index, coseExample, jwtExample, sdJwtExample});\n return {html};\n}\n\nasync function processJwtExample(index, json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const jwtExample = await (0,_src_exampleJwt__WEBPACK_IMPORTED_MODULE_3__.getJwtExample)(privateKey, json);\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getJwtHtml)({index, jwtExample});\n return {html};\n}\n\nasync function processSdJwtExample(index, json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const sdJwtExample = await (0,_src_exampleSdJwt__WEBPACK_IMPORTED_MODULE_4__.getSdJwtExample)(privateKey, json);\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getSdJwtHtml)({index, sdJwtExample});\n return {html};\n}\n\nasync function processCoseExample(index, json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const coseExample = await (0,_src_exampleCose__WEBPACK_IMPORTED_MODULE_2__.getCoseExample)(privateKey, json);\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getCoseHtml)({index, coseExample});\n return {html};\n}\n\nwindow.respecVcJoseCose = {\n processVcJoseCose\n}\n\n\n//# sourceURL=webpack://respec-vc-jose-cose/./index.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ processCombinedExample: () => (/* binding */ processCombinedExample),\n/* harmony export */ processCoseExample: () => (/* binding */ processCoseExample),\n/* harmony export */ processJwtExample: () => (/* binding */ processJwtExample),\n/* harmony export */ processSdJwtExample: () => (/* binding */ processSdJwtExample)\n/* harmony export */ });\n/* harmony import */ var _src_getHtml__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/getHtml */ \"./src/getHtml.js\");\n/* harmony import */ var _src_exampleKey__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./src/exampleKey */ \"./src/exampleKey.js\");\n/* harmony import */ var _src_exampleCose__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./src/exampleCose */ \"./src/exampleCose.js\");\n/* harmony import */ var _src_exampleJwt__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./src/exampleJwt */ \"./src/exampleJwt.js\");\n/* harmony import */ var _src_exampleSdJwt__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./src/exampleSdJwt */ \"./src/exampleSdJwt.js\");\n\n\n\n\n\n\nasync function processVcJoseCose() {\n addVcJoseStyles();\n\n const examples = Array.from(document.querySelectorAll(\".vc-jose-cose\")).filter((e) => !!e.innerText);\n for (const index in examples) {\n const example = examples[index];\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''));\n const processedData = await processCombinedExample(index, json);\n example.outerHTML = processedData.html;\n }\n\n const jwtExamples = Array.from(document.querySelectorAll(\".vc-jose-cose-jwt\")).filter((e) => !!e.innerText);\n for (const index in jwtExamples) {\n const example = jwtExamples[index];\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''));\n const processedData = await processJwtExample(json);\n example.outerHTML = processedData.html;\n }\n\n const sdJwtExamples = Array.from(document.querySelectorAll(\".vc-jose-cose-sd-jwt\")).filter((e) => !!e.innerText);\n for (const index in sdJwtExamples) {\n const example = sdJwtExamples[index];\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''));\n const processedData = await processSdJwtExample(index, json);\n example.outerHTML = processedData.html;\n }\n\n const coseExamples = Array.from(document.querySelectorAll(\".vc-jose-cose-cose\")).filter((e) => !!e.innerText);\n for (const index in coseExamples) {\n const example = coseExamples[index];\n const json = JSON.parse(example.innerText.replace(/\\/\\/ .*$/gm, ''));\n const processedData = await processCoseExample(json);\n example.outerHTML = processedData.html;\n }\n}\n\nasync function processCombinedExample(index, json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const coseExample = await (0,_src_exampleCose__WEBPACK_IMPORTED_MODULE_2__.getCoseExample)(privateKey, json);\n const jwtExample = await (0,_src_exampleJwt__WEBPACK_IMPORTED_MODULE_3__.getJwtExample)(privateKey, json);\n const sdJwtExample = await (0,_src_exampleSdJwt__WEBPACK_IMPORTED_MODULE_4__.getSdJwtExample)(index, privateKey, json, 'combined');\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getCombinedHtml)({ index, coseExample, jwtExample, sdJwtExample });\n return { html };\n}\n\nasync function processJwtExample(json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const jwtExample = await (0,_src_exampleJwt__WEBPACK_IMPORTED_MODULE_3__.getJwtExample)(privateKey, json);\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getJwtHtml)({ jwtExample });\n return { html };\n}\n\nasync function processSdJwtExample(index, json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const sdJwtExample = await (0,_src_exampleSdJwt__WEBPACK_IMPORTED_MODULE_4__.getSdJwtExample)(index, privateKey, json, 'standalone');\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getSdJwtHtml)({ sdJwtExample });\n return { html };\n}\n\nasync function processCoseExample(json) {\n const privateKey = await (0,_src_exampleKey__WEBPACK_IMPORTED_MODULE_1__.getPrivateKey)();\n const coseExample = await (0,_src_exampleCose__WEBPACK_IMPORTED_MODULE_2__.getCoseExample)(privateKey, json);\n const html = (0,_src_getHtml__WEBPACK_IMPORTED_MODULE_0__.getCoseHtml)({ coseExample });\n return { html };\n}\n\nfunction addVcJoseStyles() {\n const styles = document.createElement('style');\n styles.innerHTML = `\n .vc-jose-cose-tabbed, .vc-jose-cose-tabbed-jwt, .vc-jose-cose-tabbed-sd-jwt, .vc-jose-cose-tabbed-cose,\n .sd-jwt-tabbed {\n overflow-x: hidden;\n margin: 0 0;\n}\n.vc-jose-cose-tabbed h1, .vc-jose-cose-jwt-tabbed h1, .vc-jose-cose-sd-jwt-tabbed h1, .vc-jose-cose-cose-tabbed h1,\n.sd-jwt-tabbed h1 {\n font-size: 1em;\n margin: 0 0;\n}\n.vc-jose-cose-tabbed [type=\"radio\"], .vc-jose-cose-tabbed-jwt [type=\"radio\"], .vc-jose-cose-tabbed-sd-jwt [type=\"radio\"], .vc-jose-cose-tabbed-cose [type=\"radio\"],\n.sd-jwt-tabbed [type=\"radio\"] {\n display: none;\n}\n.vc-jose-cose-tabs, .vc-jose-cose-jwt-tabs, .vc-jose-cose-sd-jwt-tabs, .vc-jose-cose-cose-tabs,\n.sd-jwt-tabs {\n display: flex;\n align-items: stretch;\n list-style: none;\n padding: 0;\n border-bottom: 1px solid #ccc;\n}\nli.vc-jose-cose-tab, li.vc-jose-cose-jwt-tab, li.vc-jose-cose-sd-jwt-tab, li.vc-jose-cose-cose-tab,\nli.sd-jwt-tab {\n margin: 0 0;\n margin-left: 8px;\n}\n.vc-jose-cose-tab>label, .vc-jose-cose-jwt-tab>label, .vc-jose-cose-sd-jwt-tab>label, .vc-jose-cose-cose-tab>label,\n.sd-jwt-tab>label {\n display: block;\n margin-bottom: -1px;\n padding: .4em .5em;\n border: 1px solid #ccc;\n border-top-right-radius: .4em;\n border-top-left-radius: .4em;\n background: #eee;\n color: #666;\n cursor: pointer;\n transition: all 0.3s;\n}\n.vc-jose-cose-tab:hover label, .vc-jose-cose-jwt-tab:hover label, .vc-jose-cose-sd-jwt-tab:hover label, .vc-jose-cose-cose-tab:hover label,\n.sd-jwt-tab:hover label {\n border-left-color: #333;\n border-top-color: #333;\n border-right-color: #333;\n color: #333;\n}\n.vc-jose-cose-tab-content,\n.sd-jwt-tab-content {\n display: none;\n}\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(1):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(1) label,\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(2):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(2) label,\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(3):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(3) label,\n.sd-jwt-tabbed [type=\"radio\"]:nth-of-type(1):checked~.sd-jwt-tabs .sd-jwt-tab:nth-of-type(1) label,\n.sd-jwt-tabbed [type=\"radio\"]:nth-of-type(2):checked~.sd-jwt-tabs .sd-jwt-tab:nth-of-type(2) label,\n.sd-jwt-tabbed [type=\"radio\"]:nth-of-type(3):checked~.sd-jwt-tabs .sd-jwt-tab:nth-of-type(3) label {\n border-bottom-color: #fff;\n background: #fff;\n color: #222;\n}\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(1):checked~.vc-jose-cose-tab-content:nth-of-type(1),\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(2):checked~.vc-jose-cose-tab-content:nth-of-type(2),\n.vc-jose-cose-tabbed [type=\"radio\"]:nth-of-type(3):checked~.vc-jose-cose-tab-content:nth-of-type(3),\n.sd-jwt-tabbed [type=\"radio\"]:nth-of-type(1):checked~.sd-jwt-tab-content:nth-of-type(1),\n.sd-jwt-tabbed [type=\"radio\"]:nth-of-type(2):checked~.sd-jwt-tab-content:nth-of-type(2),\n.sd-jwt-tabbed [type=\"radio\"]:nth-of-type(3):checked~.sd-jwt-tab-content:nth-of-type(3) {\n display: block;\n}\n.sd-jwt-header, .jwt-header, .vc-jose-cose-jwt .header, .vc-jose-cose-sd-jwt .header, .vc-jose-cose-cose .header {\n color: red;\n}\n.sd-jwt-payload, .jwt-payload, .vc-jose-cose-jwt .payload, .vc-jose-cose-sd-jwt .payload, .vc-jose-cose-cose .payload {\n color: green;\n}\n.sd-jwt-signature, .jwt-signature, .vc-jose-cose-jwt .signature, .vc-jose-cose-sd-jwt .signature, .vc-jose-cose-cose .signature {\n color: blue;\n}\n.sd-jwt-disclosure, .vc-jose-cose-jwt .disclosure, .vc-jose-cose-sd-jwt .disclosure, .vc-jose-cose-cose .disclosure {\n color: purple;\n}\n.sd-jwt-compact, .jwt-compact, .vc-jose-cose-jwt .compact, .vc-jose-cose-sd-jwt .compact, .vc-jose-cose-cose .compact {\n background-color: rgba(0,0,0,.03);\n}\n.cose-text, .jose-text, .vc-jose-cose-jwt .text, .vc-jose-cose-sd-jwt .text, .vc-jose-cose-cose .text {\n font-family: monospace;\n color: green;\n}\n.disclosure {\n margin: 10px 0;\n font-size: 12px;\n line-height: 1.6;\n padding: 5px;\n}\n.disclosure h3 {\n margin: 0;\n font-size: 14px;\n padding-left: 5px;\n}\n.disclosure .claim-name {\n color: #333;\n}\n.disclosure .hash,\n.disclosure .disclosure-value,\n.disclosure .contents {\n color: #555;\n word-wrap: break-word;\n display: inline;\n}\n.disclosure p {\n margin: 0;\n padding-left: 5px;\n}\n.disclosure pre {\n white-space: pre-wrap;\n word-wrap: break-word;\n margin: 0;\n padding-left: 5px;\n line-height: 1.6;\n display: inline-block;\n}\n.header-value {\n white-space: pre-wrap;\n word-wrap: break-word;\n margin: 0;\n padding-left: 5px;\n line-height: 1.6;\n font-size: 12px;\n}\n`;\n document.head.appendChild(styles);\n}\n\nwindow.respecVcJoseCose = {\n processVcJoseCose\n};\n\n\n//# sourceURL=webpack://respec-vc-jose-cose/./index.js?");
/***/ }),
@@ -7884,7 +7884,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ generateIssuerClaims: () => (/* binding */ generateIssuerClaims),\n/* harmony export */ getSdJwtExample: () => (/* binding */ getSdJwtExample)\n/* harmony export */ });\n/* harmony import */ var yaml__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! yaml */ \"./node_modules/yaml/browser/index.js\");\n/* harmony import */ var _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @transmute/verifiable-credentials */ \"./node_modules/@transmute/verifiable-credentials/dist/index.js\");\n/* harmony import */ var _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var jose__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! jose */ \"./node_modules/jose/dist/browser/index.js\");\n/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! crypto */ \"./node_modules/crypto-browserify/index.js\");\n\n\n\n\n\nconst calculateHash = (value) => {\n return _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.base64url.encode(crypto__WEBPACK_IMPORTED_MODULE_3__.createHash('sha256').update(value).digest());\n};\n\n// Custom JSON.stringify with prettier formatting\nconst customJSONStringify = (obj) => {\n return JSON.stringify(obj, null, 2).replace(/\\n/g, '
').replace(/\\s/g, ' ');\n};\n\nconst generateDisclosureHtml = (claimName, hash, disclosure, contents) => {\n return `\n
\n
Claim: ${claimName}
\n
SHA-256 Hash: ${hash}
\n
Disclosure(s): ${disclosure}
\n
Contents: ${customJSONStringify(contents)}
\n
\n`;\n};\n\nconst getSdHtml = (vc) => {\n const [token, ...disclosure] = vc.split('~');\n const [header, payload, signature] = token.split('.');\n const disclosures = disclosure.map((d) => {\n return `~${d}`;\n }).join('');\n return `\n.${payload}.${signature}${disclosures}
`;\n};\n\nconst getHeadersHtml = (vc) => {\n const [token] = vc.split('~');\n const [header] = token.split('.');\n const headerJson = JSON.parse(new TextDecoder().decode(_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.base64url.decode(header)));\n return ``;\n};\n\nconst getDisclosabilityHtml = async (vc) => {\n const [_, ...disclosures] = vc.split('~');\n const disclosureHtml = disclosures.map((disclosure) => {\n const decodedDisclosure = JSON.parse(new TextDecoder().decode(_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.base64url.decode(disclosure)));\n const [, ...claimPath] = decodedDisclosure;\n const claimName = claimPath.pop();\n const hash = calculateHash(disclosure);\n\n return generateDisclosureHtml(JSON.stringify(claimName), hash, disclosure, decodedDisclosure);\n });\n\n return `\n\n ${disclosureHtml.join('\\n')}\n
\n`;\n};\n\nconst generateIssuerClaims = (example) => {\n return yaml__WEBPACK_IMPORTED_MODULE_0__[\"default\"].stringify(example).replace(/id: /g, '!sd id: ').replace(/type:/g, '!sd type:');\n};\n\nconst getCredential = async (privateKey, byteSigner, messageType, messageJson) => {\n return await (0,_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.issuer)({\n alg: privateKey.alg,\n type: messageType,\n signer: byteSigner\n }).issue({\n claimset: new TextEncoder().encode(generateIssuerClaims(messageJson))\n });\n};\n\nconst getPresentation = async (privateKey, byteSigner, messageType, messageJson) => {\n return await getCredential(privateKey, byteSigner, 'application/vc+ld+json+sd-jwt', messageJson);\n};\n\nconst getBinaryMessage = async (privateKey, messageType, messageJson) => {\n const byteSigner = {\n sign: async (bytes) => {\n const jws = await new jose__WEBPACK_IMPORTED_MODULE_2__.CompactSign(bytes)\n .setProtectedHeader({ kid: privateKey.kid, alg: privateKey.alg })\n .sign(await _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.key.importKeyLike({\n type: 'application/jwk+json',\n content: new TextEncoder().encode(JSON.stringify(privateKey))\n }));\n return _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.text.encoder.encode(jws);\n }\n };\n switch (messageType) {\n case 'application/vc+ld+json+sd-jwt': {\n return getCredential(privateKey, byteSigner, messageType, messageJson);\n }\n case 'application/vp+ld+json+sd-jwt': {\n return getPresentation(privateKey, byteSigner, messageType, messageJson);\n }\n default: {\n throw new Error('Unknown message type');\n }\n }\n};\n\nconst getSdJwtExample = async (privateKey, messageJson) => {\n injectStyles();\n const type = Array.isArray(messageJson.type) ? messageJson.type : [messageJson.type];\n const messageType = type.includes('VerifiableCredential') ? 'application/vc+ld+json+sd-jwt' : 'application/vp+ld+json+sd-jwt';\n const message = await getBinaryMessage(privateKey, messageType, messageJson);\n const messageEncoded = new TextDecoder().decode(message);\n\n return `\nProtected Headers
\n\n${getHeadersHtml(messageEncoded)}\n
\n\nDisclosures
\n\n${await getDisclosabilityHtml(messageEncoded)}\n
\n\n${messageType}
\n\n${getSdHtml(messageEncoded)}\n
\n `.trim();\n};\n\nconst injectStyles = () => {\n const style = document.createElement('style');\n style.innerHTML = `\n .disclosure {\n margin: 10px 0;\n font-size: 12px;\n line-height: 1.6;\n padding: 5px;\n }\n .disclosure h3 {\n margin: 0;\n font-size: 14px;\n padding-left: 5px;\n }\n .disclosure .claim-name {\n color: #333;\n }\n .disclosure .hash,\n .disclosure .disclosure-value,\n .disclosure .contents {\n color: #555;\n word-wrap: break-word;\n display: inline;\n }\n .disclosure p {\n margin: 0;\n padding-left: 5px;\n }\n .disclosure pre {\n white-space: pre-wrap;\n word-wrap: break-word;\n margin: 0;\n padding-left: 5px;\n line-height: 1.6;\n display: inline-block;\n }\n .header-value {\n white-space: pre-wrap;\n word-wrap: break-word;\n margin: 0;\n padding-left: 5px;\n line-height: 1.6;\n font-size: 12px;\n }\n `;\n document.head.appendChild(style);\n};\n\n//# sourceURL=webpack://respec-vc-jose-cose/./src/exampleSdJwt.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ generateIssuerClaims: () => (/* binding */ generateIssuerClaims),\n/* harmony export */ getBinaryMessage: () => (/* binding */ getBinaryMessage),\n/* harmony export */ getSdJwtExample: () => (/* binding */ getSdJwtExample)\n/* harmony export */ });\n/* harmony import */ var yaml__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! yaml */ \"./node_modules/yaml/browser/index.js\");\n/* harmony import */ var _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @transmute/verifiable-credentials */ \"./node_modules/@transmute/verifiable-credentials/dist/index.js\");\n/* harmony import */ var _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var jose__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! jose */ \"./node_modules/jose/dist/browser/index.js\");\n/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! crypto */ \"./node_modules/crypto-browserify/index.js\");\n\n\n\n\n\nconst calculateHash = (value) => {\n return _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.base64url.encode(crypto__WEBPACK_IMPORTED_MODULE_3__.createHash('sha256').update(value).digest());\n};\n\nconst customJSONStringify = (obj) => {\n return JSON.stringify(obj, null, 2).replace(/\\n/g, '
').replace(/\\s/g, ' ');\n};\n\nconst generateDisclosureHtml = (claimName, hash, disclosure, contents) => {\n return `\n\n
Claim: ${claimName}
\n
SHA-256 Hash: ${hash}
\n
Disclosure(s): ${disclosure}
\n
Contents: ${customJSONStringify(contents)}
\n
\n`;\n};\n\nconst getSdHtml = (vc) => {\n const [token, ...disclosure] = vc.split('~');\n const [header, payload, signature] = token.split('.');\n const disclosures = disclosure.map((d) => {\n return `~${d}`;\n }).join('');\n return `\n.${payload}.${signature}${disclosures}
`;\n};\n\nconst getHeadersHtml = (vc) => {\n const [token] = vc.split('~');\n const [header] = token.split('.');\n const headerJson = JSON.parse(new TextDecoder().decode(_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.base64url.decode(header)));\n return ``;\n};\n\nconst getPayloadHtml = (vc) => {\n const [token] = vc.split('~');\n const [, payload] = token.split('.');\n const payloadJson = JSON.parse(new TextDecoder().decode(_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.base64url.decode(payload)));\n return ``;\n};\n\nconst getDisclosuresHtml = async (vc) => {\n const [_, ...disclosures] = vc.split('~');\n const disclosureHtml = disclosures.map((disclosure) => {\n const decodedDisclosure = JSON.parse(new TextDecoder().decode(_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.base64url.decode(disclosure)));\n const [, ...claimPath] = decodedDisclosure;\n const claimName = claimPath.pop();\n const hash = calculateHash(disclosure);\n\n return generateDisclosureHtml(JSON.stringify(claimName), hash, disclosure, decodedDisclosure);\n });\n\n return `${disclosureHtml.join('\\n')}
`;\n};\n\nconst generateIssuerClaims = (example) => {\n return yaml__WEBPACK_IMPORTED_MODULE_0__[\"default\"].stringify(example).replace(/id: /g, '!sd id: ').replace(/type:/g, '!sd type:');\n};\n\nconst getCredential = async (privateKey, byteSigner, messageType, messageJson) => {\n return await (0,_transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.issuer)({\n alg: privateKey.alg,\n type: messageType,\n signer: byteSigner\n }).issue({\n claimset: new TextEncoder().encode(generateIssuerClaims(messageJson))\n });\n};\n\nconst getPresentation = async (privateKey, byteSigner, messageType, messageJson) => {\n return await getCredential(privateKey, byteSigner, 'application/vc+ld+json+sd-jwt', messageJson);\n};\n\nconst getBinaryMessage = async (privateKey, messageType, messageJson) => {\n const byteSigner = {\n sign: async (bytes) => {\n const jws = await new jose__WEBPACK_IMPORTED_MODULE_2__.CompactSign(bytes)\n .setProtectedHeader({ kid: privateKey.kid, alg: privateKey.alg })\n .sign(await _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.key.importKeyLike({\n type: 'application/jwk+json',\n content: new TextEncoder().encode(JSON.stringify(privateKey))\n }));\n return _transmute_verifiable_credentials__WEBPACK_IMPORTED_MODULE_1__.text.encoder.encode(jws);\n }\n };\n switch (messageType) {\n case 'application/vc+ld+json+sd-jwt': {\n return getCredential(privateKey, byteSigner, messageType, messageJson);\n }\n case 'application/vp+ld+json+sd-jwt': {\n return getPresentation(privateKey, byteSigner, messageType, messageJson);\n }\n default: {\n throw new Error('Unknown message type');\n }\n }\n};\n\nconst getSdJwtExample = async (index, privateKey, messageJson, prefix = 'sd-jwt') => {\n const type = Array.isArray(messageJson.type) ? messageJson.type : [messageJson.type];\n const messageType = type.includes('VerifiableCredential') ? 'application/vc+ld+json+sd-jwt' : 'application/vp+ld+json+sd-jwt';\n const binaryMessage = await getBinaryMessage(privateKey, messageType, messageJson);\n const message = new TextDecoder().decode(binaryMessage);\n const encoded = getSdHtml(message);\n const header = getHeadersHtml(message);\n const payload = getPayloadHtml(message);\n const disclosures = await getDisclosuresHtml(message);\n return `\n\n
\n
\n
\n
\n - \n \n
\n - \n \n
\n - \n \n
\n
\n
\n ${encoded}\n
\n
\n
${header}
\n
${payload}
\n
\n
\n ${disclosures}\n
\n
\n`;\n};\n\n//# sourceURL=webpack://respec-vc-jose-cose/./src/exampleSdJwt.js?");
/***/ }),
@@ -7895,7 +7895,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getCombinedHtml: () => (/* binding */ getCombinedHtml),\n/* harmony export */ getCoseHtml: () => (/* binding */ getCoseHtml),\n/* harmony export */ getJwtHtml: () => (/* binding */ getJwtHtml),\n/* harmony export */ getSdJwtHtml: () => (/* binding */ getSdJwtHtml)\n/* harmony export */ });\n\n\nconst getCombinedHtml = ({ index, coseExample, jwtExample, sdJwtExample })=>{\n return `\n\n
\n
\n
\n
\n - \n \n
\n - \n \n
\n - \n \n
\n
\n
\n${coseExample}\n
\n
\n${jwtExample}\n
\n
\n${sdJwtExample}\n
\n
`\n}\n\nconst getJwtHtml = ({ index, jwtExample })=>{\n return `\n\n
\n
\n${jwtExample}\n
\n
`\n}\n\nconst getSdJwtHtml = ({ index, sdJwtExample })=>{\n return `\n\n
\n
\n${sdJwtExample}\n
\n
`\n}\n\nconst getCoseHtml = ({ index, coseExample })=>{\n return `\n\n
\n
\n${coseExample}\n
\n
`\n}\n\n\n//# sourceURL=webpack://respec-vc-jose-cose/./src/getHtml.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getCombinedHtml: () => (/* binding */ getCombinedHtml),\n/* harmony export */ getCoseHtml: () => (/* binding */ getCoseHtml),\n/* harmony export */ getJwtHtml: () => (/* binding */ getJwtHtml),\n/* harmony export */ getSdJwtHtml: () => (/* binding */ getSdJwtHtml)\n/* harmony export */ });\nconst getCombinedHtml = ({index, coseExample, jwtExample, sdJwtExample}) => {\n return `\n\n
\n
\n
\n
\n - \n \n
\n - \n \n
\n - \n \n
\n
\n
\n${coseExample}\n
\n
\n${jwtExample}\n
\n
\n${sdJwtExample}\n
\n
`\n}\n\nconst getJwtHtml = ({jwtExample}) => {\n return `\n\n
\n
\n${jwtExample}\n
\n
`\n}\n\nconst getSdJwtHtml = ({sdJwtExample}) => {\n return `\n\n${sdJwtExample}\n
\n`.trim();\n};\n\nconst getCoseHtml = ({coseExample}) => {\n return `\n\n
\n
\n${coseExample}\n
\n
`\n};\n\n//# sourceURL=webpack://respec-vc-jose-cose/./src/getHtml.js?");
/***/ }),
diff --git a/plugin/index.js b/plugin/index.js
index 0d1ba19..2201512 100644
--- a/plugin/index.js
+++ b/plugin/index.js
@@ -5,78 +5,103 @@ import { getJwtExample } from './src/exampleJwt';
import { getSdJwtExample } from './src/exampleSdJwt';
async function processVcJoseCose() {
- // add styling for examples
addVcJoseStyles();
- // handle full vc-jose-cose examples
- const examples = Array.from(document.querySelectorAll(".vc-jose-cose")).filter((e) => !!e.innerText)
+ const examples = Array.from(document.querySelectorAll(".vc-jose-cose")).filter((e) => !!e.innerText);
for (const index in examples) {
- const example = examples[index]
- const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''))
+ const example = examples[index];
+ const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''));
const processedData = await processCombinedExample(index, json);
- example.outerHTML = processedData.html
+ example.outerHTML = processedData.html;
}
- // handle jwt examples
- const jwtExamples = Array.from(document.querySelectorAll(".vc-jose-cose-jwt")).filter((e) => !!e.innerText)
+ const jwtExamples = Array.from(document.querySelectorAll(".vc-jose-cose-jwt")).filter((e) => !!e.innerText);
for (const index in jwtExamples) {
- const example = jwtExamples[index]
- const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''))
- const processedData = await processJwtExample(index, json);
- example.outerHTML = processedData.html
+ const example = jwtExamples[index];
+ const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''));
+ const processedData = await processJwtExample(json);
+ example.outerHTML = processedData.html;
}
- // handle sd-jwt examples
- const sdJwtExamples = Array.from(document.querySelectorAll(".vc-jose-cose-sd-jwt")).filter((e) => !!e.innerText)
+ const sdJwtExamples = Array.from(document.querySelectorAll(".vc-jose-cose-sd-jwt")).filter((e) => !!e.innerText);
for (const index in sdJwtExamples) {
- const example = sdJwtExamples[index]
- const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''))
+ const example = sdJwtExamples[index];
+ const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''));
const processedData = await processSdJwtExample(index, json);
- example.outerHTML = processedData.html
+ example.outerHTML = processedData.html;
}
- // handle cose examples
- const coseExamples = Array.from(document.querySelectorAll(".vc-jose-cose-cose")).filter((e) => !!e.innerText)
+ const coseExamples = Array.from(document.querySelectorAll(".vc-jose-cose-cose")).filter((e) => !!e.innerText);
for (const index in coseExamples) {
- const example = coseExamples[index]
- const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''))
- const processedData = await processCoseExample(index, json);
- example.outerHTML = processedData.html
+ const example = coseExamples[index];
+ const json = JSON.parse(example.innerText.replace(/\/\/ .*$/gm, ''));
+ const processedData = await processCoseExample(json);
+ example.outerHTML = processedData.html;
}
}
+export async function processCombinedExample(index, json) {
+ const privateKey = await getPrivateKey();
+ const coseExample = await getCoseExample(privateKey, json);
+ const jwtExample = await getJwtExample(privateKey, json);
+ const sdJwtExample = await getSdJwtExample(index, privateKey, json, 'combined');
+ const html = getCombinedHtml({ index, coseExample, jwtExample, sdJwtExample });
+ return { html };
+}
+
+export async function processJwtExample(json) {
+ const privateKey = await getPrivateKey();
+ const jwtExample = await getJwtExample(privateKey, json);
+ const html = getJwtHtml({ jwtExample });
+ return { html };
+}
+
+export async function processSdJwtExample(index, json) {
+ const privateKey = await getPrivateKey();
+ const sdJwtExample = await getSdJwtExample(index, privateKey, json, 'standalone');
+ const html = getSdJwtHtml({ sdJwtExample });
+ return { html };
+}
+
+export async function processCoseExample(json) {
+ const privateKey = await getPrivateKey();
+ const coseExample = await getCoseExample(privateKey, json);
+ const html = getCoseHtml({ coseExample });
+ return { html };
+}
+
function addVcJoseStyles() {
const styles = document.createElement('style');
-
- styles.innerHTML += `
- .vc-jose-cose-tabbed, .vc-jose-cose-tabbed-jwt, .vc-jose-cose-tabbed-sd-jwt, .vc-jose-cose-tabbed-cose {
+ styles.innerHTML = `
+ .vc-jose-cose-tabbed, .vc-jose-cose-tabbed-jwt, .vc-jose-cose-tabbed-sd-jwt, .vc-jose-cose-tabbed-cose,
+ .sd-jwt-tabbed {
overflow-x: hidden;
margin: 0 0;
}
-
-.vc-jose-cose-tabbed h1, .vc-jose-cose-jwt-tabbed h1, .vc-jose-cose-sd-jwt-tabbed h1, .vc-jose-cose-cose-tabbed h1 {
+.vc-jose-cose-tabbed h1, .vc-jose-cose-jwt-tabbed h1, .vc-jose-cose-sd-jwt-tabbed h1, .vc-jose-cose-cose-tabbed h1,
+.sd-jwt-tabbed h1 {
font-size: 1em;
margin: 0 0;
}
-
-.vc-jose-cose-tabbed [type="radio"], .vc-jose-cose-tabbed-jwt [type="radio"], .vc-jose-cose-tabbed-sd-jwt [type="radio"], .vc-jose-cose-tabbed-cose [type="radio"] {
+.vc-jose-cose-tabbed [type="radio"], .vc-jose-cose-tabbed-jwt [type="radio"], .vc-jose-cose-tabbed-sd-jwt [type="radio"], .vc-jose-cose-tabbed-cose [type="radio"],
+.sd-jwt-tabbed [type="radio"] {
display: none;
}
-
-.vc-jose-cose-tabs, .vc-jose-cose-jwt-tabs, .vc-jose-cose-sd-jwt-tabs, .vc-jose-cose-cose-tabs {
+.vc-jose-cose-tabs, .vc-jose-cose-jwt-tabs, .vc-jose-cose-sd-jwt-tabs, .vc-jose-cose-cose-tabs,
+.sd-jwt-tabs {
display: flex;
align-items: stretch;
list-style: none;
padding: 0;
border-bottom: 1px solid #ccc;
}
-
-li.vc-jose-cose-tab, li.vc-jose-cose-jwt-tab, li.vc-jose-cose-sd-jwt-tab, li.vc-jose-cose-cose-tab {
+li.vc-jose-cose-tab, li.vc-jose-cose-jwt-tab, li.vc-jose-cose-sd-jwt-tab, li.vc-jose-cose-cose-tab,
+li.sd-jwt-tab {
margin: 0 0;
margin-left: 8px;
}
-
-.vc-jose-cose-tab>label, .vc-jose-cose-jwt-tab>label, .vc-jose-cose-sd-jwt-tab>label, .vc-jose-cose-cose-tab>label {
+.vc-jose-cose-tab>label, .vc-jose-cose-jwt-tab>label, .vc-jose-cose-sd-jwt-tab>label, .vc-jose-cose-cose-tab>label,
+.sd-jwt-tab>label {
display: block;
margin-bottom: -1px;
padding: .4em .5em;
@@ -88,90 +113,99 @@ li.vc-jose-cose-tab, li.vc-jose-cose-jwt-tab, li.vc-jose-cose-sd-jwt-tab, li.vc-
cursor: pointer;
transition: all 0.3s;
}
-
-.vc-jose-cose-tab:hover label, .vc-jose-cose-jwt-tab:hover label, .vc-jose-cose-sd-jwt-tab:hover label, .vc-jose-cose-cose-tab:hover label {
+.vc-jose-cose-tab:hover label, .vc-jose-cose-jwt-tab:hover label, .vc-jose-cose-sd-jwt-tab:hover label, .vc-jose-cose-cose-tab:hover label,
+.sd-jwt-tab:hover label {
border-left-color: #333;
border-top-color: #333;
border-right-color: #333;
color: #333;
}
-
-.vc-jose-cose-tab-content {
+.vc-jose-cose-tab-content,
+.sd-jwt-tab-content {
display: none;
}
-
.vc-jose-cose-tabbed [type="radio"]:nth-of-type(1):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(1) label,
.vc-jose-cose-tabbed [type="radio"]:nth-of-type(2):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(2) label,
-.vc-jose-cose-tabbed [type="radio"]:nth-of-type(3):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(3) label {
+.vc-jose-cose-tabbed [type="radio"]:nth-of-type(3):checked~.vc-jose-cose-tabs .vc-jose-cose-tab:nth-of-type(3) label,
+.sd-jwt-tabbed [type="radio"]:nth-of-type(1):checked~.sd-jwt-tabs .sd-jwt-tab:nth-of-type(1) label,
+.sd-jwt-tabbed [type="radio"]:nth-of-type(2):checked~.sd-jwt-tabs .sd-jwt-tab:nth-of-type(2) label,
+.sd-jwt-tabbed [type="radio"]:nth-of-type(3):checked~.sd-jwt-tabs .sd-jwt-tab:nth-of-type(3) label {
border-bottom-color: #fff;
background: #fff;
color: #222;
}
-
.vc-jose-cose-tabbed [type="radio"]:nth-of-type(1):checked~.vc-jose-cose-tab-content:nth-of-type(1),
.vc-jose-cose-tabbed [type="radio"]:nth-of-type(2):checked~.vc-jose-cose-tab-content:nth-of-type(2),
-.vc-jose-cose-tabbed [type="radio"]:nth-of-type(3):checked~.vc-jose-cose-tab-content:nth-of-type(3) {
+.vc-jose-cose-tabbed [type="radio"]:nth-of-type(3):checked~.vc-jose-cose-tab-content:nth-of-type(3),
+.sd-jwt-tabbed [type="radio"]:nth-of-type(1):checked~.sd-jwt-tab-content:nth-of-type(1),
+.sd-jwt-tabbed [type="radio"]:nth-of-type(2):checked~.sd-jwt-tab-content:nth-of-type(2),
+.sd-jwt-tabbed [type="radio"]:nth-of-type(3):checked~.sd-jwt-tab-content:nth-of-type(3) {
display: block;
}
-
.sd-jwt-header, .jwt-header, .vc-jose-cose-jwt .header, .vc-jose-cose-sd-jwt .header, .vc-jose-cose-cose .header {
color: red;
}
-
.sd-jwt-payload, .jwt-payload, .vc-jose-cose-jwt .payload, .vc-jose-cose-sd-jwt .payload, .vc-jose-cose-cose .payload {
color: green;
}
-
.sd-jwt-signature, .jwt-signature, .vc-jose-cose-jwt .signature, .vc-jose-cose-sd-jwt .signature, .vc-jose-cose-cose .signature {
color: blue;
}
-
.sd-jwt-disclosure, .vc-jose-cose-jwt .disclosure, .vc-jose-cose-sd-jwt .disclosure, .vc-jose-cose-cose .disclosure {
color: purple;
}
-
.sd-jwt-compact, .jwt-compact, .vc-jose-cose-jwt .compact, .vc-jose-cose-sd-jwt .compact, .vc-jose-cose-cose .compact {
background-color: rgba(0,0,0,.03);
}
-
.cose-text, .jose-text, .vc-jose-cose-jwt .text, .vc-jose-cose-sd-jwt .text, .vc-jose-cose-cose .text {
font-family: monospace;
color: green;
-}`;
-
- document.head.appendChild(styles);
-}
-
-export async function processCombinedExample(index, json) {
- const privateKey = await getPrivateKey();
- const coseExample = await getCoseExample(privateKey, json);
- const jwtExample = await getJwtExample(privateKey, json);
- const sdJwtExample = await getSdJwtExample(privateKey, json);
- const html = getCombinedHtml({index, coseExample, jwtExample, sdJwtExample});
- return {html};
}
-
-export async function processJwtExample(index, json) {
- const privateKey = await getPrivateKey();
- const jwtExample = await getJwtExample(privateKey, json);
- const html = getJwtHtml({index, jwtExample});
- return {html};
-}
-
-export async function processSdJwtExample(index, json) {
- const privateKey = await getPrivateKey();
- const sdJwtExample = await getSdJwtExample(privateKey, json);
- const html = getSdJwtHtml({index, sdJwtExample});
- return {html};
-}
-
-export async function processCoseExample(index, json) {
- const privateKey = await getPrivateKey();
- const coseExample = await getCoseExample(privateKey, json);
- const html = getCoseHtml({index, coseExample});
- return {html};
+.disclosure {
+ margin: 10px 0;
+ font-size: 12px;
+ line-height: 1.6;
+ padding: 5px;
+}
+.disclosure h3 {
+ margin: 0;
+ font-size: 14px;
+ padding-left: 5px;
+}
+.disclosure .claim-name {
+ color: #333;
+}
+.disclosure .hash,
+.disclosure .disclosure-value,
+.disclosure .contents {
+ color: #555;
+ word-wrap: break-word;
+ display: inline;
+}
+.disclosure p {
+ margin: 0;
+ padding-left: 5px;
+}
+.disclosure pre {
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ margin: 0;
+ padding-left: 5px;
+ line-height: 1.6;
+ display: inline-block;
+}
+.header-value {
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ margin: 0;
+ padding-left: 5px;
+ line-height: 1.6;
+ font-size: 12px;
+}
+`;
+ document.head.appendChild(styles);
}
window.respecVcJoseCose = {
processVcJoseCose
-}
+};
diff --git a/plugin/src/exampleSdJwt.js b/plugin/src/exampleSdJwt.js
index abc0807..16103d7 100644
--- a/plugin/src/exampleSdJwt.js
+++ b/plugin/src/exampleSdJwt.js
@@ -7,7 +7,6 @@ const calculateHash = (value) => {
return base64url.encode(crypto.createHash('sha256').update(value).digest());
};
-// Custom JSON.stringify with prettier formatting
const customJSONStringify = (obj) => {
return JSON.stringify(obj, null, 2).replace(/\n/g, '
').replace(/\s/g, ' ');
};
@@ -40,7 +39,14 @@ const getHeadersHtml = (vc) => {
return ``;
};
-const getDisclosabilityHtml = async (vc) => {
+const getPayloadHtml = (vc) => {
+ const [token] = vc.split('~');
+ const [, payload] = token.split('.');
+ const payloadJson = JSON.parse(new TextDecoder().decode(base64url.decode(payload)));
+ return ``;
+};
+
+const getDisclosuresHtml = async (vc) => {
const [_, ...disclosures] = vc.split('~');
const disclosureHtml = disclosures.map((disclosure) => {
const decodedDisclosure = JSON.parse(new TextDecoder().decode(base64url.decode(disclosure)));
@@ -51,11 +57,7 @@ const getDisclosabilityHtml = async (vc) => {
return generateDisclosureHtml(JSON.stringify(claimName), hash, disclosure, decodedDisclosure);
});
- return `
-
- ${disclosureHtml.join('\n')}
-
-`;
+ return `${disclosureHtml.join('\n')}
`;
};
export const generateIssuerClaims = (example) => {
@@ -76,7 +78,7 @@ const getPresentation = async (privateKey, byteSigner, messageType, messageJson)
return await getCredential(privateKey, byteSigner, 'application/vc+ld+json+sd-jwt', messageJson);
};
-const getBinaryMessage = async (privateKey, messageType, messageJson) => {
+export const getBinaryMessage = async (privateKey, messageType, messageJson) => {
const byteSigner = {
sign: async (bytes) => {
const jws = await new jose.CompactSign(bytes)
@@ -101,75 +103,41 @@ const getBinaryMessage = async (privateKey, messageType, messageJson) => {
}
};
-export const getSdJwtExample = async (privateKey, messageJson) => {
- injectStyles();
+export const getSdJwtExample = async (index, privateKey, messageJson, prefix = 'sd-jwt') => {
const type = Array.isArray(messageJson.type) ? messageJson.type : [messageJson.type];
const messageType = type.includes('VerifiableCredential') ? 'application/vc+ld+json+sd-jwt' : 'application/vp+ld+json+sd-jwt';
- const message = await getBinaryMessage(privateKey, messageType, messageJson);
- const messageEncoded = new TextDecoder().decode(message);
-
+ const binaryMessage = await getBinaryMessage(privateKey, messageType, messageJson);
+ const message = new TextDecoder().decode(binaryMessage);
+ const encoded = getSdHtml(message);
+ const header = getHeadersHtml(message);
+ const payload = getPayloadHtml(message);
+ const disclosures = await getDisclosuresHtml(message);
return `
-Protected Headers
-
-${getHeadersHtml(messageEncoded)}
-
-
-Disclosures
-
-${await getDisclosabilityHtml(messageEncoded)}
-
-
-${messageType}
-
-${getSdHtml(messageEncoded)}
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ ${encoded}
+
+
+
${header}
+
${payload}
+
+
+ ${disclosures}
+
- `.trim();
-};
-
-const injectStyles = () => {
- const style = document.createElement('style');
- style.innerHTML = `
- .disclosure {
- margin: 10px 0;
- font-size: 12px;
- line-height: 1.6;
- padding: 5px;
- }
- .disclosure h3 {
- margin: 0;
- font-size: 14px;
- padding-left: 5px;
- }
- .disclosure .claim-name {
- color: #333;
- }
- .disclosure .hash,
- .disclosure .disclosure-value,
- .disclosure .contents {
- color: #555;
- word-wrap: break-word;
- display: inline;
- }
- .disclosure p {
- margin: 0;
- padding-left: 5px;
- }
- .disclosure pre {
- white-space: pre-wrap;
- word-wrap: break-word;
- margin: 0;
- padding-left: 5px;
- line-height: 1.6;
- display: inline-block;
- }
- .header-value {
- white-space: pre-wrap;
- word-wrap: break-word;
- margin: 0;
- padding-left: 5px;
- line-height: 1.6;
- font-size: 12px;
- }
- `;
- document.head.appendChild(style);
+`;
};
\ No newline at end of file
diff --git a/plugin/src/getHtml.js b/plugin/src/getHtml.js
index 053b404..d49c052 100644
--- a/plugin/src/getHtml.js
+++ b/plugin/src/getHtml.js
@@ -1,6 +1,4 @@
-
-
-export const getCombinedHtml = ({ index, coseExample, jwtExample, sdJwtExample })=>{
+export const getCombinedHtml = ({index, coseExample, jwtExample, sdJwtExample}) => {
return `
@@ -29,7 +27,7 @@ ${sdJwtExample}
`
}
-export const getJwtHtml = ({ index, jwtExample })=>{
+export const getJwtHtml = ({jwtExample}) => {
return `
@@ -43,21 +41,15 @@ ${jwtExample}
`
}
-export const getSdJwtHtml = ({ index, sdJwtExample })=>{
+export const getSdJwtHtml = ({sdJwtExample}) => {
return `
-
+`.trim();
+};
-export const getCoseHtml = ({ index, coseExample })=>{
+export const getCoseHtml = ({coseExample}) => {
return `
@@ -69,4 +61,4 @@ export const getCoseHtml = ({ index, coseExample })=>{
${coseExample}
`
-}
+};
\ No newline at end of file