diff --git a/package-lock.json b/package-lock.json index 2a2cc687d..ecc017d0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1585,6 +1585,13 @@ "@tybys/wasm-util": "^0.9.0" } }, + "node_modules/@neon-rs/load": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.1.82.tgz", + "integrity": "sha512-H4Gu2o5kPp+JOEhRrOQCnJnf7X6sv9FBLttM/wSbb4efsgFWeHzfU/ItZ01E5qqEk+U6QGdeVO7lxXIAtYHr5A==", + "dev": true, + "license": "MIT" + }, "node_modules/@nmshd/app-runtime": { "resolved": "packages/app-runtime", "link": true @@ -1602,21 +1609,119 @@ "link": true }, "node_modules/@nmshd/crypto": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@nmshd/crypto/-/crypto-2.1.2.tgz", - "integrity": "sha512-DbcBnqPAeviaMiIG7G1QaICvoAS3xNMdW/CWoig1XJAbRcpeVRQ3LpKZSgt5XwDc8xl+0j3Ork/HDWijk3rlNw==", + "version": "2.2.0-alpha.8", + "resolved": "https://registry.npmjs.org/@nmshd/crypto/-/crypto-2.2.0-alpha.8.tgz", + "integrity": "sha512-hlYfSXNy4gX23AZf90X9iC4v00UhXcqK1X2z7SYKqRGc00AK+OLi+j9ioH5ENdzum02x9gegF6qAIdzzixb4+A==", "license": "MIT", "dependencies": { + "@nmshd/rs-crypto-types": "^0.12.1", "libsodium-wrappers-sumo": "0.7.15", "uuid": "^11.1.0" } }, + "node_modules/@nmshd/crypto/node_modules/@nmshd/rs-crypto-types": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@nmshd/rs-crypto-types/-/rs-crypto-types-0.12.1.tgz", + "integrity": "sha512-tNcFwArHTLlFpeVdFuErSsIqa3xrc5PLmQeU453VLAI13UrG8wBh7Z+Wz29YWZFQtM1P4AcOnhzkhV6cRlZn9w==", + "license": "MIT", + "dependencies": { + "typia": "^8.0.3" + } + }, "node_modules/@nmshd/iql": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@nmshd/iql/-/iql-1.0.3.tgz", "integrity": "sha512-gTc69pUQrxjN8kajwfcg9+6/HCRrEcIURKkGtCc/5CqYf6Owq3F1AwPX31BPAopnB/ElvkNpzM1MntohXUe2vA==", "license": "MIT" }, + "node_modules/@nmshd/rs-crypto-node": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@nmshd/rs-crypto-node/-/rs-crypto-node-0.14.0.tgz", + "integrity": "sha512-oulGjidoe25cTnvUNL8lYO0LoJsSwgWVql7THMBolz531WKeB8fgp6Z4AOdAAh9NLtPPpUaIKbTirU8n3UaeOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@neon-rs/load": "^0.1.73", + "@nmshd/rs-crypto-types": "^0.11.0" + }, + "optionalDependencies": { + "@nmshd/darwin-arm64": "0.14.0", + "@nmshd/darwin-x64": "0.14.0", + "@nmshd/linux-arm64-gnu": "0.14.0", + "@nmshd/linux-x64-gnu": "0.14.0", + "@nmshd/rs-crypto-node-darwin-arm64": "0.14.0", + "@nmshd/rs-crypto-node-darwin-x64": "0.14.0", + "@nmshd/rs-crypto-node-linux-x64-gnu": "0.14.0", + "@nmshd/rs-crypto-node-win32-x64-msvc": "0.14.0", + "@nmshd/win32-x64-msvc": "0.14.0" + } + }, + "node_modules/@nmshd/rs-crypto-node-darwin-arm64": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@nmshd/rs-crypto-node-darwin-arm64/-/rs-crypto-node-darwin-arm64-0.14.0.tgz", + "integrity": "sha512-GM0wnInGFd+9dyO/RUpk7AQzmjca0VBzlTM/SSRNObDcx7Riwl9kccp7UwTVnM3YVGybnyot1nOI+LXYfrUbCw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@nmshd/rs-crypto-node-darwin-x64": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@nmshd/rs-crypto-node-darwin-x64/-/rs-crypto-node-darwin-x64-0.14.0.tgz", + "integrity": "sha512-3bF8eDkug4LPrFfIxqOqubpMm4M9vyBYE3HgXfbWDHHz0iRSxwGPvwBzyXes2V/HMRpYKjqG5XQdeSOjuMemGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@nmshd/rs-crypto-node-linux-x64-gnu": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@nmshd/rs-crypto-node-linux-x64-gnu/-/rs-crypto-node-linux-x64-gnu-0.14.0.tgz", + "integrity": "sha512-FMi4nMGiiWmzF39ZJOj1AhyZ5MAv4PsotZpRJiIZ1rkNOnTOeQSDj//85GXXv4i715TBJwLSp3eelkt+9xlqkw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@nmshd/rs-crypto-node-win32-x64-msvc": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@nmshd/rs-crypto-node-win32-x64-msvc/-/rs-crypto-node-win32-x64-msvc-0.14.0.tgz", + "integrity": "sha512-09+Ov2Z30n3YUkHvcpf2bYJlV8GYesOaS3dWNCRAiseGmqduIWp/GQZZvAUHWslHhGKpT84fXy6HO5j8HrtOLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@nmshd/rs-crypto-types": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@nmshd/rs-crypto-types/-/rs-crypto-types-0.11.0.tgz", + "integrity": "sha512-xP/NQhK3I2ui0j6IsIlAJ0FJKRW1Av7gZzdAiBoFpCE1OhENt2lTdh5ilgGCKR4ddPhaDLIvaBkTTbQU0tUOOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "typia": "^8.0.3" + } + }, "node_modules/@nmshd/runtime": { "resolved": "packages/runtime", "link": true @@ -2015,6 +2120,12 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@samchon/openapi": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@samchon/openapi/-/openapi-3.3.0.tgz", + "integrity": "sha512-f8HMS0PVAKTGR0TwgiBX4PKlZRPfdtH5fJbtpUth3fMUZmikjZ7CBey8gX7HZgY4n/aYHyNQKcf/W/E2267oYw==", + "license": "MIT" + }, "node_modules/@sigstore/bundle": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.1.0.tgz", @@ -2444,6 +2555,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/tmp": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", + "integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/uuid": { "version": "10.0.0", "dev": true, @@ -3097,7 +3215,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.21.3" @@ -3113,7 +3230,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -3124,7 +3240,6 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3132,7 +3247,6 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -3313,6 +3427,12 @@ "node": ">=0.10.0" } }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "license": "MIT" + }, "node_modules/array-union": { "version": "2.1.0", "dev": true, @@ -3554,7 +3674,6 @@ }, "node_modules/base64-js": { "version": "1.5.1", - "dev": true, "funding": [ { "type": "github", @@ -3581,7 +3700,6 @@ }, "node_modules/bl": { "version": "4.1.0", - "dev": true, "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -3673,7 +3791,6 @@ }, "node_modules/buffer": { "version": "5.7.1", - "dev": true, "funding": [ { "type": "github", @@ -3897,7 +4014,6 @@ }, "node_modules/chalk": { "version": "4.1.2", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -3920,6 +4036,12 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "license": "MIT" + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -3955,7 +4077,6 @@ }, "node_modules/cli-cursor": { "version": "3.1.0", - "dev": true, "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" @@ -3966,7 +4087,6 @@ }, "node_modules/cli-spinners": { "version": "2.9.2", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3975,6 +4095,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, "node_modules/cliui": { "version": "8.0.1", "dev": true, @@ -4006,7 +4135,6 @@ }, "node_modules/clone": { "version": "1.0.4", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8" @@ -4032,7 +4160,6 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -4043,7 +4170,6 @@ }, "node_modules/color-name": { "version": "1.1.4", - "dev": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -4064,6 +4190,22 @@ "node": ">= 10" } }, + "node_modules/comment-json": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", + "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/commondir": { "version": "1.0.1", "dev": true, @@ -4134,7 +4276,6 @@ }, "node_modules/core-util-is": { "version": "1.0.3", - "dev": true, "license": "MIT" }, "node_modules/correlation-id": { @@ -4310,7 +4451,6 @@ }, "node_modules/defaults": { "version": "1.0.4", - "dev": true, "license": "MIT", "dependencies": { "clone": "^1.0.2" @@ -4677,6 +4817,15 @@ "node": ">=6.0.0" } }, + "node_modules/drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "license": "MIT", @@ -4730,7 +4879,6 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, "license": "MIT" }, "node_modules/encoding": { @@ -5114,7 +5262,6 @@ }, "node_modules/esprima": { "version": "4.0.1", - "dev": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -5267,6 +5414,44 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "license": "MIT" @@ -5336,6 +5521,30 @@ "bser": "2.1.1" } }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "dev": true, @@ -5784,7 +5993,15 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", "license": "MIT", "engines": { "node": ">=8" @@ -5908,7 +6125,6 @@ }, "node_modules/ieee754": { "version": "1.2.1", - "dev": true, "funding": [ { "type": "github", @@ -6000,7 +6216,6 @@ }, "node_modules/inherits": { "version": "2.0.4", - "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -6013,6 +6228,32 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/ip-address": { "version": "9.0.5", "dev": true, @@ -6056,7 +6297,6 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6085,7 +6325,6 @@ }, "node_modules/is-interactive": { "version": "1.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6136,7 +6375,6 @@ }, "node_modules/is-unicode-supported": { "version": "0.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -7247,7 +7485,6 @@ }, "node_modules/log-symbols": { "version": "4.1.0", - "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", @@ -7458,7 +7695,6 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7755,6 +7991,12 @@ "version": "2.1.3", "license": "MIT" }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "license": "ISC" + }, "node_modules/nan": { "version": "2.22.0", "dev": true, @@ -8132,7 +8374,6 @@ }, "node_modules/onetime": { "version": "5.1.2", - "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -8162,7 +8403,6 @@ }, "node_modules/ora": { "version": "5.4.1", - "dev": true, "license": "MIT", "dependencies": { "bl": "^4.1.0", @@ -8192,7 +8432,6 @@ }, "node_modules/os-tmpdir": { "version": "1.0.2", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8263,6 +8502,15 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/package-manager-detector": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", + "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", + "license": "MIT", + "dependencies": { + "quansync": "^0.2.7" + } + }, "node_modules/pacote": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.0.0.tgz", @@ -8796,6 +9044,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", + "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "dev": true, @@ -8830,6 +9094,19 @@ "dev": true, "license": "MIT" }, + "node_modules/randexp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", + "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", + "license": "MIT", + "dependencies": { + "drange": "^1.0.2", + "ret": "^0.2.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/rc": { "version": "1.2.8", "dev": true, @@ -8933,7 +9210,6 @@ }, "node_modules/readable-stream": { "version": "3.6.2", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -8978,6 +9254,15 @@ "version": "0.2.2", "license": "Apache-2.0" }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/require-directory": { "version": "2.1.1", "dev": true, @@ -9074,7 +9359,6 @@ }, "node_modules/restore-cursor": { "version": "3.1.0", - "dev": true, "license": "MIT", "dependencies": { "onetime": "^5.1.0", @@ -9084,6 +9368,15 @@ "node": ">=8" } }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/retry": { "version": "0.12.0", "dev": true, @@ -9120,6 +9413,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "dev": true, @@ -9142,9 +9444,17 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", - "dev": true, "funding": [ { "type": "github", @@ -9171,7 +9481,6 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", - "dev": true, "license": "MIT" }, "node_modules/sass-lookup": { @@ -9294,7 +9603,6 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "dev": true, "license": "ISC" }, "node_modules/sigstore": { @@ -9570,7 +9878,6 @@ }, "node_modules/string_decoder": { "version": "1.3.0", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -9592,7 +9899,6 @@ }, "node_modules/string-width": { "version": "4.2.3", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -9632,7 +9938,6 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -9708,7 +10013,6 @@ }, "node_modules/supports-color": { "version": "7.2.0", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -9954,6 +10258,12 @@ "dev": true, "license": "MIT" }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", @@ -10338,7 +10648,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD" }, "node_modules/tuf-js": { @@ -10397,7 +10706,6 @@ "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -10418,6 +10726,36 @@ "typescript-logging": "~2.2.0" } }, + "node_modules/typia": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/typia/-/typia-8.2.0.tgz", + "integrity": "sha512-DAQl9CLItDwMd4k4HnaExxv6wjBFLW04WqGBQEnOpylq2YmZsM6HTj4Bfxxp3wtgAsMXZTugAdQRPsFOxMiRrQ==", + "license": "MIT", + "dependencies": { + "@samchon/openapi": "^3.3.0", + "commander": "^10.0.0", + "comment-json": "^4.2.3", + "inquirer": "^8.2.5", + "package-manager-detector": "^0.2.0", + "randexp": "^0.5.3" + }, + "bin": { + "typia": "lib/executable/typia.js" + }, + "peerDependencies": { + "@samchon/openapi": ">=3.3.0 <4.0.0", + "typescript": ">=4.8.0 <5.9.0" + } + }, + "node_modules/typia/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/undici": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.11.0.tgz", @@ -10545,7 +10883,6 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "dev": true, "license": "MIT" }, "node_modules/util-extend": { @@ -10621,7 +10958,6 @@ }, "node_modules/wcwidth": { "version": "1.0.1", - "dev": true, "license": "MIT", "dependencies": { "defaults": "^1.0.3" @@ -10669,6 +11005,20 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", @@ -10873,7 +11223,7 @@ "@js-soft/docdb-access-loki": "1.3.0", "@js-soft/docdb-access-mongo": "1.3.0", "@js-soft/node-logger": "1.2.0", - "@nmshd/crypto": "2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "@types/lodash": "^4.17.20", "ts-mockito": "^2.6.1" } @@ -10889,7 +11239,7 @@ "ts-simple-nameof": "^1.3.1" }, "devDependencies": { - "@nmshd/crypto": "2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "@types/luxon": "^3.6.2" } }, @@ -10899,7 +11249,7 @@ "dependencies": { "@js-soft/logging-abstractions": "^1.0.1", "@js-soft/ts-serval": "2.0.12", - "@nmshd/crypto": "^2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "json-stringify-safe": "^5.0.1", "luxon": "^3.7.1" }, @@ -10918,7 +11268,7 @@ "@nmshd/consumption": "*", "@nmshd/content": "*", "@nmshd/core-types": "*", - "@nmshd/crypto": "2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "@nmshd/iql": "^1.0.3", "@nmshd/runtime-types": "*", "@nmshd/transport": "*", @@ -10936,6 +11286,7 @@ "@js-soft/docdb-access-loki": "1.3.0", "@js-soft/docdb-access-mongo": "1.3.0", "@js-soft/node-logger": "1.2.0", + "@nmshd/rs-crypto-node": "0.14.0", "@types/json-stringify-safe": "^5.0.3", "@types/lodash": "^4.17.20", "@types/luxon": "^3.6.2", @@ -10982,7 +11333,7 @@ "@js-soft/simple-logger": "1.0.5", "@js-soft/ts-utils": "^2.3.3", "@nmshd/core-types": "*", - "@nmshd/crypto": "2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "axios": "^1.10.0", "fast-json-patch": "^3.1.1", "form-data": "^4.0.3", @@ -11000,10 +11351,12 @@ "@js-soft/docdb-access-mongo": "1.3.0", "@js-soft/node-logger": "1.2.0", "@js-soft/ts-serval": "2.0.12", + "@nmshd/rs-crypto-node": "0.14.0", "@types/json-stringify-safe": "^5.0.3", "@types/lodash": "^4.17.20", "@types/luxon": "^3.6.2", "@types/qs": "^6.14.0", + "@types/tmp": "0.2.6", "@types/uuid": "^10.0.0", "correlation-id": "^5.2.0", "expect": "^30.0.4", diff --git a/packages/app-runtime/src/AppConfig.ts b/packages/app-runtime/src/AppConfig.ts index 3aee21a32..9d57de1ef 100644 --- a/packages/app-runtime/src/AppConfig.ts +++ b/packages/app-runtime/src/AppConfig.ts @@ -1,3 +1,5 @@ +import { StorageConfig } from "@nmshd/crypto"; +import { ProviderFactoryFunctions } from "@nmshd/rs-crypto-types"; import { RuntimeConfig } from "@nmshd/runtime"; import { IConfigOverwrite } from "@nmshd/transport"; import { defaultsDeep } from "lodash"; @@ -20,6 +22,8 @@ export interface AppConfigOverwrite { allowMultipleAccountsWithSameAddress?: boolean; databaseFolder?: string; modules?: Record; + calFactory?: ProviderFactoryFunctions; + calStorageConfig?: StorageConfig; } export function createAppConfig(...configs: (AppConfigOverwrite | AppConfig)[]): AppConfig { diff --git a/packages/consumption/package.json b/packages/consumption/package.json index 12469df9a..dc848045c 100644 --- a/packages/consumption/package.json +++ b/packages/consumption/package.json @@ -73,7 +73,7 @@ "@js-soft/docdb-access-loki": "1.3.0", "@js-soft/docdb-access-mongo": "1.3.0", "@js-soft/node-logger": "1.2.0", - "@nmshd/crypto": "2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "@types/lodash": "^4.17.20", "ts-mockito": "^2.6.1" }, diff --git a/packages/content/package.json b/packages/content/package.json index 1d6a045f4..7ddf8d082 100644 --- a/packages/content/package.json +++ b/packages/content/package.json @@ -58,8 +58,8 @@ "ts-simple-nameof": "^1.3.1" }, "devDependencies": { - "@types/luxon": "^3.6.2", - "@nmshd/crypto": "2.1.2" + "@nmshd/crypto": "^2.2.0-alpha.8", + "@types/luxon": "^3.6.2" }, "publishConfig": { "access": "public", diff --git a/packages/core-types/package.json b/packages/core-types/package.json index 03728360c..1c8f0d605 100644 --- a/packages/core-types/package.json +++ b/packages/core-types/package.json @@ -51,7 +51,7 @@ "dependencies": { "@js-soft/logging-abstractions": "^1.0.1", "@js-soft/ts-serval": "2.0.12", - "@nmshd/crypto": "^2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "json-stringify-safe": "^5.0.1", "luxon": "^3.7.1" }, diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 1d8619a6d..ed58597c6 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -67,7 +67,7 @@ "@nmshd/consumption": "*", "@nmshd/content": "*", "@nmshd/core-types": "*", - "@nmshd/crypto": "2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "@nmshd/iql": "^1.0.3", "@nmshd/runtime-types": "*", "@nmshd/transport": "*", @@ -85,6 +85,7 @@ "@js-soft/docdb-access-loki": "1.3.0", "@js-soft/docdb-access-mongo": "1.3.0", "@js-soft/node-logger": "1.2.0", + "@nmshd/rs-crypto-node": "0.14.0", "@types/json-stringify-safe": "^5.0.3", "@types/lodash": "^4.17.20", "@types/luxon": "^3.6.2", diff --git a/packages/runtime/src/Runtime.ts b/packages/runtime/src/Runtime.ts index f703836ab..74aec796a 100644 --- a/packages/runtime/src/Runtime.ts +++ b/packages/runtime/src/Runtime.ts @@ -13,6 +13,7 @@ import { SettingsController } from "@nmshd/consumption"; import { ICoreAddress } from "@nmshd/core-types"; +import { initializeProviders, newInitializedProviders, ProviderInitConfig } from "@nmshd/crypto"; import { RuntimeHealth } from "@nmshd/runtime-types"; import { AccountController, @@ -144,6 +145,29 @@ export abstract class Runtime { this.databaseConnection = await this.createDatabaseConnection(); + if (this.runtimeConfig.calFactory && this.runtimeConfig.calStorageConfig) { + this.logger.trace("Initializing Crypto Layer"); + const calDB = await this.databaseConnection.getDatabase("cryptoConfig"); + const calMap = await calDB.getMap("calConfig"); + const calConfig = await calMap.get("initializedProviders"); + if (calConfig === null) { + this.logger.trace("Initializing Crypto Layer with new config"); + const calConfig = await newInitializedProviders(this.runtimeConfig.calStorageConfig, this.runtimeConfig.calFactory); + if (!calConfig) { + throw RuntimeErrors.startup.failedCalInit(); + } + const serializedConfig = calConfig.serialize(); + await calMap.set("initializedProviders", serializedConfig); + } else { + this.logger.trace("Initializing Crypto Layer with saved config"); + const calConfigloaded = ProviderInitConfig.deserialize(calConfig); + await initializeProviders(calConfigloaded, this.runtimeConfig.calStorageConfig, this.runtimeConfig.calFactory); + } + this.logger.trace("Crypto Layer initialized"); + } else { + this.logger.trace("No Crypto Layer configuration provided, skipping initialization."); + } + await this.initTransportLibrary(); await this.initAccount(); diff --git a/packages/runtime/src/RuntimeConfig.ts b/packages/runtime/src/RuntimeConfig.ts index d0b43014d..21a889311 100644 --- a/packages/runtime/src/RuntimeConfig.ts +++ b/packages/runtime/src/RuntimeConfig.ts @@ -1,3 +1,5 @@ +import { StorageConfig } from "@nmshd/crypto"; +import { ProviderFactoryFunctions } from "@nmshd/rs-crypto-types"; import { IConfigOverwrite } from "@nmshd/transport"; import { ModuleConfiguration } from "./extensibility/modules/RuntimeModule"; import { DeciderModuleConfiguration } from "./modules"; @@ -7,4 +9,6 @@ export interface RuntimeConfig { modules: Record & { decider: DeciderModuleConfiguration; }; + calFactory?: ProviderFactoryFunctions; + calStorageConfig?: StorageConfig; } diff --git a/packages/runtime/src/useCases/common/RuntimeErrors.ts b/packages/runtime/src/useCases/common/RuntimeErrors.ts index 966b82b7d..b98555982 100644 --- a/packages/runtime/src/useCases/common/RuntimeErrors.ts +++ b/packages/runtime/src/useCases/common/RuntimeErrors.ts @@ -169,6 +169,10 @@ class Startup { public noActiveExpander(): ApplicationError { return new ApplicationError("error.runtime.startup.noActiveExpander", "No DataViewExpander could be found. You might have to login first."); } + + public failedCalInit(): ApplicationError { + return new ApplicationError("error.runtime.startup.failedCalInit", "Initialising Crypto Abtraction Layer failed."); + } } class Challenges { diff --git a/packages/transport/package.json b/packages/transport/package.json index 29bb7c42c..421c9c18c 100644 --- a/packages/transport/package.json +++ b/packages/transport/package.json @@ -71,7 +71,7 @@ "@js-soft/simple-logger": "1.0.5", "@js-soft/ts-utils": "^2.3.3", "@nmshd/core-types": "*", - "@nmshd/crypto": "2.1.2", + "@nmshd/crypto": "^2.2.0-alpha.8", "axios": "^1.10.0", "fast-json-patch": "^3.1.1", "form-data": "^4.0.3", @@ -89,10 +89,12 @@ "@js-soft/docdb-access-mongo": "1.3.0", "@js-soft/node-logger": "1.2.0", "@js-soft/ts-serval": "2.0.12", + "@nmshd/rs-crypto-node": "0.14.0", "@types/json-stringify-safe": "^5.0.3", "@types/lodash": "^4.17.20", "@types/luxon": "^3.6.2", "@types/qs": "^6.14.0", + "@types/tmp": "0.2.6", "@types/uuid": "^10.0.0", "correlation-id": "^5.2.0", "expect": "^30.0.4", diff --git a/packages/transport/src/core/CoreCrypto.ts b/packages/transport/src/core/CoreCrypto.ts index 10a7dd033..29f666fb0 100644 --- a/packages/transport/src/core/CoreCrypto.ts +++ b/packages/transport/src/core/CoreCrypto.ts @@ -3,8 +3,10 @@ import { CryptoCipher, CryptoDerivation, CryptoDerivationAlgorithm, + CryptoDerivationHandle, CryptoEncryption, CryptoEncryptionAlgorithm, + CryptoEncryptionHandle, CryptoExchange, CryptoExchangeAlgorithm, CryptoExchangeKeypair, @@ -19,7 +21,12 @@ import { CryptoSignaturePrivateKey, CryptoSignaturePublicKey, CryptoSignatures, - Encoding + DeviceBoundDerivedKeyHandle, + DeviceBoundKeyHandle, + Encoding, + PortableDerivedKeyHandle, + PortableKeyHandle, + CryptoLayerProviderIdentifier as ProviderIdentifier } from "@nmshd/crypto"; import { PasswordGenerator } from "../util"; import { TransportError } from "./TransportError"; @@ -81,6 +88,74 @@ export abstract class CoreCrypto { } } + /** + * Generates a handle-based secret key for symmetric encryption. + * Depending on the given version, different algorithms are used: + * + * v1: AES256_GCM + * + * @param providerIdent The provider identifier + * @param version The version which should be used, "latest" is the default. + * @returns A Promise object resolving into a new CryptoSecretKeyHandle. + */ + public static async generateDeviceBoundKeyHandle(providerIdent: ProviderIdentifier, version: TransportVersion = TransportVersion.Latest): Promise { + switch (version) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + case TransportVersion.V1: + return await CryptoEncryptionHandle.generateDeviceBoundKeyHandle(providerIdent, CryptoEncryptionAlgorithm.XCHACHA20_POLY1305, CryptoHashAlgorithm.SHA512); + default: + throw this.invalidVersion(version); + } + } + + /** + * Generates a handle-based secret key for symmetric encryption. + * Depending on the given version, different algorithms are used: + * + * v1: AES256_GCM + * + * @param providerIdent The provider identifier + * @param version The version which should be used, "latest" is the default. + * @returns A Promise object resolving into a new CryptoSecretKeyHandle. + */ + public static async generatePortableKeyHandle(providerIdent: ProviderIdentifier, version: TransportVersion = TransportVersion.Latest): Promise { + switch (version) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + case TransportVersion.V1: + return await CryptoEncryptionHandle.generatePortableKeyHandle(providerIdent, CryptoEncryptionAlgorithm.XCHACHA20_POLY1305, CryptoHashAlgorithm.SHA512); + default: + throw this.invalidVersion(version); + } + } + + /** + * Generates a handle-based secret key for symmetric encryption. + * Depending on the given version, different algorithms are used: + * + * v1: AES256_GCM + * + * @param providerIdent The provider identifier + * @param version The version which should be used, "latest" is the default. + * @returns A Promise object resolving into a new CryptoSecretKeyHandle. + */ + public static async generateDeviceBoundDerivationHandle(baseKey: DeviceBoundKeyHandle, keyId: number, context: string): Promise { + return await CryptoDerivationHandle.deriveDeviceBoundKeyHandle(baseKey, keyId, context); + } + + /** + * Generates a handle-based secret key for symmetric encryption. + * Depending on the given version, different algorithms are used: + * + * v1: AES256_GCM + * + * @param providerIdent The provider identifier + * @param version The version which should be used, "latest" is the default. + * @returns A Promise object resolving into a new CryptoSecretKeyHandle. + */ + public static async generatePortableDerivationHandle(baseKey: PortableKeyHandle, keyId: number, context: string): Promise { + return await CryptoDerivationHandle.derivePortableKeyHandle(baseKey, keyId, context); + } + /** * Generates a high entropy key / hash derived from a low entropy human readable/memorable master password, a unique salt, * the given symmetric algorithm and the version. Depending on the given version, different key derivation algorithms are used. diff --git a/packages/transport/src/core/CryptoProviderMapping.ts b/packages/transport/src/core/CryptoProviderMapping.ts new file mode 100644 index 000000000..4169b5cb8 --- /dev/null +++ b/packages/transport/src/core/CryptoProviderMapping.ts @@ -0,0 +1,171 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { DeviceBoundKeyHandle, hasProviderForSecurityLevel, PortableKeyHandle } from "@nmshd/crypto"; +import { SecurityLevel } from "@nmshd/rs-crypto-types"; +import { CoreCrypto } from "./CoreCrypto"; + +export const CryptoProviderTypes = { + Software: "Software", + Hardware: "Hardware", + Network: "Network", + Legacy: "Legacy" +} as const; + +export const CryptoPurpose = { + DeviceKeyPair: "deviceKeyPair", + BaseKey: "baseKey" +} as const; +type CryptoPurpose = (typeof CryptoPurpose)[keyof typeof CryptoPurpose]; + +export const CryptoKeyType = { + Signature: "signature", + Encryption: "encryption", + Derivation: "derivation", + Exchange: "exchange" +} as const; +type CryptoKeyType = (typeof CryptoKeyType)[keyof typeof CryptoKeyType]; + +export const CryptoObject = { + AccountController: "AccountController", + AnonymousTokenController: "AnonymousTokenController", + Certificate: "Certificate", + DeviceController: "DeviceController", + DeviceSecretController: "DeviceSecretController", + IdentityController: "IdentityController", + FileController: "FileController", + MessageController: "MessageController", + RelationshipTemplateController: "RelationshipTemplateController", + RelationshipsController: "RelationshipsController", + RelationshipSecretController: "RelationshipSecretController", + SecretController: "SecretController", + TokenController: "TokenController" +} as const; +type CryptoObject = (typeof CryptoObject)[keyof typeof CryptoObject]; + +export type CryptoOperationPreferences = Partial< + Record, SecurityLevel>>>>> +>; + +export const DEFAULT_CRYPTO_OPERATION_PREFERENCES: CryptoOperationPreferences = { + [CryptoObject.AccountController]: {}, + [CryptoObject.AnonymousTokenController]: {}, + [CryptoObject.Certificate]: {}, + [CryptoObject.DeviceController]: {}, + [CryptoObject.DeviceSecretController]: {}, + [CryptoObject.FileController]: { + [CryptoKeyType.Encryption]: CryptoProviderTypes.Software + }, + [CryptoObject.IdentityController]: {}, + [CryptoObject.MessageController]: { + [CryptoKeyType.Encryption]: CryptoProviderTypes.Software + }, + [CryptoObject.RelationshipTemplateController]: { + [CryptoKeyType.Encryption]: CryptoProviderTypes.Software + }, + [CryptoObject.RelationshipsController]: {}, + [CryptoObject.RelationshipSecretController]: {}, + [CryptoObject.SecretController]: { + [CryptoKeyType.Exchange]: CryptoProviderTypes.Software + }, + [CryptoObject.TokenController]: { + [CryptoKeyType.Encryption]: CryptoProviderTypes.Software + } +}; + +// To be removed after initialization of ts-crypto is adjusted +export const ALL_CRYPTO_PROVIDERS = ["SoftwareProvider"]; + +export class CryptoProviderMapping { + private static readonly ALLOWED_CRYPTO_OPERATIONS: Partial> = { + [CryptoObject.AccountController]: [CryptoKeyType.Encryption, CryptoKeyType.Signature], + [CryptoObject.AnonymousTokenController]: [CryptoKeyType.Derivation], + [CryptoObject.Certificate]: [CryptoKeyType.Encryption], + [CryptoObject.DeviceController]: [CryptoKeyType.Signature, CryptoKeyType.Encryption], + [CryptoObject.DeviceSecretController]: [CryptoKeyType.Derivation], + [CryptoObject.FileController]: [CryptoKeyType.Encryption], + [CryptoObject.IdentityController]: [CryptoKeyType.Encryption], + [CryptoObject.MessageController]: [CryptoKeyType.Encryption], + [CryptoObject.RelationshipTemplateController]: [CryptoKeyType.Derivation, CryptoKeyType.Encryption], + [CryptoObject.RelationshipsController]: [CryptoKeyType.Encryption], + [CryptoObject.RelationshipSecretController]: [CryptoKeyType.Encryption], + [CryptoObject.SecretController]: [CryptoKeyType.Encryption], + [CryptoObject.TokenController]: [CryptoKeyType.Encryption] + }; + + private static readonly DEFAULT_OPERATION_PREFERENCES: Partial> = { + [CryptoKeyType.Derivation]: CryptoProviderTypes.Software, + [CryptoKeyType.Signature]: CryptoProviderTypes.Hardware, + [CryptoKeyType.Encryption]: CryptoProviderTypes.Hardware, + [CryptoKeyType.Exchange]: CryptoProviderTypes.Software + }; + + private static readonly FALLBACK_PREFERENCE: SecurityLevel = CryptoProviderTypes.Software; + + private readonly _objectOperationPreferences: CryptoOperationPreferences; + + public constructor(preferences: CryptoOperationPreferences = DEFAULT_CRYPTO_OPERATION_PREFERENCES) { + this._objectOperationPreferences = preferences; + } + + private getPreferredProviderLevel(cryptoObject: CryptoObject, cryptoOperation: CryptoKeyType, purpose?: Exclude): SecurityLevel { + const allowedOps = CryptoProviderMapping.ALLOWED_CRYPTO_OPERATIONS[cryptoObject]; + if (allowedOps && !allowedOps.includes(cryptoOperation)) { + throw new Error(`Operation '${cryptoOperation}' is not supported for object '${cryptoObject}'.`); + } + + let chosenSecurityLevel: SecurityLevel | undefined; + const objectPrefs = this._objectOperationPreferences[cryptoObject]; + if (objectPrefs) { + const operationPrefOrMap = objectPrefs[cryptoOperation]; + if (operationPrefOrMap) { + if (typeof operationPrefOrMap === "object") { + if (purpose && operationPrefOrMap[purpose]) { + chosenSecurityLevel = operationPrefOrMap[purpose]; + } + } else { + chosenSecurityLevel = operationPrefOrMap; + } + } + } + + if (!chosenSecurityLevel) { + const operationPref = CryptoProviderMapping.DEFAULT_OPERATION_PREFERENCES[cryptoOperation]; + chosenSecurityLevel = operationPref ?? CryptoProviderMapping.FALLBACK_PREFERENCE; + } + + if (!hasProviderForSecurityLevel(chosenSecurityLevel)) { + if (chosenSecurityLevel !== CryptoProviderMapping.FALLBACK_PREFERENCE && !hasProviderForSecurityLevel(CryptoProviderMapping.FALLBACK_PREFERENCE)) { + throw new Error( + `No provider available for either ${chosenSecurityLevel} or fallback ${CryptoProviderMapping.FALLBACK_PREFERENCE} for operation ${cryptoOperation}.` + ); + } + return CryptoProviderMapping.FALLBACK_PREFERENCE; + } + + return chosenSecurityLevel; + } + + public async getPreferredProviderKeyHandle( + cryptoObject: CryptoObject, + cryptoOperation: CryptoKeyType, + isPortable: boolean, + purpose?: CryptoPurpose + ): Promise { + const securityLevel = this.getPreferredProviderLevel(cryptoObject, cryptoOperation, purpose); + switch (securityLevel) { + case CryptoProviderTypes.Hardware: + if (isPortable) { + return await CoreCrypto.generatePortableKeyHandle({ securityLevel: "Software" }); + } + return await CoreCrypto.generateDeviceBoundKeyHandle({ securityLevel: "Software" }); + + case CryptoProviderTypes.Software: + if (isPortable) { + return await CoreCrypto.generatePortableKeyHandle({ securityLevel }); + } + return await CoreCrypto.generateDeviceBoundKeyHandle({ securityLevel }); + + default: + throw new Error(`Unsupported SecurityLevel '${securityLevel}' encountered for key handle generation.`); + } + } +} diff --git a/packages/transport/src/core/Transport.ts b/packages/transport/src/core/Transport.ts index fb54a11f7..8370a8555 100644 --- a/packages/transport/src/core/Transport.ts +++ b/packages/transport/src/core/Transport.ts @@ -5,6 +5,7 @@ import { SodiumWrapper } from "@nmshd/crypto"; import { AgentOptions } from "http"; import { AgentOptions as HTTPSAgentOptions } from "https"; import _ from "lodash"; +import { CryptoOperationPreferences, DEFAULT_CRYPTO_OPERATION_PREFERENCES } from "./CryptoProviderMapping"; import { ICorrelator } from "./ICorrelator"; import { TransportCoreErrors } from "./TransportCoreErrors"; import { TransportError } from "./TransportError"; @@ -31,6 +32,7 @@ export interface IConfig { httpAgentOptions: AgentOptions; httpsAgentOptions: HTTPSAgentOptions; tagCacheLifetimeInMinutes: number; + cryptoOperationPreferences: CryptoOperationPreferences; } export interface IConfigOverwrite { @@ -49,6 +51,7 @@ export interface IConfigOverwrite { httpAgentOptions?: AgentOptions; httpsAgentOptions?: HTTPSAgentOptions; tagCacheLifetimeInMinutes?: number; + cryptoOperationPreferences?: CryptoOperationPreferences; } export class Transport { @@ -79,7 +82,8 @@ export class Transport { keepAlive: true, maxFreeSockets: 2 }, - tagCacheLifetimeInMinutes: 5 + tagCacheLifetimeInMinutes: 5, + cryptoOperationPreferences: DEFAULT_CRYPTO_OPERATION_PREFERENCES }; public constructor( diff --git a/packages/transport/src/core/index.ts b/packages/transport/src/core/index.ts index 713a38561..26390d917 100644 --- a/packages/transport/src/core/index.ts +++ b/packages/transport/src/core/index.ts @@ -2,6 +2,7 @@ export * from "./backbone"; export * from "./CoreCrypto"; export * from "./CoreSynchronizable"; export * from "./CoreUtil"; +export * from "./CryptoProviderMapping"; export * from "./DbCollectionName"; export * from "./DependencyOverrides"; export * from "./ICorrelator"; diff --git a/packages/transport/src/modules/accounts/AccountController.ts b/packages/transport/src/modules/accounts/AccountController.ts index c72aa86b4..52670f700 100644 --- a/packages/transport/src/modules/accounts/AccountController.ts +++ b/packages/transport/src/modules/accounts/AccountController.ts @@ -2,8 +2,20 @@ import { IDatabaseCollection, IDatabaseCollectionProvider, IDatabaseMap } from " import { ILogger } from "@js-soft/logging-abstractions"; import { log, sleep } from "@js-soft/ts-utils"; import { CoreAddress, CoreDate, CoreId } from "@nmshd/core-types"; -import { CryptoSecretKey } from "@nmshd/crypto"; -import { AbstractAuthenticator, Authenticator, ControllerName, IConfig, Transport, TransportCoreErrors, TransportError } from "../../core"; +import { CryptoSecretKey, DeviceBoundKeyHandle, hasProviderForSecurityLevel } from "@nmshd/crypto"; +import { + AbstractAuthenticator, + Authenticator, + ControllerName, + CryptoKeyType, + CryptoObject, + CryptoProviderMapping, + CryptoPurpose, + IConfig, + Transport, + TransportCoreErrors, + TransportError +} from "../../core"; import { CoreCrypto } from "../../core/CoreCrypto"; import { DbCollectionName } from "../../core/DbCollectionName"; import { DependencyOverrides } from "../../core/DependencyOverrides"; @@ -130,7 +142,9 @@ export class AccountController { this._activeDevice = new DeviceController(this); this.challenges = await new ChallengeController(this).init(); - const [availableIdentityDoc, availableDeviceDoc, availableBaseKeyDoc] = await Promise.all([this.info.get("identity"), this.info.get("device"), this.info.get("baseKey")]); + const isStoredOnHardware = await this.info.get("isBaseKeyStoredOnHardware"); + const baseKeyName = isStoredOnHardware ? "baseKeyHandle" : "baseKey"; + const [availableIdentityDoc, availableDeviceDoc, availableBaseKeyDoc] = await Promise.all([this.info.get("identity"), this.info.get("device"), this.info.get(baseKeyName)]); let device: Device; let identityCreated = false; @@ -162,7 +176,12 @@ export class AccountController { const availableIdentity = Identity.from(availableIdentityDoc); const availableDevice = Device.from(availableDeviceDoc); - const availableBaseKey = CryptoSecretKey.fromJSON(availableBaseKeyDoc); + let availableBaseKey; + if (isStoredOnHardware) { + availableBaseKey = await DeviceBoundKeyHandle.fromJSON(availableBaseKeyDoc); + } else { + availableBaseKey = CryptoSecretKey.fromJSON(availableBaseKeyDoc); + } await this.identity.init(availableIdentity); await this.identityDeletionProcess.init(); @@ -263,7 +282,7 @@ export class AccountController { @log() private async createIdentityAndDevice(): Promise<{ identity: Identity; device: Device }> { - const [identityKeypair, devicePwdD1, deviceKeypair, privBaseShared, privBaseDevice] = await Promise.all([ + const [identityKeypair, devicePwdD1, deviceKeypair, privBaseShared] = await Promise.all([ // Generate identity keypair CoreCrypto.generateSignatureKeypair(), // Generate strong device password @@ -271,10 +290,36 @@ export class AccountController { // Generate device keypair CoreCrypto.generateSignatureKeypair(), // Generate Shared Base Key - CoreCrypto.generateSecretKey(), - // Generate Device Base Key CoreCrypto.generateSecretKey() ]); + + const providerMapping = new CryptoProviderMapping(this._transport.config.cryptoOperationPreferences); + + // Generate device basekey + let privBaseDevice: CryptoSecretKey | DeviceBoundKeyHandle; + let dbKey; + + let isBaseKeyStoredOnHardware; + try { + isBaseKeyStoredOnHardware = hasProviderForSecurityLevel("Hardware"); + } catch (error) { + this._log.warn("Crypto Layer not initialized, continuing without it.", error); + isBaseKeyStoredOnHardware = false; + } + + if (isBaseKeyStoredOnHardware) { + privBaseDevice = (await providerMapping.getPreferredProviderKeyHandle( + CryptoObject.AccountController, + CryptoKeyType.Encryption, + false, + CryptoPurpose.BaseKey + )) as DeviceBoundKeyHandle; + dbKey = "baseKeyHandle"; + } else { + privBaseDevice = await CoreCrypto.generateSecretKey(); + dbKey = "baseKey"; + } + this._log.trace("Created keys. Requesting challenge..."); // Sign Challenge @@ -370,7 +415,8 @@ export class AccountController { await Promise.all([ storeSecretWithRetry(() => this.info.set("device", device.toJSON())), storeSecretWithRetry(() => this.info.set("identity", identity.toJSON())), - storeSecretWithRetry(() => this.info.set("baseKey", privBaseDevice.toJSON())), + storeSecretWithRetry(() => this.info.set(dbKey, privBaseDevice.toJSON())), + storeSecretWithRetry(() => this.info.set("isBaseKeyStoredOnHardware", isBaseKeyStoredOnHardware)), storeSecretWithRetry(() => this.activeDevice.secrets.storeSecret(privBaseShared, DeviceSecretType.SharedSecretBaseKey)), storeSecretWithRetry(() => this.activeDevice.secrets.storeSecret(privSync, DeviceSecretType.IdentitySynchronizationMaster)), storeSecretWithRetry(() => this.activeDevice.secrets.storeSecret(identityKeypair.privateKey, DeviceSecretType.IdentitySignature)), @@ -383,16 +429,41 @@ export class AccountController { public async onboardDevice(deviceSharedSecret: DeviceSharedSecret): Promise { this._log.trace("Onboarding device for existing identity..."); - const [devicePwdDn, deviceKeypair, deviceInfo, privBaseDevice] = await Promise.all([ + const [devicePwdDn, deviceKeypair, deviceInfo] = await Promise.all([ // Generate strong device password PasswordGenerator.createStrongPassword(45, 50), // Generate device keypair CoreCrypto.generateSignatureKeypair(), - this.fetchDeviceInfo(), - // Generate device basekey - CoreCrypto.generateSecretKey() + this.fetchDeviceInfo() ]); + const providerMapping = new CryptoProviderMapping(this._transport.config.cryptoOperationPreferences); + + // Generate device basekey + let privBaseDevice: CryptoSecretKey | DeviceBoundKeyHandle; + let dbKey; + + let isBaseKeyStoredOnHardware; + try { + isBaseKeyStoredOnHardware = hasProviderForSecurityLevel("Hardware"); + } catch (error) { + this._log.warn("Crypto Layer not initialized, continuing without it.", error); + isBaseKeyStoredOnHardware = false; + } + + if (isBaseKeyStoredOnHardware) { + privBaseDevice = (await providerMapping.getPreferredProviderKeyHandle( + CryptoObject.AccountController, + CryptoKeyType.Encryption, + false, + CryptoPurpose.BaseKey + )) as DeviceBoundKeyHandle; + dbKey = "baseKeyHandle"; + } else { + privBaseDevice = await CoreCrypto.generateSecretKey(); + dbKey = "baseKey"; + } + const device = Device.from({ id: deviceSharedSecret.id, name: deviceSharedSecret.name ?? "", @@ -423,7 +494,8 @@ export class AccountController { await Promise.all([ this.info.set("device", device.toJSON()), this.info.set("identity", deviceSharedSecret.identity.toJSON()), - this.info.set("baseKey", privBaseDevice.toJSON()), + this.info.set(dbKey, privBaseDevice.toJSON()), + this.info.set("isBaseKeyStoredOnHardware", isBaseKeyStoredOnHardware), this.info.set(SecretController.secretNonceKey, deviceSharedSecret.deviceIndex * 1000000), this.activeDevice.secrets.storeSecret(deviceSharedSecret.secretBaseKey, DeviceSecretType.SharedSecretBaseKey), this.activeDevice.secrets.storeSecret(deviceSharedSecret.synchronizationKey, DeviceSecretType.IdentitySynchronizationMaster), diff --git a/packages/transport/src/modules/devices/DeviceController.ts b/packages/transport/src/modules/devices/DeviceController.ts index 90a2c9fdf..36be8f6ad 100644 --- a/packages/transport/src/modules/devices/DeviceController.ts +++ b/packages/transport/src/modules/devices/DeviceController.ts @@ -1,6 +1,6 @@ import { log } from "@js-soft/ts-utils"; import { CoreDate, CoreId } from "@nmshd/core-types"; -import { CoreBuffer, CryptoSecretKey, CryptoSignature, CryptoSignaturePrivateKey, CryptoSignaturePublicKey } from "@nmshd/crypto"; +import { CoreBuffer, CryptoSecretKey, CryptoSignature, CryptoSignaturePrivateKey, CryptoSignaturePublicKey, DeviceBoundKeyHandle } from "@nmshd/crypto"; import { ControllerName, CoreCrypto, CredentialsBasic, TransportController, TransportCoreErrors, TransportError } from "../../core"; import { AccountController } from "../accounts/AccountController"; import { DeviceSecretController, DeviceSecretType } from "./DeviceSecretController"; @@ -59,7 +59,7 @@ export class DeviceController extends TransportController { } @log() - public override async init(baseKey: CryptoSecretKey, device: Device): Promise { + public override async init(baseKey: DeviceBoundKeyHandle | CryptoSecretKey, device: Device): Promise { await super.init(); this._device = device; diff --git a/packages/transport/src/modules/devices/DeviceSecretController.ts b/packages/transport/src/modules/devices/DeviceSecretController.ts index 649f37629..82241e542 100644 --- a/packages/transport/src/modules/devices/DeviceSecretController.ts +++ b/packages/transport/src/modules/devices/DeviceSecretController.ts @@ -2,7 +2,17 @@ import { IDatabaseMap } from "@js-soft/docdb-access-abstractions"; import { Serializable } from "@js-soft/ts-serval"; import { log } from "@js-soft/ts-utils"; import { CoreDate } from "@nmshd/core-types"; -import { CoreBuffer, CryptoCipher, CryptoExchangeKeypair, CryptoExchangePrivateKey, CryptoSecretKey, CryptoSignatureKeypair, CryptoSignaturePrivateKey } from "@nmshd/crypto"; +import { + CoreBuffer, + CryptoCipher, + CryptoEncryptionHandle, + CryptoExchangeKeypair, + CryptoExchangePrivateKey, + CryptoSecretKey, + CryptoSignatureKeypair, + CryptoSignaturePrivateKey, + DeviceBoundKeyHandle +} from "@nmshd/crypto"; import { CoreCrypto, TransportCoreErrors } from "../../core"; import { ControllerName, TransportController } from "../../core/TransportController"; import { TransportIds } from "../../core/TransportIds"; @@ -33,9 +43,9 @@ export class DeviceSecretController extends TransportController { private static readonly secretContext: string = "DEVICE01"; - private readonly baseKey?: CryptoSecretKey; + private readonly baseKey?: DeviceBoundKeyHandle | CryptoSecretKey; - public constructor(parent: AccountController, baseKey: CryptoSecretKey) { + public constructor(parent: AccountController, baseKey: DeviceBoundKeyHandle | CryptoSecretKey) { super(ControllerName.DeviceSecret, parent); this.baseKey = baseKey; } @@ -55,9 +65,17 @@ export class DeviceSecretController extends TransportController { const plainString = secret.serialize(); const plainBuffer = CoreBuffer.fromUtf8(plainString); - const encryptionKey = await CoreCrypto.deriveKeyFromBase(this.getBaseKey(), 1, DeviceSecretController.secretContext); + let encryptionKey; + let cipher; + const baseKey = this.getBaseKey(); + if (baseKey instanceof DeviceBoundKeyHandle) { + encryptionKey = await CoreCrypto.generateDeviceBoundDerivationHandle(baseKey, 1, DeviceSecretController.secretContext); + cipher = await CryptoEncryptionHandle.encrypt(plainBuffer, encryptionKey); + } else { + encryptionKey = await CoreCrypto.deriveKeyFromBase(baseKey, 1, DeviceSecretController.secretContext); + cipher = await CoreCrypto.encrypt(plainBuffer, encryptionKey); + } - const cipher = await CoreCrypto.encrypt(plainBuffer, encryptionKey); const date = CoreDate.utc(); const container = SecretContainerCipher.from({ cipher: cipher, @@ -79,10 +97,18 @@ export class DeviceSecretController extends TransportController { const secretObj = await this.secrets.get(name); if (!secretObj) return; - const baseKey = this.getBaseKey(); const secret = SecretContainerCipher.from(secretObj); - const decryptionKey = await CoreCrypto.deriveKeyFromBase(baseKey, 1, DeviceSecretController.secretContext); - const plainBuffer = await CoreCrypto.decrypt(secret.cipher, decryptionKey); + let decryptionKey; + let plainBuffer; + const baseKey = this.getBaseKey(); + if (baseKey instanceof DeviceBoundKeyHandle) { + decryptionKey = await CoreCrypto.generateDeviceBoundDerivationHandle(baseKey, 1, DeviceSecretController.secretContext); + plainBuffer = await CryptoEncryptionHandle.decrypt(secret.cipher, decryptionKey); + } else { + decryptionKey = await CoreCrypto.deriveKeyFromBase(baseKey, 1, DeviceSecretController.secretContext); + plainBuffer = await CoreCrypto.decrypt(secret.cipher, decryptionKey); + } + const plainString = plainBuffer.toUtf8(); const decryptedSecret = Serializable.deserializeUnknown(plainString); @@ -192,7 +218,7 @@ export class DeviceSecretController extends TransportController { } @log() - private getBaseKey(): CryptoSecretKey { + private getBaseKey(): DeviceBoundKeyHandle | CryptoSecretKey { if (!this.baseKey) { throw TransportCoreErrors.general.recordNotFound(CryptoSecretKey, DeviceSecretType.SharedSecretBaseKey); } diff --git a/packages/transport/test/testHelpers/AppDeviceTest.ts b/packages/transport/test/testHelpers/AppDeviceTest.ts index 4b472a4d8..6347b25d9 100644 --- a/packages/transport/test/testHelpers/AppDeviceTest.ts +++ b/packages/transport/test/testHelpers/AppDeviceTest.ts @@ -1,5 +1,6 @@ import { ILogger } from "@js-soft/logging-abstractions"; import { EventEmitter2EventBus } from "@js-soft/ts-utils"; +import * as tmp from "tmp"; import { AccountController, DeviceSharedSecret, Transport } from "../../src"; import { DeviceTestParameters } from "./DeviceTestParameters"; import { TestUtil } from "./TestUtil"; @@ -12,8 +13,11 @@ export class AppDeviceTest { private readonly createdAccounts: AccountController[] = []; + private static readonly rootTempDir = tmp.dirSync({ unsafeCleanup: true }); + public constructor(parameters: DeviceTestParameters) { this.parameters = parameters; + this.transport = new Transport( this.parameters.config, new EventEmitter2EventBus(() => { diff --git a/packages/transport/test/testHelpers/TestUtil.ts b/packages/transport/test/testHelpers/TestUtil.ts index c2e4ef26d..19b22512b 100644 --- a/packages/transport/test/testHelpers/TestUtil.ts +++ b/packages/transport/test/testHelpers/TestUtil.ts @@ -8,11 +8,13 @@ import { SimpleLoggerFactory } from "@js-soft/simple-logger"; import { ISerializable, Serializable } from "@js-soft/ts-serval"; import { EventEmitter2EventBus, sleep } from "@js-soft/ts-utils"; import { CoreAddress, CoreDate, CoreId } from "@nmshd/core-types"; -import { CoreBuffer } from "@nmshd/crypto"; +import { CoreBuffer, initializeNewProviders } from "@nmshd/crypto"; +import { createProvider, createProviderFromName, getAllProviders, getProviderCapabilities } from "@nmshd/rs-crypto-node"; import fs from "fs"; import { DurationLike } from "luxon"; import path from "path"; import { GenericContainer, Wait } from "testcontainers"; +import * as tmp from "tmp"; import { LogLevel } from "typescript-logging"; import { AccountController, @@ -38,6 +40,7 @@ import { } from "../../src"; export class TestUtil { + private static readonly rootTempDir = tmp.dirSync({ unsafeCleanup: true }); private static readonly fatalLogger = new SimpleLoggerFactory(LogLevel.Fatal); private static oldLogger: ILoggerFactory; public static loggerFactory = new NodeLoggerFactory({ @@ -179,6 +182,15 @@ export class TestUtil { throw new Error(`Missing environment variable(s): ${notDefinedEnvironmentVariables.join(", ")}}`); } + if (process.env["NMSHD_TEST_CAL"]) { + const transportSpecificDir = fs.mkdtempSync(path.join(TestUtil.rootTempDir.name, "transport-")); + const factoryFunctions = { getAllProviders, createProvider, createProviderFromName, getProviderCapabilities }; + // eslint-disable-next-line @typescript-eslint/naming-convention + const storageConfig = { FileStoreConfig: { db_dir: transportSpecificDir } }; + initializeNewProviders(storageConfig, factoryFunctions).catch((err) => { + throw new Error(`Failed to initialize crypto providers: ${err.message}`); + }); + } return { baseUrl: globalThis.process.env.NMSHD_TEST_BASEURL!, platformClientId: globalThis.process.env.NMSHD_TEST_CLIENTID!, @@ -548,7 +560,7 @@ export class TestUtil { return e; } - throw new Error("no error occured"); + throw new Error("no error occurred"); } public static async sendRelationshipTemplate(from: AccountController, body?: ISerializable): Promise {