diff --git a/package-lock.json b/package-lock.json index 2fc72ee781..e8cba3ace5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,8 @@ "@matrixai/workers": "^1.3.6", "@noble/ed25519": "^1.7.1", "@noble/hashes": "^1.1.2", + "@peculiar/webcrypto": "^1.4.0", + "@peculiar/x509": "^1.8.3", "@scure/bip39": "^1.1.0", "ajv": "^7.0.4", "bip39": "^3.0.3", @@ -2775,6 +2777,167 @@ "node": ">= 8" } }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.1.tgz", + "integrity": "sha512-zJ4YojOSerCMjU3oGsw8IVzSYcRODW42i5KNJVzQntQRgYPsqe8e3rt4rgymmB+0xreBWeH4X3zI/t8pyT4UJw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "@peculiar/asn1-x509-attr": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.3.0.tgz", + "integrity": "sha512-Ss5DibPLHkWgcVheohy6tS4KyWCmtP3dlkxg10ZSfz/3wDj2BCQ4F+fmik4kTUCXZFd6otogXFMn2zc8SlXynQ==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.0.tgz", + "integrity": "sha512-IUFZ5jyiduvSbXxnw5Y6QMAG1C5NHXqE5+kJePJXcFsEHh5NxdBYNa21kBGdz09Y4b1awCT2NP1YtZPBhFNYqw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.3.1.tgz", + "integrity": "sha512-LdlUYml+438C8yBQxMZm0CEvhG2Z0pZsGw8tKZxxSmKX6MdIpj4JQWuDE5ie3jwz7oaMDlUm1LsAwcpPwEUkyA==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.1", + "@peculiar/asn1-pkcs8": "^2.3.0", + "@peculiar/asn1-rsa": "^2.3.0", + "@peculiar/asn1-schema": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.3.0.tgz", + "integrity": "sha512-WpItuGy5OSVXqetgbekVvJbX0YE02pwhjesQrUkPBy5GamzTX2OeK2+Avxc4TeeiT2s7Y/VD9RZylowmb1ScnQ==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.3.1.tgz", + "integrity": "sha512-awUjcCHMCJ1A9LUWo1oxmGdvX2iDbSnm+tuafbf1Q8UrBzN/iIbBjc6V6BhvIF32Jja79xP/N8RyoOaVkoh20w==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.1", + "@peculiar/asn1-pfx": "^2.3.1", + "@peculiar/asn1-pkcs8": "^2.3.0", + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "@peculiar/asn1-x509-attr": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.0.tgz", + "integrity": "sha512-v63dbd1dQnDp6EZYV0/Foi/H9N0j4nTeuXip8Oxy79OyEQ6Vll9bmk6cfhKQdDCxSBYNTdyZiJnwWirpKPrrUw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.0.tgz", + "integrity": "sha512-DtNLAG4vmDrdSJFPe7rypkcj597chNQL7u+2dBtYo5mh7VW2+im6ke+O0NVr8W1f4re4C3F71LhoMb0Yxqa48Q==", + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.0.tgz", + "integrity": "sha512-iDRNPHAx/HLwR9wN5xaHDPifpdSW/bquu+zo/kQXurnxg6KQ1jcZw+4a63uTvrzyGU/hHzDqjalG/sQvV02lAw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "asn1js": "^3.0.5", + "ipaddr.js": "^2.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.3.0.tgz", + "integrity": "sha512-oViOaJaqhBM7cFnGAb/VJr8ljp6qOrh6X5WRa7USYcaVz9O4IxYKIaBA8ZbTH2NthRd6HkE++3+nerQguxctdw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.0.tgz", + "integrity": "sha512-U58N44b2m3OuTgpmKgf0LPDOmP3bhwNz01vAnj1mBwxBASRhptWYK+M3zG+HBkDqGQM+bFsoIihTW8MdmPXEqg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0", + "webcrypto-core": "^1.7.4" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.8.3.tgz", + "integrity": "sha512-omZfI3n4eGLS5NLudURzbc0smQ4ePreOPUEk31n1MLaqd2GGb48b4Zw5xjHzHJ0hnPYmZ+NRjqqquXYUYKjMCw==", + "dependencies": { + "@peculiar/asn1-cms": "^2.2.0", + "@peculiar/asn1-csr": "^2.2.0", + "@peculiar/asn1-ecc": "^2.2.0", + "@peculiar/asn1-pkcs9": "^2.2.0", + "@peculiar/asn1-rsa": "^2.2.0", + "@peculiar/asn1-schema": "^2.2.0", + "@peculiar/asn1-x509": "^2.2.0", + "pvtsutils": "^1.3.2", + "reflect-metadata": "^0.1.13", + "tslib": "^2.4.0", + "tsyringe": "^4.7.0" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -3600,6 +3763,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -6321,6 +6497,14 @@ "resolved": "https://registry.npmjs.org/ip-num/-/ip-num-1.4.0.tgz", "integrity": "sha512-MP+gq4uBvrvm+G7EwP14GcJeFK49/p6sZrNOarMUoExLRodULJQM8mnkb/SbT1YKxRsZfh8rgwei2pUJIa35jA==" }, + "node_modules/ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "engines": { + "node": ">= 10" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -9903,6 +10087,22 @@ "url": "https://opencollective.com/fast-check" } }, + "node_modules/pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9992,6 +10192,11 @@ "node": ">= 0.10" } }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -11093,6 +11298,22 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/tsyringe": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.7.0.tgz", + "integrity": "sha512-ncFDM1jTLsok4ejMvSW5jN1VGPQD48y2tfAR0pdptWRKYX4bkbqPt92k7KJ5RFJ1KV36JEs/+TMh7I6OUgj74g==", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -11403,6 +11624,18 @@ "makeerror": "1.0.12" } }, + "node_modules/webcrypto-core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.5.tgz", + "integrity": "sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A==", + "dependencies": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13576,6 +13809,161 @@ "fastq": "^1.6.0" } }, + "@peculiar/asn1-cms": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.1.tgz", + "integrity": "sha512-zJ4YojOSerCMjU3oGsw8IVzSYcRODW42i5KNJVzQntQRgYPsqe8e3rt4rgymmB+0xreBWeH4X3zI/t8pyT4UJw==", + "requires": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "@peculiar/asn1-x509-attr": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-csr": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.3.0.tgz", + "integrity": "sha512-Ss5DibPLHkWgcVheohy6tS4KyWCmtP3dlkxg10ZSfz/3wDj2BCQ4F+fmik4kTUCXZFd6otogXFMn2zc8SlXynQ==", + "requires": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-ecc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.0.tgz", + "integrity": "sha512-IUFZ5jyiduvSbXxnw5Y6QMAG1C5NHXqE5+kJePJXcFsEHh5NxdBYNa21kBGdz09Y4b1awCT2NP1YtZPBhFNYqw==", + "requires": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pfx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.3.1.tgz", + "integrity": "sha512-LdlUYml+438C8yBQxMZm0CEvhG2Z0pZsGw8tKZxxSmKX6MdIpj4JQWuDE5ie3jwz7oaMDlUm1LsAwcpPwEUkyA==", + "requires": { + "@peculiar/asn1-cms": "^2.3.1", + "@peculiar/asn1-pkcs8": "^2.3.0", + "@peculiar/asn1-rsa": "^2.3.0", + "@peculiar/asn1-schema": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pkcs8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.3.0.tgz", + "integrity": "sha512-WpItuGy5OSVXqetgbekVvJbX0YE02pwhjesQrUkPBy5GamzTX2OeK2+Avxc4TeeiT2s7Y/VD9RZylowmb1ScnQ==", + "requires": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pkcs9": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.3.1.tgz", + "integrity": "sha512-awUjcCHMCJ1A9LUWo1oxmGdvX2iDbSnm+tuafbf1Q8UrBzN/iIbBjc6V6BhvIF32Jja79xP/N8RyoOaVkoh20w==", + "requires": { + "@peculiar/asn1-cms": "^2.3.1", + "@peculiar/asn1-pfx": "^2.3.1", + "@peculiar/asn1-pkcs8": "^2.3.0", + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "@peculiar/asn1-x509-attr": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-rsa": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.0.tgz", + "integrity": "sha512-v63dbd1dQnDp6EZYV0/Foi/H9N0j4nTeuXip8Oxy79OyEQ6Vll9bmk6cfhKQdDCxSBYNTdyZiJnwWirpKPrrUw==", + "requires": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-schema": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.0.tgz", + "integrity": "sha512-DtNLAG4vmDrdSJFPe7rypkcj597chNQL7u+2dBtYo5mh7VW2+im6ke+O0NVr8W1f4re4C3F71LhoMb0Yxqa48Q==", + "requires": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-x509": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.0.tgz", + "integrity": "sha512-iDRNPHAx/HLwR9wN5xaHDPifpdSW/bquu+zo/kQXurnxg6KQ1jcZw+4a63uTvrzyGU/hHzDqjalG/sQvV02lAw==", + "requires": { + "@peculiar/asn1-schema": "^2.3.0", + "asn1js": "^3.0.5", + "ipaddr.js": "^2.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-x509-attr": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.3.0.tgz", + "integrity": "sha512-oViOaJaqhBM7cFnGAb/VJr8ljp6qOrh6X5WRa7USYcaVz9O4IxYKIaBA8ZbTH2NthRd6HkE++3+nerQguxctdw==", + "requires": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/asn1-x509": "^2.3.0", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@peculiar/webcrypto": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.0.tgz", + "integrity": "sha512-U58N44b2m3OuTgpmKgf0LPDOmP3bhwNz01vAnj1mBwxBASRhptWYK+M3zG+HBkDqGQM+bFsoIihTW8MdmPXEqg==", + "requires": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0", + "webcrypto-core": "^1.7.4" + } + }, + "@peculiar/x509": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.8.3.tgz", + "integrity": "sha512-omZfI3n4eGLS5NLudURzbc0smQ4ePreOPUEk31n1MLaqd2GGb48b4Zw5xjHzHJ0hnPYmZ+NRjqqquXYUYKjMCw==", + "requires": { + "@peculiar/asn1-cms": "^2.2.0", + "@peculiar/asn1-csr": "^2.2.0", + "@peculiar/asn1-ecc": "^2.2.0", + "@peculiar/asn1-pkcs9": "^2.2.0", + "@peculiar/asn1-rsa": "^2.2.0", + "@peculiar/asn1-schema": "^2.2.0", + "@peculiar/asn1-x509": "^2.2.0", + "pvtsutils": "^1.3.2", + "reflect-metadata": "^0.1.13", + "tslib": "^2.4.0", + "tsyringe": "^4.7.0" + } + }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -14214,6 +14602,16 @@ "is-string": "^1.0.7" } }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -16290,6 +16688,11 @@ "resolved": "https://registry.npmjs.org/ip-num/-/ip-num-1.4.0.tgz", "integrity": "sha512-MP+gq4uBvrvm+G7EwP14GcJeFK49/p6sZrNOarMUoExLRodULJQM8mnkb/SbT1YKxRsZfh8rgwei2pUJIa35jA==" }, + "ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -18931,6 +19334,19 @@ "integrity": "sha512-ksWccjmXOHU2gJBnH0cK1lSYdvSZ0zLoCMSz/nTGh6hDvCSgcRxDyIcOBD6KNxFz3xhMPm/T267Tbe2JRymKEQ==", "dev": true }, + "pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "requires": { + "tslib": "^2.4.0" + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==" + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -18996,6 +19412,11 @@ "resolve": "^1.1.6" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -19777,6 +20198,21 @@ } } }, + "tsyringe": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.7.0.tgz", + "integrity": "sha512-ncFDM1jTLsok4ejMvSW5jN1VGPQD48y2tfAR0pdptWRKYX4bkbqPt92k7KJ5RFJ1KV36JEs/+TMh7I6OUgj74g==", + "requires": { + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -20014,6 +20450,18 @@ "makeerror": "1.0.12" } }, + "webcrypto-core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.5.tgz", + "integrity": "sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A==", + "requires": { + "@peculiar/asn1-schema": "^2.1.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 877298374a..7d046303cd 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,8 @@ "@matrixai/workers": "^1.3.6", "@noble/ed25519": "^1.7.1", "@noble/hashes": "^1.1.2", + "@peculiar/webcrypto": "^1.4.0", + "@peculiar/x509": "^1.8.3", "@scure/bip39": "^1.1.0", "ajv": "^7.0.4", "bip39": "^3.0.3", diff --git a/test-bootstrapping.ts b/test-bootstrapping.ts index e7772dc4a4..1ddc4ef9d4 100644 --- a/test-bootstrapping.ts +++ b/test-bootstrapping.ts @@ -689,6 +689,8 @@ async function main () { console.log(omg.plaintext.toString()); + console.log('?', result); + diff --git a/test-dek.ts b/test-dek.ts index 01d067e556..ade163f4a7 100644 --- a/test-dek.ts +++ b/test-dek.ts @@ -12,12 +12,20 @@ import * as nobleHkdf from '@noble/hashes/hkdf'; import { sha512 as nobleSha512 } from '@noble/hashes/sha512'; import { sha256 as nobleSha256 } from '@noble/hashes/sha256'; -import { isTypedArray } from 'util/types'; -type Assert = (condition: unknown) => asserts condition; -const assert: Assert = (condition) => { - if (condition == false) throw new Error('Invalid assertion'); -}; +// type Assert = (condition: unknown) => asserts condition; +// const assert: Assert = (condition) => { +// if (condition == false) throw new Error('Invalid assertion'); +// }; + +/** + * Opaque types are wrappers of existing types + * that require smart constructors + */ +type Opaque = T & { readonly [brand]: K }; +declare const brand: unique symbol; + +type RecoveryCode = Opaque<'RecoveryCode', string>; /** @@ -114,8 +122,32 @@ async function decryptWithKey( return bufferWrap(plainText); } +function generateRecoveryCode(size: 12 | 24 = 24): RecoveryCode { + if (size === 12) { + return bip39.generateMnemonic(wordlist, 128) as RecoveryCode; + } else if (size === 24) { + return bip39.generateMnemonic(wordlist, 256) as RecoveryCode; + } + throw RangeError(size); +} + +async function generateDeterministicKeyPair(recoveryCode: string) { + // This uses BIP39 standard, the result is 64 byte seed + // This is deterministic, and does not use any random source + const recoverySeed = await bip39.mnemonicToSeed(recoveryCode); + // Slice it to 32 bytes, as ed25519 private key is only 32 bytes + const privateKey = recoverySeed.slice(0, 32); + const publicKey = await nobleEd25519.getPublicKey(privateKey); + return { + publicKey, + privateKey + }; +} + async function main () { + const recoveryCode = generateRecoveryCode(24); + const rootKeyPair = await generateDeterministicKeyPair(recoveryCode); const databaseKey = getRandomBytesSync(32); const databaseKeyJWK = { @@ -155,9 +187,49 @@ async function main () { console.log(plainText?.toString()); - // Now we do key wrapping + // We are going to wrap it + // Encrypted JWK + const databaseKeyJWKEncrypted = new jose.FlattenedEncrypt( + Buffer.from(JSON.stringify(databaseKeyJWK), 'utf-8') + ); + + databaseKeyJWKEncrypted.setProtectedHeader({ + alg: 'dir', + enc: 'A256GCM', + cty: 'jwk+JSON' + }); + + const z = await nobleEd25519.getSharedSecret( + rootKeyPair.privateKey, + rootKeyPair.publicKey + ); + + const PRK = nobleHkdf.extract( + nobleSha512, + z, + ); + + const KEK = nobleHkdf.expand( + nobleSha512, + PRK, + Buffer.from('DB KEY key wrap/key encapsulation mechanism'), + 32 + ); + + const jweEncrypted = await databaseKeyJWKEncrypted.encrypt(KEK); + + // We save this as `db_key.jwk` + // It can now be decrypted in the future with the same KEK + // This also doesn't bother with an ephemeral static, no need + const jweEncryptedString = JSON.stringify(jweEncrypted); + + // In the future, use ECDH-ES + // Ok we are going to use X.509 now + console.log(jweEncryptedString); + // We could assume all these libraries actually use node's crypto + // and node's webcrypto ultimately uses node's crypto anyway } diff --git a/test-x509.ts b/test-x509.ts new file mode 100644 index 0000000000..09b17bc31c --- /dev/null +++ b/test-x509.ts @@ -0,0 +1,297 @@ +// We are going to test x509 +// and let's see how we can make use of this +// No more node-forge - we are going to make use of this + +// pkijs - 5 packages +// @pecualiar/x509 - 15 packages + +import fs from 'fs'; +// import { webcrypto } from 'crypto'; +import * as x509 from '@peculiar/x509'; +import * as jose from 'jose'; +import * as bip39 from '@scure/bip39'; +import { wordlist } from '@scure/bip39/wordlists/english'; +import * as nobleEd25519 from '@noble/ed25519'; +import * as nobleHashesUtils from '@noble/hashes/utils'; +import * as base64 from 'multiformats/bases/base64'; +import * as noblePbkdf2 from '@noble/hashes/pbkdf2'; +import * as nobleHkdf from '@noble/hashes/hkdf'; +import { sha512 as nobleSha512 } from '@noble/hashes/sha512'; +import { sha256 as nobleSha256 } from '@noble/hashes/sha256'; +import { Crypto } from '@peculiar/webcrypto'; + +// Both PKIJS and X509 library +// ends up being capable of setting +// the crypto global +// or crypto.webcrypto in the case of nodejs +// In PKIJS it's CryptoEngineInit.ts +// In X509, i'ts the provider.ts +// However it does not automatically do the below +// So we have to do it ourselves +// It is the `Crypto` interface that's the webcrypto object +// Note that nodejs now has native webcrypto so we are using this + +const webcrypto = new Crypto(); + +/** + * Zero-copy wraps ArrayBuffer-like objects into Buffer + * This supports ArrayBuffer, TypedArrays and NodeJS Buffer + */ +function bufferWrap( + array: ArrayBuffer, + offset?: number, + length?: number, +): Buffer { + if (Buffer.isBuffer(array)) { + return array; + } else if (ArrayBuffer.isView(array)) { + return Buffer.from( + array.buffer, + offset ?? array.byteOffset, + length ?? array.byteLength + ); + } else { + return Buffer.from( + array, + offset, + length + ); + } +} + +// @ts-ignore - this overrides the random source used by @noble and @scure libraries +nobleHashesUtils.randomBytes = (size: number = 32) => getRandomBytesSync(size); +nobleEd25519.utils.randomBytes = (size: number = 32) => getRandomBytesSync(size); +x509.cryptoProvider.set(webcrypto as Crypto); + +/** + * This is limited to 65,536 bytes of random data + * Stream this call, if you want more + */ +function getRandomBytesSync(size: number): Buffer { + return webcrypto.getRandomValues( + Buffer.allocUnsafe(size) + ); +} + +type Opaque = T & { readonly [brand]: K }; +declare const brand: unique symbol; + +type RecoveryCode = Opaque<'RecoveryCode', string>; + +function generateRecoveryCode(size: 12 | 24 = 24): RecoveryCode { + if (size === 12) { + return bip39.generateMnemonic(wordlist, 128) as RecoveryCode; + } else if (size === 24) { + return bip39.generateMnemonic(wordlist, 256) as RecoveryCode; + } + throw RangeError(size); +} + +async function generateDeterministicKeyPair( + recoveryCode: string +): Promise<{ + publicKey: Buffer; + privateKey: Buffer; +}> { + // This uses BIP39 standard, the result is 64 byte seed + // This is deterministic, and does not use any random source + const recoverySeed = await bip39.mnemonicToSeed(recoveryCode); + // Slice it to 32 bytes, as ed25519 private key is only 32 bytes + const privateKey = recoverySeed.slice(0, 32); + const publicKey = await nobleEd25519.getPublicKey(privateKey); + return { + publicKey: bufferWrap(publicKey), + privateKey: bufferWrap(privateKey) + }; +} + +async function main () { + const recoveryCode = generateRecoveryCode(24); + const rootKeyPair = await generateDeterministicKeyPair(recoveryCode); + + // We don't actually use jose's importJWK + // Well if we do, the problem is that we get a key object in NodeJS + // not a webcrypto CryptoKey + // We can import JWKs directly in webcrypto + + const d = base64.base64url.baseEncode(rootKeyPair.privateKey); + const x = base64.base64url.baseEncode(rootKeyPair.publicKey); + + const privateKeyJWK = { + alg: 'EdDSA', + kty: 'OKP', // Octet key pair + crv: 'Ed25519', // Curve + d: d, // Private key + x: x, // Public key + ext: true, // Extractable (always true in nodejs) + key_ops: ['sign', 'verify'], // Key operations + }; + + const publicKeyJWK = { + alg: 'EdDSA', + kty: 'OKP', // Octet key pair + crv: 'Ed25519', // Curve + x: x, // Public key + ext: true, // Extractable (always true in nodejs) + key_ops: ['verify'], // Key operations + }; + + // The below is technically non-standard + // Because Ed25519 and X25519 has not been standardised under webcrypto + // But the problem is that the x509 library seems to demand this requirement + + const privateCryptoKey = await webcrypto.subtle.importKey( + 'jwk', + privateKeyJWK, + // { name: 'Ed25519' }, // NODEJS + { name: 'EdDSA', namedCurve: 'Ed25519' }, // PECULIAR + true, + ['sign'] + ); + + const publicCryptoKey = await webcrypto.subtle.importKey( + 'jwk', + publicKeyJWK, + // { name: 'Ed25519' }, // NODEJS + { name: 'EdDSA', namedCurve: 'Ed25519' }, // PECULIAR + true, + ['verify'] + ); + + console.log('Got it', privateCryptoKey); + console.log('Got it', publicCryptoKey); + + // Ed25519 isn't officially supported by webcrypto + // However NodeJS has Ed25519 implemented + // The X509 library relies on the crypto provider + // It seems to assume the same API as the peculiarventures/webcrypto + // I'm not sure if we are supposed to be using that + // The problem is that it doesn't just take Uint8Arrays as the keys + // const keys = await webcrypto.subtle.generateKey({ + // name: 'Ed25519', + // }, true, ['sign', 'verify']); + // console.log(keys); + + + const cert = await x509.X509CertificateGenerator.createSelfSigned({ + serialNumber: '01', + // This can be JSON, only used for self-signed + // on The other ones, we can do subject, issuer, publicKey, signingKey, signature, publicKey + name: 'CN=Test, E=some@email.net', + notBefore: new Date('2020/01/01'), + notAfter: new Date('2025/01/01'), + signingAlgorithm: { + // This is only used if the `signingKey` is set + name: 'EdDSA', // <- peculiar venture style, but it's not really used + }, + // This is a CryptoKeyPair interface + keys: { + // This has to be a CryptoKey + // Which is object with algorithm, extractable, type, usages + publicKey: publicCryptoKey, + privateKey: privateCryptoKey, + }, + extensions: [ + new x509.BasicConstraintsExtension(false, undefined, true), + new x509.ExtendedKeyUsageExtension( + ["1.2.3.4.5.6.7", "2.3.4.5.6.7.8"], + true + ), + new x509.KeyUsagesExtension( + x509.KeyUsageFlags.keyCertSign | x509.KeyUsageFlags.cRLSign, + true + ), + await x509.SubjectKeyIdentifierExtension.create(publicCryptoKey), + ] + }); + + // You can do this + // but it doesn't have any effect on the underlying data + // Cause the `toString` runs against the `rawData` + // So you cannot just modify the certificate afterwards... + cert.notAfter = new Date('2030/01/01'); + cert.notBefore = new Date('2020/01/01'); + cert.signature = new ArrayBuffer(10); + + + console.log(cert); + + console.log(cert.toString('pem')); + + fs.writeFileSync('./tmp/x.crt', cert.toString('pem')); + + // We need to test what we do to our certificates now + // 1. CN is just the NodeId (which is multibase base32hex) + // 2. Issue is the same + // 3. Subject is the same + // Extensions: + // basic + // key usage + // extended key usage + // nsCertType can be used <- this is actually useless now, it's deprecated + // Subject alternative name is available + // Subject key identifier is available + // Custom extension which is the Polykey Version + + // there is a bit of weird thing + // the node signature custom extension + // It requires us to sign the certificate first with the private key + + // Extract that signature... + // Then create a extension with that signature + // Then add that to it again, and then sign it again + + // These 2 signing operations are using different keys... + // The first time, is the subject private key + // The second time is the issuer's private key + + // The second time is what makes it a self signed cert + // But the first time, allows us to have another part (the subject) end up signing the same information + + // Why do we do this + // It's to create a root certificate chain that allows rotations of the root key + // This means it's possible for the issuer to be the OLD node + // but the subject to be the NEW node + + // Therefore the node signature always has a signature indicating + // the subject has "signed" this certificate, which can be the new AND current node + + // While the cert signature is actually the issue signing it, which could be the old node + + // So yea, it's a cert with 2 signatures + // while officially x509 can only have 1 signature + + // Note that X509 is just a data format containing identity information + // At the end of the day, it could just be replaced with JWT & JWS + // But we seem to continue using X509 due to all the systems that consume X509 stuff( + // So there isn't an alternative certificate format that is purely JSON + // But one could definitely create one + // In a way, the sigchain/blockchain is this + + + // Basically, JWS (compact format) replace X509 pems + // JWS flattened format we can just use to represent certificates too + // Note that all those extensions... validity.. etc, are all info in the JWT itself + + // https://security.stackexchange.com/questions/128185/jwt-vs-client-certificates + + // I wonder if we should even bother presenting a X509 cert + // Remember this cert is then also presented for TLS purposes + // So we sort of still do need it, but an equivalent JWT can be presented + // And used as a certificate + + // However for now I think this is possible + + // You cannot mutate the existing certificate to set the new extension + // But you can create a new one, using information the old one + // With the new extension... I think that makes sense for what we want to do here.. + + // I don't think we need to have pkijs at all then + // this is all we are doing + + // Attempt to do this with custom extensions soon + +} + +void main();