diff --git a/package-lock.json b/package-lock.json index 709a212a..997e5180 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,7 +85,7 @@ "@babel/preset-env": "^7.22.10", "@docknetwork/cheqd-blockchain-api": "6.0.1", "@docknetwork/cheqd-blockchain-modules": "6.0.1", - "@docknetwork/credential-sdk": "0.56.1", + "@docknetwork/credential-sdk": "0.56.2", "@docknetwork/universal-wallet": "2.1.1", "@react-native-community/eslint-config": "^2.0.0", "@testing-library/jest-dom": "^5.11.4", @@ -4006,14 +4006,14 @@ } }, "node_modules/@docknetwork/credential-sdk": { - "version": "0.56.1", - "resolved": "https://registry.npmjs.org/@docknetwork/credential-sdk/-/credential-sdk-0.56.1.tgz", - "integrity": "sha512-6RaPzLoeWSV7Xah59yTF1+j6c/L+YWnw47lQ7KYZd10H/0eS+H5NBfQLiW0hQfDGsdYamyD9plqQpCVhefYt3Q==", + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@docknetwork/credential-sdk/-/credential-sdk-0.56.2.tgz", + "integrity": "sha512-nP08cZJzOvNfQQbWu3FZgJQj6iBc4yvx3fDGXKiOuvKMJWQ66LGuUPvqU45kownOKayWomOIlwNyniaPpdPGpQ==", "license": "MIT", "dependencies": { "@astronautlabs/jsonpath": "^1.1.2", "@digitalcredentials/vc-status-list": "^9.0.0", - "@docknetwork/crypto-utils": "0.2.1", + "@docknetwork/crypto-utils": "0.2.2", "@docknetwork/crypto-wasm-ts": "^0.63.0", "@docknetwork/vc-delegation-engine": "1.0.4", "@juanelas/base64": "^1.1.5", @@ -4077,11 +4077,15 @@ } }, "node_modules/@docknetwork/crypto-utils": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@docknetwork/crypto-utils/-/crypto-utils-0.2.1.tgz", - "integrity": "sha512-hx2nkap3w8CJzoIA9NYm/Ui8PLN5nNjAreBJa69AJJ0DMvfsCv7990cICBMJCfzclFZXzoowDixtyaFDyGk3Kw==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@docknetwork/crypto-utils/-/crypto-utils-0.2.2.tgz", + "integrity": "sha512-/XDXZO+1obToS8rMnkFvqxX4RszJ4bmP6ndIgJcP6g1J6NNngsTtDvkAUm6I9/iwb2eI64JEHxYAJG1uj7XIoA==", "license": "MIT", "dependencies": { + "@noble/hashes": "^1.8.0", + "@sd-jwt/crypto-browser": "^0.9.2", + "@sd-jwt/crypto-nodejs": "^0.9.2", + "@sd-jwt/sd-jwt-vc": "^0.9.2", "@stablelib/ed25519": "^1.0.0", "base64url": "^3.0.1", "elliptic": "6.6.1", @@ -4091,6 +4095,115 @@ "node": ">=22.0.0" } }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/core": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/core/-/core-0.9.2.tgz", + "integrity": "sha512-AbvID/VIogRtPtCWGmfUlCZczHaBSRFmTwOAiUeuPRjDJTGUQu3gMRKwsfSGRHlfPo0pSaRQ7lqN3N+a5i+SDA==", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/decode": "0.9.2", + "@sd-jwt/present": "0.9.2", + "@sd-jwt/types": "0.9.2", + "@sd-jwt/utils": "0.9.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/crypto-nodejs": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/crypto-nodejs/-/crypto-nodejs-0.9.2.tgz", + "integrity": "sha512-OL5drLhrsDok60XfLoovAK+DT/6mA1myZe1tkA8JflV8tcx4OZTLi/UMVcW/hc+7nBugYICutVSoIejTYsgbEw==", + "deprecated": "Merged into @owf/crypto", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/decode": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/decode/-/decode-0.9.2.tgz", + "integrity": "sha512-jHY7hqk7EMkp6E2cB13QmXvRZN7njvAveVh+zKKy0kxpAM7DmcR4TqcDA4mc5y4lP8zWFUgbk7oGLCx2wiBq+w==", + "deprecated": "Merged into @sd-jwt/core (>= 0.20.0). Security: GHSA-f9j6-8p6x-r9j6.", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/types": "0.9.2", + "@sd-jwt/utils": "0.9.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/jwt-status-list": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/jwt-status-list/-/jwt-status-list-0.9.2.tgz", + "integrity": "sha512-59bPkgSnwvibJgUNVKmSE3SFMQwvDnh3Xr21aUi0bgII7yoHTQ+vqnryVOF8qcjpyICyi/clIlkTw3VWSyAV+g==", + "deprecated": "Package moved to @owf/token-status-list, please use this instead", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/types": "0.9.2", + "base64url": "^3.0.1", + "pako": "^2.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/present": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/present/-/present-0.9.2.tgz", + "integrity": "sha512-ozBDYfQxUCwu0N+gbyk6zJDraMslFFuNLW+GxITybdDfVJek65tBtbROB8ZBvkAlEl0PDRKebq+xKOCRmplmWA==", + "deprecated": "Package got merged into @sd-jwt/core, please use this instead", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/decode": "0.9.2", + "@sd-jwt/types": "0.9.2", + "@sd-jwt/utils": "0.9.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/sd-jwt-vc": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/sd-jwt-vc/-/sd-jwt-vc-0.9.2.tgz", + "integrity": "sha512-UOx5ULWyztJv2FbIjVJ0XCDixXwpgFxRCFykhLeRJI0T9+48hi2ucvOdqZqD2X7LkXkjCZNR0kQlJs+/n8gLEg==", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/core": "0.9.2", + "@sd-jwt/jwt-status-list": "0.9.2", + "@sd-jwt/utils": "0.9.2", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/types": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/types/-/types-0.9.2.tgz", + "integrity": "sha512-eV/MY80ekeTrqaohzPpkrgwPki6Igx69D6RniduV1Ehv6o/zaJQ2F0hY/RqBAkJhQtBQoOzouwKYHme40k1Dlw==", + "deprecated": "Package got merged into @sd-jwt/core, please use this instead", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@docknetwork/crypto-utils/node_modules/@sd-jwt/utils": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/utils/-/utils-0.9.2.tgz", + "integrity": "sha512-GpTD0isav2f+JyMyzeyf6wV3nYcD5e3oL+sVVr/61Y3oaIBGMWLtGGGhBRMCimSnd8kbb0P9jLxvp7ioASk6vw==", + "deprecated": "Package got merged into @sd-jwt/core, please use this instead", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/types": "0.9.2", + "js-base64": "^3.7.6" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@docknetwork/crypto-utils/node_modules/@stablelib/ed25519": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", @@ -4129,6 +4242,23 @@ "@stablelib/wipe": "^1.0.1" } }, + "node_modules/@docknetwork/crypto-utils/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/@docknetwork/crypto-wasm-ts": { "version": "0.63.0", "resolved": "https://registry.npmjs.org/@docknetwork/crypto-wasm-ts/-/crypto-wasm-ts-0.63.0.tgz", @@ -11974,78 +12104,12 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@sd-jwt/core": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/core/-/core-0.15.0.tgz", - "integrity": "sha512-H+I8OcZj8/f6GZxNSblJqJXi6Mo/W5sUcVNiW9K6kc0rEGt+na111zS1vpjbG6QEJT/YC9egIVUHXNJlNIlWxw==", - "license": "Apache-2.0", - "dependencies": { - "@sd-jwt/decode": "0.15.0", - "@sd-jwt/present": "0.15.0", - "@sd-jwt/types": "0.15.0", - "@sd-jwt/utils": "0.15.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/core/node_modules/@sd-jwt/decode": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/decode/-/decode-0.15.0.tgz", - "integrity": "sha512-c9PX4/Cnl1G0pSUXU236lkDx1AzkbgGKFnevBaVIPX8WlJl0nII345uDW/KWCV4rs5Ci8j4ZviWVOJm8TCt2fg==", - "license": "Apache-2.0", - "dependencies": { - "@sd-jwt/types": "0.15.0", - "@sd-jwt/utils": "0.15.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/core/node_modules/@sd-jwt/present": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/present/-/present-0.15.0.tgz", - "integrity": "sha512-Wf/KUKDe06QjnRBzaN6fMAtYPVynQZ+hJOSnpDiNU3E2k3X1KB/rPy7J4uT08ch3ZwJN+08FR7aFsrKvWjjsmg==", - "license": "Apache-2.0", - "dependencies": { - "@sd-jwt/decode": "0.15.0", - "@sd-jwt/types": "0.15.0", - "@sd-jwt/utils": "0.15.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/core/node_modules/@sd-jwt/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/types/-/types-0.15.0.tgz", - "integrity": "sha512-3b/jz4xkQ9HAOVtnR5s+R9qzqPUig8EvTK4kDOL1rSdTHSQ8E50+Gji1k2m/0hF/DP4EskWc5iQJKrk2qRohaQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/core/node_modules/@sd-jwt/utils": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/utils/-/utils-0.15.0.tgz", - "integrity": "sha512-eHenn93LQD1DirBwz8bgE5vEH+sJaKKP+1y9kk2OGuPh1vLiw1hT0O7zlvRVHf9Z9SFYe09ZVucH0jDkjo5OAw==", - "license": "Apache-2.0", - "dependencies": { - "@sd-jwt/types": "0.15.0", - "js-base64": "^3.7.6" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/crypto-nodejs": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/crypto-nodejs/-/crypto-nodejs-0.15.0.tgz", - "integrity": "sha512-qWoXeJL/knLUDYJ5s3elOwT5iakGz3gGpjdM3F9Xghq0lx6MdOUEBdLoJuGzhkyxCVg2eBNewLqsaeg7h2Ik/Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } + "node_modules/@sd-jwt/crypto-browser": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/crypto-browser/-/crypto-browser-0.9.2.tgz", + "integrity": "sha512-m/l+z3c6ily0uadGEdg6979h8HXgl975qeM2xn/qC0hXtzypM8XW9C7Ym7M6IaBTUkZoh9RRjD6wO0tEtpPsEg==", + "deprecated": "Merged into @owf/crypto", + "license": "Apache-2.0" }, "node_modules/@sd-jwt/decode": { "version": "0.7.2", @@ -12060,29 +12124,6 @@ "node": ">=18" } }, - "node_modules/@sd-jwt/jwt-status-list": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/jwt-status-list/-/jwt-status-list-0.15.0.tgz", - "integrity": "sha512-+wy0+Z5tgO6hjTSjrDV9o/fjxIBqWajsTl3cU//u2mZpPFWljLCvZgC0743iwphkkRf9hSQhRsPIgH5mIWtRVQ==", - "license": "Apache-2.0", - "dependencies": { - "@sd-jwt/types": "0.15.0", - "base64url": "^3.0.1", - "pako": "^2.1.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/jwt-status-list/node_modules/@sd-jwt/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/types/-/types-0.15.0.tgz", - "integrity": "sha512-3b/jz4xkQ9HAOVtnR5s+R9qzqPUig8EvTK4kDOL1rSdTHSQ8E50+Gji1k2m/0hF/DP4EskWc5iQJKrk2qRohaQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } - }, "node_modules/@sd-jwt/present": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@sd-jwt/present/-/present-0.7.2.tgz", @@ -12097,61 +12138,6 @@ "node": ">=18" } }, - "node_modules/@sd-jwt/sd-jwt-vc": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@sd-jwt/sd-jwt-vc/-/sd-jwt-vc-0.15.1.tgz", - "integrity": "sha512-xgs611LuHwNU71sw1dcWluFB0C+20uqvsuQdpcPnLckKu0yyxmm9Sb2s01Ec0uBvC3HGdQAgmP/I/B0mHXYPUA==", - "license": "Apache-2.0", - "dependencies": { - "@sd-jwt/core": "0.15.0", - "@sd-jwt/jwt-status-list": "0.15.0", - "@sd-jwt/utils": "0.15.0", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/sd-jwt-vc/node_modules/@sd-jwt/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/types/-/types-0.15.0.tgz", - "integrity": "sha512-3b/jz4xkQ9HAOVtnR5s+R9qzqPUig8EvTK4kDOL1rSdTHSQ8E50+Gji1k2m/0hF/DP4EskWc5iQJKrk2qRohaQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/sd-jwt-vc/node_modules/@sd-jwt/utils": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@sd-jwt/utils/-/utils-0.15.0.tgz", - "integrity": "sha512-eHenn93LQD1DirBwz8bgE5vEH+sJaKKP+1y9kk2OGuPh1vLiw1hT0O7zlvRVHf9Z9SFYe09ZVucH0jDkjo5OAw==", - "license": "Apache-2.0", - "dependencies": { - "@sd-jwt/types": "0.15.0", - "js-base64": "^3.7.6" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sd-jwt/sd-jwt-vc/node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, "node_modules/@sd-jwt/types": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@sd-jwt/types/-/types-0.7.2.tgz", @@ -48459,14 +48445,15 @@ "@cosmjs/proto-signing": "^0.32.4", "@docknetwork/cheqd-blockchain-api": "6.0.1", "@docknetwork/cheqd-blockchain-modules": "6.0.1", - "@docknetwork/credential-sdk": "0.56.1", + "@docknetwork/credential-sdk": "0.56.2", + "@docknetwork/crypto-utils": "0.2.2", "@docknetwork/universal-wallet": "^2.0.1", "@docknetwork/vc-delegation-engine": "1.0.4", "@docknetwork/wallet-sdk-dids": "^1.9.1", "@noble/hashes": "1.8.0", "@scure/bip39": "^1.6.0", - "@sd-jwt/crypto-nodejs": "^0.15.0", - "@sd-jwt/sd-jwt-vc": "^0.15.1", + "@sd-jwt/crypto-nodejs": "0.9.2", + "@sd-jwt/sd-jwt-vc": "0.9.2", "@sphereon/oid4vci-client": "^0.16.0", "@sphereon/oid4vci-common": "^0.16.0", "@sphereon/pex": "^1.1.4", @@ -48490,6 +48477,132 @@ "typescript": "^5.0.4" } }, + "packages/wasm/node_modules/@sd-jwt/core": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/core/-/core-0.9.2.tgz", + "integrity": "sha512-AbvID/VIogRtPtCWGmfUlCZczHaBSRFmTwOAiUeuPRjDJTGUQu3gMRKwsfSGRHlfPo0pSaRQ7lqN3N+a5i+SDA==", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/decode": "0.9.2", + "@sd-jwt/present": "0.9.2", + "@sd-jwt/types": "0.9.2", + "@sd-jwt/utils": "0.9.2" + }, + "engines": { + "node": ">=18" + } + }, + "packages/wasm/node_modules/@sd-jwt/crypto-nodejs": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/crypto-nodejs/-/crypto-nodejs-0.9.2.tgz", + "integrity": "sha512-OL5drLhrsDok60XfLoovAK+DT/6mA1myZe1tkA8JflV8tcx4OZTLi/UMVcW/hc+7nBugYICutVSoIejTYsgbEw==", + "deprecated": "Merged into @owf/crypto", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "packages/wasm/node_modules/@sd-jwt/decode": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/decode/-/decode-0.9.2.tgz", + "integrity": "sha512-jHY7hqk7EMkp6E2cB13QmXvRZN7njvAveVh+zKKy0kxpAM7DmcR4TqcDA4mc5y4lP8zWFUgbk7oGLCx2wiBq+w==", + "deprecated": "Merged into @sd-jwt/core (>= 0.20.0). Security: GHSA-f9j6-8p6x-r9j6.", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/types": "0.9.2", + "@sd-jwt/utils": "0.9.2" + }, + "engines": { + "node": ">=18" + } + }, + "packages/wasm/node_modules/@sd-jwt/jwt-status-list": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/jwt-status-list/-/jwt-status-list-0.9.2.tgz", + "integrity": "sha512-59bPkgSnwvibJgUNVKmSE3SFMQwvDnh3Xr21aUi0bgII7yoHTQ+vqnryVOF8qcjpyICyi/clIlkTw3VWSyAV+g==", + "deprecated": "Package moved to @owf/token-status-list, please use this instead", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/types": "0.9.2", + "base64url": "^3.0.1", + "pako": "^2.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "packages/wasm/node_modules/@sd-jwt/present": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/present/-/present-0.9.2.tgz", + "integrity": "sha512-ozBDYfQxUCwu0N+gbyk6zJDraMslFFuNLW+GxITybdDfVJek65tBtbROB8ZBvkAlEl0PDRKebq+xKOCRmplmWA==", + "deprecated": "Package got merged into @sd-jwt/core, please use this instead", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/decode": "0.9.2", + "@sd-jwt/types": "0.9.2", + "@sd-jwt/utils": "0.9.2" + }, + "engines": { + "node": ">=18" + } + }, + "packages/wasm/node_modules/@sd-jwt/sd-jwt-vc": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/sd-jwt-vc/-/sd-jwt-vc-0.9.2.tgz", + "integrity": "sha512-UOx5ULWyztJv2FbIjVJ0XCDixXwpgFxRCFykhLeRJI0T9+48hi2ucvOdqZqD2X7LkXkjCZNR0kQlJs+/n8gLEg==", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/core": "0.9.2", + "@sd-jwt/jwt-status-list": "0.9.2", + "@sd-jwt/utils": "0.9.2", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "packages/wasm/node_modules/@sd-jwt/sd-jwt-vc/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "packages/wasm/node_modules/@sd-jwt/types": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/types/-/types-0.9.2.tgz", + "integrity": "sha512-eV/MY80ekeTrqaohzPpkrgwPki6Igx69D6RniduV1Ehv6o/zaJQ2F0hY/RqBAkJhQtBQoOzouwKYHme40k1Dlw==", + "deprecated": "Package got merged into @sd-jwt/core, please use this instead", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "packages/wasm/node_modules/@sd-jwt/utils": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@sd-jwt/utils/-/utils-0.9.2.tgz", + "integrity": "sha512-GpTD0isav2f+JyMyzeyf6wV3nYcD5e3oL+sVVr/61Y3oaIBGMWLtGGGhBRMCimSnd8kbb0P9jLxvp7ioASk6vw==", + "deprecated": "Package got merged into @sd-jwt/core, please use this instead", + "license": "Apache-2.0", + "dependencies": { + "@sd-jwt/types": "0.9.2", + "js-base64": "^3.7.6" + }, + "engines": { + "node": ">=18" + } + }, "packages/wasm/node_modules/@sphereon/pex": { "version": "1.1.6", "license": "Apache-2.0", diff --git a/package.json b/package.json index bffa899a..b8c53d96 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@babel/preset-env": "^7.22.10", "@docknetwork/cheqd-blockchain-api": "6.0.1", "@docknetwork/cheqd-blockchain-modules": "6.0.1", - "@docknetwork/credential-sdk": "0.56.1", + "@docknetwork/credential-sdk": "0.56.2", "@docknetwork/universal-wallet": "2.1.1", "@react-native-community/eslint-config": "^2.0.0", "@testing-library/jest-dom": "^5.11.4", diff --git a/packages/core/src/credential-provider.ts b/packages/core/src/credential-provider.ts index 1b2462ea..45a01c0a 100644 --- a/packages/core/src/credential-provider.ts +++ b/packages/core/src/credential-provider.ts @@ -112,6 +112,11 @@ export async function isValid({ const {verified, error} = verificationResult; + const errorMessage = + typeof error === 'string' + ? error + : error?.message || error?.errors?.[0]?.message || error; + if (error) { const sdkNotInitialized = error?.errors?.find(err => err?.message === 'SDK is not initialized'); if (sdkNotInitialized) { @@ -122,17 +127,17 @@ export async function isValid({ } if (!verified) { - const errorMessage = (error?.message || error || '').toString().toLowerCase(); - if (errorMessage.includes('revok')) { + const normalizedError = (errorMessage || '').toString().toLowerCase(); + if (normalizedError.includes('revok')) { return { status: CredentialStatus.Revoked, - error, + error: errorMessage, }; } return { status: CredentialStatus.Invalid, - error: error, + error: errorMessage, }; } diff --git a/packages/wasm/package.json b/packages/wasm/package.json index 646e2848..ed03156f 100644 --- a/packages/wasm/package.json +++ b/packages/wasm/package.json @@ -23,14 +23,15 @@ "@cosmjs/proto-signing": "^0.32.4", "@docknetwork/cheqd-blockchain-api": "6.0.1", "@docknetwork/cheqd-blockchain-modules": "6.0.1", - "@docknetwork/credential-sdk": "0.56.1", + "@docknetwork/credential-sdk": "0.56.2", + "@docknetwork/crypto-utils": "0.2.2", "@docknetwork/universal-wallet": "^2.0.1", "@docknetwork/vc-delegation-engine": "1.0.4", "@docknetwork/wallet-sdk-dids": "^1.9.1", "@noble/hashes": "1.8.0", "@scure/bip39": "^1.6.0", - "@sd-jwt/crypto-nodejs": "^0.15.0", - "@sd-jwt/sd-jwt-vc": "^0.15.1", + "@sd-jwt/crypto-nodejs": "0.9.2", + "@sd-jwt/sd-jwt-vc": "0.9.2", "@sphereon/oid4vci-client": "^0.16.0", "@sphereon/oid4vci-common": "^0.16.0", "@sphereon/pex": "^1.1.4", diff --git a/packages/wasm/src/services/credential/index.test.js b/packages/wasm/src/services/credential/index.test.js index 8a02c51b..904e56ee 100644 --- a/packages/wasm/src/services/credential/index.test.js +++ b/packages/wasm/src/services/credential/index.test.js @@ -37,6 +37,22 @@ describe('Credential Service', () => { const error0 = await getPromiseError(() => service.verifyCredential({})); expect(error0.message).toBe('invalid credential'); }); + it('expect to reject SD-JWT credentials missing compact serialization', async () => { + const result = await service.verifyCredential({ + credential: { + '@context': ['https://www.w3.org/2018/credentials/v1'], + type: ['VerifiableCredential', 'BasicCredential'], + issuer: 'did:example:issuer', + credentialSubject: {}, + _sd_jwt: { + // decoded-payload imports store metadata without an encoded JWT + }, + }, + }); + + expect(result.verified).toBe(false); + expect(result.error).toContain('compact serialization'); + }); it('expect to verify credential', async () => { jest .spyOn(serviceCredentialUtils, 'verifyCredential') diff --git a/packages/wasm/src/services/credential/sd-jwt.test.ts b/packages/wasm/src/services/credential/sd-jwt.test.ts index 641b4ea2..97c453d0 100644 --- a/packages/wasm/src/services/credential/sd-jwt.test.ts +++ b/packages/wasm/src/services/credential/sd-jwt.test.ts @@ -1,3 +1,7 @@ +// @ts-nocheck +import {createJwsSigner, Ed25519Keypair} from '@docknetwork/crypto-utils'; +import {digest, generateSalt} from '@sd-jwt/crypto-nodejs'; +import {SDJwtVcInstance} from '@sd-jwt/sd-jwt-vc'; import { isSDJWTCredential, sdJwtToW3C, @@ -11,6 +15,41 @@ import { // Test SD-JWT credential provided by the user const TEST_SD_JWT = 'eyJ0eXAiOiJ2YytzZC1qd3QiLCJraWQiOiJkaWQ6Y2hlcWQ6dGVzdG5ldDpjMDg5MGYxYy1jN2JiLTRlYTYtYmU3YS04YzMxNDA0NzQzYjcja2V5cy0xIiwiYWxnIjoiRWREU0EifQ.eyJpYXQiOjE3NTk0MTQzOTQsImlzcyI6ImRpZDpjaGVxZDp0ZXN0bmV0OmMwODkwZjFjLWM3YmItNGVhNi1iZTdhLThjMzE0MDQ3NDNiNyNrZXlzLTEiLCJ2Y3QiOiJJbnRlcm5hbFRlc3RpbmciLCJfc2QiOlsiM3JVUGt1Mk5XckFFeTV3ZE9uVms5TkJBa0haMWE4RDB6Y2liMFNQdmthWSIsIkhjNHAxMnZTTWNMQ0piNVRYVlFrdFFMR2xjM0J3SDNWN2ltakV5ZDdvdzAiLCJNZWNNZEd6NjAxY3kwTTdvanRtSjR1LUI5LTJxSXAya1RvbFpDUm1GZ1pFIiwiZmo4WHdBb0lERmRsWmpEa0NTVzVpeXBPYUZBcVplTWZDRncwTWd3cHhOQSJdLCJfc2RfYWxnIjoic2hhLTI1NiJ9.FcYvNrldceL5BTNmoIaS4Mub8a5NcbiseUeSmmvUpOW8SUom-bchV5AEefrH1VMECbdc2whhk2sW4_jmZo7_Dw~WyI1YTRkZWY1MTAzYjRiYjc0IiwiaWQiLCJkaWQ6a2V5Ono2TWt1OVI4emRBOExENmhjRlhrbjQ3akxuZmNLWk5HbXdhVHJEbmFDQmtTYjhVbiJd~WyJiZDUyMjQ5ZjAyNjk3NWRkIiwiZGF0ZSIsIjIwMjUtMTAtMDkiXQ~WyJlMjcxNzExNzVkODdlMWE1IiwibmFtZSIsIm1heWNvbiJd~WyIwZDFiOTBlNTlhNmMyNDNiIiwibnVtYmVyIiwxMjNd~'; +const ISSUER_DID = 'did:ex:issuer#keys-1'; + +async function issueTestSdJwt(keypair, claims, disclosureFrame = {_sd: ['name', 'date', 'number', 'id']}) { + const signer = createJwsSigner(keypair); + const sdjwt = new SDJwtVcInstance({ + signer: async data => { + const bytes = typeof data === 'string' ? Buffer.from(data) : data; + const signature = await signer.sign({data: bytes}); + return Buffer.from(signature).toString('base64url'); + }, + signAlg: 'EdDSA', + hasher: digest, + hashAlg: 'sha-256', + saltGenerator: generateSalt, + }); + + return sdjwt.issue(claims, disclosureFrame, { + header: { + typ: 'vc+sd-jwt', + alg: 'EdDSA', + kid: claims.iss, + }, + }); +} + +function createIssuerKeypair() { + return Ed25519Keypair.fromSeed( + Uint8Array.from({length: Ed25519Keypair.SeedSize}, (_, index) => index + 1), + ); +} + +function createKeyResolver(keypair) { + return async () => keypair.publicKey(); +} + // Regular JWT (not SD-JWT) for testing const REGULAR_JWT = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'; @@ -402,32 +441,69 @@ describe('SD-JWT Service', () => { }); describe('verifySDJWT', () => { - it('should verify valid SD-JWT successfully', async () => { - const result = await verifySDJWT(TEST_SD_JWT); + it('should fail when no issuer key resolution options are provided', async () => { + const keypair = createIssuerKeypair(); + const credential = await issueTestSdJwt( + keypair, + { + iss: ISSUER_DID, + iat: 1700000000, + vct: 'InternalTesting', + name: 'maycon', + }, + {_sd: ['name']}, + ); - expect(result).toHaveProperty('verified'); - expect(result.verified).toBe(true); - expect(result.error).toBeUndefined(); + // Production callers must pass documentLoader/resolver/keyResolver. + const result = await verifySDJWT(credential); + + expect(result.verified).toBe(false); + expect(result.error).toBeDefined(); }); - it('should fail verification for expired SD-JWT', async () => { - // Create an expired SD-JWT (exp in the past) - const expiredJWT = 'eyJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTppc3N1ZXIiLCJ2Y3QiOiJUZXN0Q3JlZGVudGlhbCIsImV4cCI6MTYwOTQ1OTIwMCwiaWF0IjoxNjA5NDU5MjAwfQ.signature~'; + it('should cryptographically verify a valid SD-JWT with keyResolver', async () => { + const keypair = createIssuerKeypair(); + const credential = await issueTestSdJwt(keypair, { + iss: ISSUER_DID, + iat: 1700000000, + exp: 1800000000, + vct: 'InternalTesting', + id: 'did:example:subject', + name: 'maycon', + date: '2025-10-09', + number: 123, + }); - const result = await verifySDJWT(expiredJWT); + const result = await verifySDJWT(credential, ['name'], { + keyResolver: createKeyResolver(keypair), + }); - expect(result.verified).toBe(false); - expect(result.error).toContain('expired'); + expect(result.verified).toBe(true); + expect(result.error).toBeUndefined(); + expect(result.credentialResults[0]).toMatchObject({ + issuer: 'did:ex:issuer', + type: ['InternalTesting'], + credentialSubject: { + name: 'maycon', + }, + }); }); - it('should fail verification for not-yet-valid SD-JWT', async () => { - // Create an SD-JWT with nbf in the future - const futureJWT = 'eyJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTppc3N1ZXIiLCJ2Y3QiOiJUZXN0Q3JlZGVudGlhbCIsIm5iZiI6OTk5OTk5OTk5OSwiaWF0IjoxNjA5NDU5MjAwfQ.signature~'; + it('should fail verification when issuer key cannot be resolved', async () => { + const keypair = createIssuerKeypair(); + const credential = await issueTestSdJwt(keypair, { + iss: ISSUER_DID, + iat: 1700000000, + vct: 'InternalTesting', + name: 'maycon', + }, {_sd: ['name']}); - const result = await verifySDJWT(futureJWT); + const result = await verifySDJWT(credential, undefined, { + keyResolver: async () => null, + }); expect(result.verified).toBe(false); - expect(result.error).toContain('not yet valid'); + expect(result.error).toBeDefined(); }); it('should fail verification for invalid SD-JWT format', async () => { @@ -437,11 +513,24 @@ describe('SD-JWT Service', () => { expect(result.error).toBeDefined(); }); - it('should verify SD-JWT without expiration date', async () => { - // The TEST_SD_JWT doesn't have an expiration date, so it should verify - const result = await verifySDJWT(TEST_SD_JWT); + it('should fail verification with wrong issuer key', async () => { + const issuerKeypair = createIssuerKeypair(); + const wrongKeypair = Ed25519Keypair.fromSeed( + Uint8Array.from({length: Ed25519Keypair.SeedSize}, (_, index) => index + 9), + ); + const credential = await issueTestSdJwt(issuerKeypair, { + iss: ISSUER_DID, + iat: 1700000000, + vct: 'InternalTesting', + name: 'maycon', + }, {_sd: ['name']}); + + const result = await verifySDJWT(credential, undefined, { + keyResolver: createKeyResolver(wrongKeypair), + }); - expect(result.verified).toBe(true); + expect(result.verified).toBe(false); + expect(result.error).toBeDefined(); }); it('should return error message on verification failure', async () => { @@ -602,25 +691,44 @@ describe('SD-JWT Service', () => { }); it('should preserve presentation format for verification flow', async () => { + const keypair = createIssuerKeypair(); + const credential = await issueTestSdJwt(keypair, { + iss: ISSUER_DID, + iat: 1700000000, + vct: 'InternalTesting', + name: 'maycon', + date: '2025-10-09', + }, {_sd: ['name', 'date']}); + const presentation = await createSDJWTPresentation({ attributesToReveal: ['name', 'date'], - credential: TEST_SD_JWT, + credential, }); - // The presentation should be verifiable - const verificationResult = await verifySDJWT(presentation); + const verificationResult = await verifySDJWT(presentation, undefined, { + keyResolver: createKeyResolver(keypair), + }); expect(verificationResult.verified).toBe(true); }); }); describe('Presentation Integration Tests', () => { it('should complete full flow: store credential -> create presentation -> verify', async () => { + const keypair = createIssuerKeypair(); + const issued = await issueTestSdJwt(keypair, { + iss: ISSUER_DID, + iat: 1700000000, + vct: 'InternalTesting', + name: 'maycon', + date: '2025-10-09', + }, {_sd: ['name', 'date']}); + // Step 1: Convert SD-JWT to W3C format (as done in addCredential) - const w3cCredential = await decodeSDJWTToW3C(TEST_SD_JWT) as any; + const w3cCredential = await decodeSDJWTToW3C(issued) as any; // Verify metadata is stored expect(w3cCredential._sd_jwt).toBeDefined(); - expect(w3cCredential._sd_jwt.encoded).toBe(TEST_SD_JWT); + expect(w3cCredential._sd_jwt.encoded).toBe(issued); // Step 2: Create presentation from stored credential (as done in verification-controller) const presentation = await createSDJWTPresentation({ @@ -630,8 +738,10 @@ describe('SD-JWT Service', () => { expect(typeof presentation).toBe('string'); - // Step 3: Verify presentation - const verificationResult = await verifySDJWT(presentation); + // Step 3: Verify presentation cryptographically + const verificationResult = await verifySDJWT(presentation, undefined, { + keyResolver: createKeyResolver(keypair), + }); expect(verificationResult.verified).toBe(true); // Step 4: Decode presentation to check disclosed claims @@ -643,16 +753,26 @@ describe('SD-JWT Service', () => { }); it('should support multiple presentation creations from same credential', async () => { + const keypair = createIssuerKeypair(); + const credential = await issueTestSdJwt(keypair, { + iss: ISSUER_DID, + iat: 1700000000, + vct: 'InternalTesting', + name: 'maycon', + date: '2025-10-09', + number: 123, + }, {_sd: ['name', 'date', 'number']}); + // Create first presentation with some attributes const presentation1 = await createSDJWTPresentation({ attributesToReveal: ['name'], - credential: TEST_SD_JWT, + credential, }); // Create second presentation with different attributes const presentation2 = await createSDJWTPresentation({ attributesToReveal: ['date', 'number'], - credential: TEST_SD_JWT, + credential, }); // Both should be valid @@ -662,9 +782,10 @@ describe('SD-JWT Service', () => { // They should be different (different disclosures) expect(presentation1).not.toBe(presentation2); - // Both should verify - const result1 = await verifySDJWT(presentation1); - const result2 = await verifySDJWT(presentation2); + // Both should verify cryptographically + const keyResolver = createKeyResolver(keypair); + const result1 = await verifySDJWT(presentation1, undefined, {keyResolver}); + const result2 = await verifySDJWT(presentation2, undefined, {keyResolver}); expect(result1.verified).toBe(true); expect(result2.verified).toBe(true); diff --git a/packages/wasm/src/services/credential/sd-jwt.ts b/packages/wasm/src/services/credential/sd-jwt.ts index 2dea1579..11ff8ecb 100644 --- a/packages/wasm/src/services/credential/sd-jwt.ts +++ b/packages/wasm/src/services/credential/sd-jwt.ts @@ -1,6 +1,13 @@ +// @ts-nocheck +import { + decodeSdJwt, + isSDJWTCredential as isCompactSDJWTCredential, + verifySDJWTCredential, +} from '@docknetwork/crypto-utils'; import {SDJwtVcInstance} from '@sd-jwt/sd-jwt-vc'; import {digest, generateSalt} from '@sd-jwt/crypto-nodejs'; -import base64url from 'base64url'; + +export {verifySDJWTCredential}; /** * Checks if a value is a decoded SD-JWT payload object — i.e. an SD-JWT VC @@ -25,18 +32,7 @@ export function isSDJWTCredential(credential) { return true; } - if (typeof credential !== 'string' || !credential.includes('.')) { - return false; - } - - try { - const decodedHeader = JSON.parse(base64url.decode(credential.split('.')[0])); - return ( - decodedHeader?.typ === 'dc+sd-jwt' || decodedHeader?.typ === 'vc+sd-jwt' - ); - } catch { - return false; - } + return isCompactSDJWTCredential(credential); } export async function createSDJWTPresentation({ @@ -66,71 +62,34 @@ export async function createSDJWTPresentation({ return presentation; } + /** * Decodes an SD-JWT string into its structured format * @param {string} sdJwtString - The SD-JWT string to decode * @returns {Promise} Decoded SD-JWT structure with jwt and disclosures */ export async function decodeSDJWT(sdJwtString) { - // Create SD-JWT instance with minimal configuration (no verification needed for decoding) - const sdjwt = new SDJwtVcInstance({ - signAlg: 'EdDSA', - hasher: digest, - hashAlg: 'sha-256', - saltGenerator: generateSalt, - }); - - // Decode the SD-JWT - return await sdjwt.decode(sdJwtString); + return decodeSdJwt(sdJwtString); } /** * Verifies an SD-JWT credential - * @param {string} jwt - The SD-JWT string to verify - * @returns {Promise} Verification result with verified status and optional error - * @returns {boolean} returns.verified - Whether the credential is valid - * @returns {string} [returns.error] - Error message if verification failed + * @param {string|{jwt: string}} jwt - The SD-JWT string (or `{jwt}`) to verify + * @param {string[]} [requiredAttribs] - Required disclosed claim keys + * @param {object} [options] + * @param {function} [options.keyResolver] async (issOrKid) => verification key + * @param {function} [options.documentLoader] (uri) => Promise<{document}> + * @param {{supports: function, resolve: function}} [options.resolver] + * @param {string[]} [options.algorithms] + * @returns {Promise} Verification result */ -export async function verifySDJWT(jwt) { +export async function verifySDJWT(jwt, requiredAttribs?, options = {}) { try { - // Decode the SD-JWT - const decoded = await decodeSDJWT(jwt); - - // Extract payload for validation - const payload: any = decoded.jwt.payload; - - // Check expiration date if present - if (payload.exp) { - const now = Math.floor(Date.now() / 1000); - const exp = Number(payload.exp); - if (now > exp) { - return { - verified: false, - error: 'SD-JWT credential has expired', - }; - } - } - - // Check not-before date if present - if (payload.nbf) { - const now = Math.floor(Date.now() / 1000); - const nbf = Number(payload.nbf); - if (now < nbf) { - return { - verified: false, - error: 'SD-JWT credential is not yet valid', - }; - } - } - - // If we successfully decoded and passed date checks, consider it verified - return { - verified: true, - }; + return await verifySDJWTCredential(jwt, requiredAttribs, options); } catch (error) { return { verified: false, - error: error.message || 'Failed to verify SD-JWT credential', + error: error?.message || 'Failed to verify SD-JWT credential', }; } } @@ -145,7 +104,6 @@ export function sdJwtToW3C(decodedSDJWT, encodedSDJWT?) { const {jwt, disclosures} = decodedSDJWT; // The jwt object already has header and payload parsed - const header = jwt.header; const payload = jwt.payload; // Build credential subject from disclosed claims diff --git a/packages/wasm/src/services/credential/service.ts b/packages/wasm/src/services/credential/service.ts index 8d5a5a64..c09c2615 100644 --- a/packages/wasm/src/services/credential/service.ts +++ b/packages/wasm/src/services/credential/service.ts @@ -26,6 +26,7 @@ import { VerifiableCredential, StatusList2021Credential, getSuiteFromKeyDoc, + documentLoader, } from '@docknetwork/credential-sdk/vc'; import {PEX} from '@sphereon/pex'; import {keyDocToKeypair} from './utils'; @@ -374,12 +375,22 @@ class CredentialService { validation.verifyCredential(params); let {credential, membershipWitness} = params; - if (credential._sd_jwt) { - credential = credential?._sd_jwt?.encoded; + if (credential?._sd_jwt) { + const encoded = credential._sd_jwt.encoded; + if (typeof encoded !== 'string' || !encoded) { + return { + verified: false, + error: + 'SD-JWT credential is missing compact serialization required for verification', + }; + } + credential = encoded; } if (typeof credential === 'string' && checkIsSDJWT(credential)) { - return verifySDJWT(credential); + return verifySDJWT(credential, undefined, { + documentLoader: documentLoader(blockchainService.resolver), + }); } const isStatusList2021 =