checkpoint identity encryption and decryption works fully now

This commit is contained in:
2023-10-15 01:14:10 -04:00
parent d288609e49
commit ad93e35d73
35 changed files with 868 additions and 536 deletions

421
package-lock.json generated
View File

@@ -13,10 +13,11 @@
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
"@floating-ui/dom": "^1.5.3",
"@personaelabs/spartan-ecdsa": "^2.3.0",
"@rainbow-me/rainbowkit": "^1.1.1",
"@semaphore-protocol/group": "^3.10.1",
"@semaphore-protocol/identity": "^3.10.1",
"@wagmi/core": "^1.4.3",
"@web3modal/wagmi": "^3.1.0",
"autolinker": "^4.0.0",
"date-fns": "^2.30.0",
"discreetly-interfaces": "^0.1.39",
@@ -29,6 +30,7 @@
"qrcode": "^1.5.3",
"socket.io-client": "^4.7.1",
"svelte-material-icons": "^3.0.5",
"viem": "^1.16.5",
"wagmi": "^1.4.3"
},
"devDependencies": {
@@ -288,6 +290,18 @@
"node": ">=4"
}
},
"node_modules/@babel/parser": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"optional": true,
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
@@ -745,30 +759,6 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@ethereumjs/rlp": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz",
"integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==",
"bin": {
"rlp": "bin/rlp"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@ethereumjs/util": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz",
"integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==",
"dependencies": {
"@ethereumjs/rlp": "^4.0.1",
"ethereum-cryptography": "^2.0.0",
"micro-ftch": "^0.3.1"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@ethersproject/bignumber": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz",
@@ -1221,17 +1211,6 @@
"tslib": "^2.3.1"
}
},
"node_modules/@noble/curves": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
"dependencies": {
"@noble/hashes": "1.3.1"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/hashes": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
@@ -1278,17 +1257,6 @@
"node": ">= 8"
}
},
"node_modules/@personaelabs/spartan-ecdsa": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@personaelabs/spartan-ecdsa/-/spartan-ecdsa-2.3.1.tgz",
"integrity": "sha512-svnU2vx6eEhndNOcVxCMpFec1ubEg2VAqGBEMI/QB/eWD11VdFYEmb4boRqr1HzxHMAf8H/gJzg13stATYzJRQ==",
"dependencies": {
"@ethereumjs/util": "^8.0.3",
"@zk-kit/incremental-merkle-tree": "^1.0.0",
"elliptic": "^6.5.4",
"snarkjs": "^0.7.1"
}
},
"node_modules/@playwright/test": {
"version": "1.39.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz",
@@ -1393,19 +1361,6 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@scure/bip32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
"dependencies": {
"@noble/curves": "~1.1.0",
"@noble/hashes": "~1.3.1",
"@scure/base": "~1.1.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@scure/bip39": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
@@ -2454,6 +2409,136 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"dev": true
},
"node_modules/@vue/compiler-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
"integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.21.3",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-core/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"optional": true
},
"node_modules/@vue/compiler-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
"integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
"optional": true,
"dependencies": {
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
"integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-ssr": "3.3.4",
"@vue/reactivity-transform": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0",
"postcss": "^8.1.10",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-sfc/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"optional": true
},
"node_modules/@vue/compiler-ssr": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
"integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
"optional": true,
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
"integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==",
"optional": true,
"dependencies": {
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity-transform": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz",
"integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0"
}
},
"node_modules/@vue/reactivity-transform/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"optional": true
},
"node_modules/@vue/runtime-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz",
"integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==",
"optional": true,
"dependencies": {
"@vue/reactivity": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz",
"integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==",
"optional": true,
"dependencies": {
"@vue/runtime-core": "3.3.4",
"@vue/shared": "3.3.4",
"csstype": "^3.1.1"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
"integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
"optional": true,
"dependencies": {
"@vue/compiler-ssr": "3.3.4",
"@vue/shared": "3.3.4"
},
"peerDependencies": {
"vue": "3.3.4"
}
},
"node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==",
"optional": true
},
"node_modules/@wagmi/connectors": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-3.1.2.tgz",
@@ -3089,6 +3174,145 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@web3modal/core": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/core/-/core-3.1.0.tgz",
"integrity": "sha512-gXzUCVr4QkgkwxYgu7PBZIUsv3MEJRsYXUDSCU0LZz5BLXnMVSj0+YPhQ1msZLPCo0el/MTPtAzwu0VEOMijTQ==",
"dependencies": {
"valtio": "1.11.2"
}
},
"node_modules/@web3modal/polyfills": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/polyfills/-/polyfills-3.1.0.tgz",
"integrity": "sha512-y830qGJW16k7EZe6N2LIhcLWsHv+TkgC4FuARCSQzJPvVsKi/XsKXGk4Fbrv75nETF7AqCiFrEFQVGnAc7mg8A==",
"dependencies": {
"buffer": "6.0.3"
}
},
"node_modules/@web3modal/scaffold": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/scaffold/-/scaffold-3.1.0.tgz",
"integrity": "sha512-jxCsvkGvVTSds/ezwrX27Xkhlr4IPVeewKAiGxPNZKg9ZGkZ8c+7I2XZnTCKB5XQZvLgqIpGmSYhy4OqAKbHVg==",
"dependencies": {
"@web3modal/core": "3.1.0",
"@web3modal/ui": "3.1.0",
"lit": "3.0.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/@lit/reactive-element": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.0.tgz",
"integrity": "sha512-wn+2+uDcs62ROBmVAwssO4x5xue/uKD3MGGZOXL2sMxReTRIT0JXKyMXeu7gh0aJ4IJNEIG/3aOnUaQvM7BMzQ==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/lit": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.0.0.tgz",
"integrity": "sha512-nQ0teRzU1Kdj++VdmttS2WvIen8M79wChJ6guRKIIym2M3Ansg3Adj9O6yuQh2IpjxiUXlNuS81WKlQ4iL3BmA==",
"dependencies": {
"@lit/reactive-element": "^2.0.0",
"lit-element": "^4.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/lit-element": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.0.tgz",
"integrity": "sha512-N6+f7XgusURHl69DUZU6sTBGlIN+9Ixfs3ykkNDfgfTkDYGGOWwHAYBhDqVswnFGyWgQYR2KiSpu4J76Kccs/A==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0",
"@lit/reactive-element": "^2.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/scaffold/node_modules/lit-html": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.0.0.tgz",
"integrity": "sha512-DNJIE8dNY0dQF2Gs0sdMNUppMQT2/CvV4OVnSdg7BXAsGqkVwsE5bqQ04POfkYH5dBIuGnJYdFz5fYYyNnOxiA==",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/@web3modal/ui": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/ui/-/ui-3.1.0.tgz",
"integrity": "sha512-8Av6psGG/rO5M+5s+I7l2ESUWfeKkeXMIz/Bp2pP3a3yJ+EfO3V4kN1lO/bnbquMYvO+ETmvUXprvcBPMizSBQ==",
"dependencies": {
"lit": "3.0.0",
"qrcode": "1.5.3"
}
},
"node_modules/@web3modal/ui/node_modules/@lit/reactive-element": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.0.tgz",
"integrity": "sha512-wn+2+uDcs62ROBmVAwssO4x5xue/uKD3MGGZOXL2sMxReTRIT0JXKyMXeu7gh0aJ4IJNEIG/3aOnUaQvM7BMzQ==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0"
}
},
"node_modules/@web3modal/ui/node_modules/lit": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.0.0.tgz",
"integrity": "sha512-nQ0teRzU1Kdj++VdmttS2WvIen8M79wChJ6guRKIIym2M3Ansg3Adj9O6yuQh2IpjxiUXlNuS81WKlQ4iL3BmA==",
"dependencies": {
"@lit/reactive-element": "^2.0.0",
"lit-element": "^4.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/ui/node_modules/lit-element": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.0.tgz",
"integrity": "sha512-N6+f7XgusURHl69DUZU6sTBGlIN+9Ixfs3ykkNDfgfTkDYGGOWwHAYBhDqVswnFGyWgQYR2KiSpu4J76Kccs/A==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2-pre.0",
"@lit/reactive-element": "^2.0.0",
"lit-html": "^3.0.0"
}
},
"node_modules/@web3modal/ui/node_modules/lit-html": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.0.0.tgz",
"integrity": "sha512-DNJIE8dNY0dQF2Gs0sdMNUppMQT2/CvV4OVnSdg7BXAsGqkVwsE5bqQ04POfkYH5dBIuGnJYdFz5fYYyNnOxiA==",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/@web3modal/wagmi": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@web3modal/wagmi/-/wagmi-3.1.0.tgz",
"integrity": "sha512-PSzhHtj2GTY+36d6lbfzl4EVeuzA4XcMOW7+/CyLFzUDpG4BI5fsKrDbc7NqZU6L6BjN9dPi/oZO/Q+PM8MrPw==",
"dependencies": {
"@web3modal/polyfills": "3.1.0",
"@web3modal/scaffold": "3.1.0"
},
"optionalDependencies": {
"react": ">=17",
"react-dom": ">=17",
"vue": ">=3"
},
"peerDependencies": {
"@wagmi/core": ">=1",
"react": ">=17",
"react-dom": ">=17",
"viem": ">=1",
"vue": ">=3"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-dom": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/@zk-kit/incremental-merkle-tree": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@zk-kit/incremental-merkle-tree/-/incremental-merkle-tree-1.1.0.tgz",
@@ -3557,11 +3781,6 @@
"node": ">=8"
}
},
"node_modules/brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
},
"node_modules/browserslist": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
@@ -4380,25 +4599,6 @@
"integrity": "sha512-HiRdtyKS2+VhiXvjhMvvxiMC33FJJqTA5EB2YHgFZW6v7HkK4Q9Ahv2V7O2ZPgAjw+MyCJVMQvigj13H8t+wvA==",
"dev": true
},
"node_modules/elliptic": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
"integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
"dependencies": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",
"hash.js": "^1.0.0",
"hmac-drbg": "^1.0.1",
"inherits": "^2.0.4",
"minimalistic-assert": "^1.0.1",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"node_modules/elliptic/node_modules/bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -5018,17 +5218,6 @@
"fast-safe-stringify": "^2.0.6"
}
},
"node_modules/ethereum-cryptography": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz",
"integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==",
"dependencies": {
"@noble/curves": "1.1.0",
"@noble/hashes": "1.3.1",
"@scure/bip32": "1.3.1",
"@scure/bip39": "1.2.1"
}
},
"node_modules/ethers": {
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.8.0.tgz",
@@ -5647,16 +5836,6 @@
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
},
"node_modules/hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
"integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
"dependencies": {
"hash.js": "^1.0.3",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -6905,11 +7084,6 @@
"node": ">= 8"
}
},
"node_modules/micro-ftch": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz",
"integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg=="
},
"node_modules/micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
@@ -6977,11 +7151,6 @@
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
"node_modules/minimalistic-crypto-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -7087,7 +7256,7 @@
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true,
"devOptional": true,
"funding": [
{
"type": "github",
@@ -7443,7 +7612,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
"devOptional": true
},
"node_modules/picomatch": {
"version": "2.3.1",
@@ -7568,7 +7737,7 @@
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"devOptional": true,
"funding": [
{
"type": "opencollective",
@@ -8046,7 +8215,6 @@
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -8058,7 +8226,6 @@
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
@@ -8482,7 +8649,6 @@
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
}
@@ -9955,6 +10121,19 @@
"url": "https://opencollective.com/vitest"
}
},
"node_modules/vue": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz",
"integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==",
"optional": true,
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-sfc": "3.3.4",
"@vue/runtime-dom": "3.3.4",
"@vue/server-renderer": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",

View File

@@ -63,10 +63,11 @@
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
"@floating-ui/dom": "^1.5.3",
"@personaelabs/spartan-ecdsa": "^2.3.0",
"@rainbow-me/rainbowkit": "^1.1.1",
"@semaphore-protocol/group": "^3.10.1",
"@semaphore-protocol/identity": "^3.10.1",
"@wagmi/core": "^1.4.3",
"@web3modal/wagmi": "^3.1.0",
"autolinker": "^4.0.0",
"date-fns": "^2.30.0",
"discreetly-interfaces": "^0.1.39",
@@ -79,6 +80,7 @@
"qrcode": "^1.5.3",
"socket.io-client": "^4.7.1",
"svelte-material-icons": "^3.0.5",
"viem": "^1.16.5",
"wagmi": "^1.4.3"
}
}
}

View File

@@ -3,6 +3,13 @@
<head>
<meta charset="utf-8" />
<title>%sveltekit.error.message%</title>
<style>
body {
background-color: #1f1f1f;
color: #f1f1f1;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
}
</style>
</head>
<body>
<h1>Something didn't work right</h1>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import { identityExists } from '$lib/stores';
import { getIdentityBackup } from '$lib/utils/';
$: id = getIdentityBackup();
$: identityBackupExists = id ? true : false;
$: encodedIdentity = 'data:text/json;charset=utf-8,' + encodeURIComponent(id!);
let revealIdentity = false;
@@ -26,22 +26,25 @@
</script>
<div class="m-2 sm:m-3 flex flex-col gap-4">
{#if identityBackupExists}
{#if $identityExists == 'safe' || $identityExists == 'unsafe'}
<a class="btn variant-ghost-success" href={encodedIdentity} download="Discreetly_Identity.json"
>Download Identity Backup as JSON</a
>
{#if !revealIdentity}
<div class="btn variant-ghost-success" on:click={reveal}>Show Identity</div>
{:else}
<div class="btn variant-ghost-success" on:click={reveal}>Hide Identity</div>
<textarea id="reveleadIdentity" class="textarea text-sm" rows="9" value={id} />
{/if}
{:else if $identityExists == 'encrypted'}
<p class="h5 text-primary-500">
Identity exists but is encrypted. Please unlock your keystore to reveal your identity.
</p>
{:else}
<div class="text-sm text-primary-500">
Error getting your identity backup. Please contact the developers for help.
</div>
{/if}
{#if !revealIdentity}
<div class="btn variant-ghost-success" on:click={reveal}>Show Identity</div>
{:else}
<div class="btn variant-ghost-success" on:click={reveal}>Hide Identity</div>
<textarea id="reveleadIdentity" class="textarea text-sm" rows="9" value={id} />
{/if}
</div>
<style>

View File

@@ -7,7 +7,7 @@
<h2 class="h2 my-2 md:my-3 text-center">{heading}</h2>
{/if}
<slot name="header" />
<div class="flex flex-col gap-2 md:gap-5 max-w-xl w-full mx-auto pb-3">
<div class="flex flex-col gap-2 md:gap-5 max-w-5xl w-full mx-auto pb-3">
<slot />
</div>
</div>

View File

@@ -0,0 +1,101 @@
<script lang="ts">
import { createWeb3Modal, defaultWagmiConfig } from '@web3modal/wagmi';
import { getAccount, signMessage, watchAccount, disconnect, Config } from '@wagmi/core';
import { mainnet, arbitrum, optimism, base, polygon } from '@wagmi/core/chains';
import { onMount } from 'svelte';
import { getCommitment } from '$lib/utils';
import type { Web3Modal } from '@web3modal/wagmi/dist/types/src/client';
import { alertQueue, configStore, selectedServer } from '$lib/stores';
import { getEthAddressRoomNames } from '$lib/services/server';
const projectId = 'fcc228af1d77425f1482f07a961fb32d';
let modal: Web3Modal;
let btnEl: HTMLElement;
let address: string = '';
let loadingRooms: boolean = false;
let groups: string[] = [];
let isConnected = false;
const chains = [mainnet, arbitrum, optimism, base, polygon];
const metadata = {
name: 'Discreetly',
description: 'Join Discreetly via your Ethereum address.',
url: 'https://app.discreetly.chat',
icons: ['https://avatars.githubusercontent.com/u/37784886']
};
let wagmiConfig = defaultWagmiConfig({ chains, projectId, metadata });
async function proveOwnership() {
const commitment = getCommitment();
if (commitment) {
const signature = await signMessage({
message: commitment
});
} else {
alertQueue.enqueue('Error getting Identity');
}
}
function connect() {
if (getAccount().isConnected) {
disconnect();
} else {
modal.open();
}
}
onMount(() => {
modal = createWeb3Modal({ wagmiConfig, projectId, chains });
btnEl?.addEventListener('click', connect);
watchAccount((account) => {
address = account.address ?? '';
if (account.isConnected) {
btnEl!.innerText = 'Disconnect';
loadingRooms = true;
getEthAddressRoomNames($selectedServer, address)
.then((groupNames) => {
loadingRooms = false;
groups = groupNames;
})
.finally(() => {
loadingRooms = false;
});
isConnected = true;
} else {
btnEl!.innerText = 'Connect';
isConnected = false;
}
});
});
</script>
<div class="flex flex-col gap-3 justify-between">
<div>
<h3 class="h4 mb-2">Step 1: Connect your wallet</h3>
<button bind:this={btnEl} class="btn variant-outline-tertiary">Connect</button>
</div>
{#if isConnected}
<div>
<p class="h6">Your connected address is: {address}</p>
</div>
{#if groups.length > 0 || $configStore.beta}
<p>You are eligible for the following Ethereum Groups:</p>
<ul>
{#each groups as group}
<li>{group}</li>
{/each}
</ul>
<div>
<h3 class="h4 mb-2">
Step 2: Sign your Identity Commitment to prove ownership of this address
</h3>
<button on:click={proveOwnership} id="btn" class="btn variant-outline-success">Sign</button>
</div>
{:else if loadingRooms}
<p>Loading rooms...</p>
{:else}
<p>You are not eligible for any Ethereum Groups.</p>
{/if}
{/if}
</div>

View File

@@ -1,9 +1,8 @@
<script lang="ts">
import SelectServer from '$lib/components/SelectServer.svelte';
import { alertAll } from '$lib/utils';
import { inviteCode } from '$lib/utils/inviteCode';
import { inviteCode } from '$lib/gateways/inviteCode';
import { alertQueue } from '$lib/stores';
export let code = '';
let acceptedRoomNames: string[] = [];
let loading = false;
let err: string | undefined;
@@ -13,13 +12,13 @@
inviteCode(code)
.then(({ acceptedRoomNames, err }) => {
if (err) {
alertAll(err);
alertQueue.enqueue(err);
} else {
acceptedRoomNames = acceptedRoomNames;
}
})
.catch((err) => {
alertAll(err);
alertQueue.enqueue(err);
})
.finally(() => {
loading = false;
@@ -80,52 +79,46 @@
}
</script>
<div class="flex flex-col items-center px-2 mb-2 sm:mb-4">
<label class="label w-full" for="selectServer"
><span class="h5">Select or Add a Server</span>
<SelectServer />
</label>
<label class="label mt-3" for="inviteCode">
<span class="h5">Invite Code</span>
<input
class="input"
type="text"
placeholder="Invite Code"
id="inviteCode"
bind:value={code}
on:keydown={(event) => inviteCodeKeyPress(event)}
/>
{#if !loading}
<button
class="btn variant-ghost-success"
type="button"
disabled={!code}
on:click={() => addCode(code)}>Submit</button
>
{:else}
<p class="italic">Loading...</p>
{/if}
</label>
<label class="label" for="inviteCode">
<span class="h5">Enter Invite Code:</span>
<input
class="input"
type="text"
placeholder="Invite Code"
id="inviteCode"
bind:value={code}
on:keydown={(event) => inviteCodeKeyPress(event)}
/>
</label>
{#if !loading}
<button
class="btn variant-ghost-success mt-3"
type="button"
disabled={!code}
on:click={() => addCode(code)}>Submit</button
>
{:else}
<p class="italic">Loading...</p>
{/if}
{#if err}
<aside class="p">
<div>
If you are having trouble and would like help, please message us on <a
href="https://discord.gg/brJQ36KVxk"
class="underline link">Discord</a
>
</div>
</aside>
{/if}
{#if acceptedRoomNames.length > 0}
<p class="text-center mt-2">You've been added to:</p>
<div class="my-2">
{#each acceptedRoomNames as name}
<ins class="ins border-y border-success-800">{name}</ins>
{/each}
{#if err}
<aside class="p">
<div>
If you are having trouble and would like help, please message us on <a
href="https://discord.gg/brJQ36KVxk"
class="underline link">Discord</a
>
</div>
{/if}
</div>
</aside>
{/if}
{#if acceptedRoomNames.length > 0}
<p class="text-center mt-2">You've been added to:</p>
<div class="my-2">
{#each acceptedRoomNames as name}
<ins class="ins border-y border-success-800">{name}</ins>
{/each}
</div>
{/if}
<style>
aside {

View File

@@ -1,86 +0,0 @@
<script lang="ts">
import { passwordSet, configStore, keyStore } from '$lib/stores';
import Lock from 'svelte-material-icons/Lock.svelte';
import LockOpen from 'svelte-material-icons/LockOpenVariant.svelte';
import NoPassword from 'svelte-material-icons/LockOff.svelte';
import { getModalStore, type ModalSettings } from '@skeletonlabs/skeleton';
import { deriveKey, hashPassword } from '$lib/crypto/crypto';
import { onMount } from 'svelte';
import { alertAll, setPassword } from '$lib/utils';
const modalStore = getModalStore();
export let cls: string = '';
let minPasswordLength = 3;
function setPasswordModal() {
const modal: ModalSettings = {
type: 'prompt',
title: 'Set a Password',
body: 'Set a password or pin to encrypt your identity and room passwords',
value: '',
valueAttr: { type: 'password', minlength: minPasswordLength, required: true },
response: async (r: string) => {
if (r != '' && r != null && r != undefined && r.length >= minPasswordLength) {
setPassword(r);
}
}
};
modalStore.trigger(modal);
}
function unlock() {
const modal: ModalSettings = {
type: 'prompt',
title: 'Unlock',
body: 'Enter your password to unlock your keystores',
value: '',
valueAttr: { type: 'password', minlength: 4, required: true },
response: async (r: string) => {
if (r != 'false' && r != '' && r != null && r != undefined) {
const hashedPassword = await hashPassword(r);
if ($configStore.hashedPwd == hashedPassword) {
$keyStore = await deriveKey(r);
} else {
alertAll('Incorrect Password');
$keyStore = null;
}
}
}
};
modalStore.trigger(modal);
}
function lock() {
$keyStore = null;
}
onMount(() => {
console.debug(
'PadLock:',
$passwordSet ? 'password set,' : 'password not set,',
$keyStore !== null && $keyStore !== undefined ? 'unlocked' : 'locked'
);
});
</script>
<div class={cls} id="lock">
{#if $passwordSet}
{#if $keyStore instanceof CryptoKey}
<div on:click={lock} title="Unlocked, click to lock">
<LockOpen class="w-full text-warning-300-600-token" />
</div>
{:else}
<div on:click={unlock} title="Locked" class="w-full text-success-500"><Lock /></div>
{/if}
{:else}
<div on:click={setPasswordModal} title="Password not set">
<NoPassword class="w-full text-error-500" />
</div>
{/if}
</div>
<style>
#lock {
cursor: pointer;
}
</style>

View File

@@ -1,18 +1,12 @@
<script lang="ts">
import Button from './button.svelte';
import type { ButtonI } from '$lib/types';
export let title: string;
export let buttons: ButtonI[] = [];
</script>
<div class="m-4 px-5 py-4 text-center bg-body-tertiary rounded-2">
<h2 class="text-body-emphasis m-3">{title}</h2>
<div class="col-lg-8 mx-auto fs-5 text-muted">
<slot />
</div>
<div class="d-inline-flex gap-5 my-3">
{#each buttons as button}
<Button link={button.link} cls={button.cls} text={button.text} />
{/each}
</div>
<div class="card">
{#if $$slots.header}
<header class="card-header h3"><slot name="header" /></header>
{/if}
{#if $$slots.description}
<aside class="p italic px-4 pt-3"><slot name="description" /></aside>
{/if}
<section class="p-4"><slot /></section>
{#if $$slots.footer}
<footer class="card-footer"><slot name="footer" /></footer>
{/if}
</div>

View File

@@ -1,4 +1,5 @@
import { addConsoleMessage } from '$lib/utils';
import { alertQueue, configStore } from '$lib/stores';
import { get } from 'svelte/store';
/**
* Derives an encryption key from a given password using PBKDF2.
@@ -47,14 +48,17 @@ export async function encrypt(plainText: string, key: CryptoKey): Promise<string
key,
encoder.encode(plainText)
);
console.log(encryptedContent);
const encryptedContentArr = new Uint8Array(encryptedContent);
const encryptedBytes = [...iv, ...encryptedContentArr];
return btoa(String.fromCharCode(...encryptedBytes));
} else if (get(configStore).hashedPwd) {
alertQueue.enqueue('Unlock your identity with /unlock or click on the lock');
console.error('Unlock your identity with /unlock or click on the lock');
return null;
} else {
addConsoleMessage('No Password Set, please set a password with /setpassword', 'error');
alertQueue.enqueue('No Password Set, please set a password with /setpassword');
console.error('No password set, please set a password first');
return null;
}
@@ -66,7 +70,6 @@ export async function decrypt(cipherText: string, key: CryptoKey): Promise<strin
}
if (key instanceof CryptoKey) {
const decoder = new TextDecoder();
console.log(cipherText);
const encryptedBytes = Uint8Array.from(atob(cipherText), (c) => c.charCodeAt(0));
const iv = encryptedBytes.slice(0, 12);
@@ -79,8 +82,12 @@ export async function decrypt(cipherText: string, key: CryptoKey): Promise<strin
);
return decoder.decode(decryptedContent);
} else if (get(configStore).hashedPwd) {
alertQueue.enqueue('Unlock your identity with /unlock or click on the lock');
console.error('Unlock your identity with /unlock or click on the lock');
return null;
} else {
addConsoleMessage('No Password Set, please set a password with /setpassword', 'error');
alertQueue.enqueue('No Password Set, please set a password with /setpassword');
console.error('No password set, please set a password first');
return null;
}

View File

@@ -3,8 +3,10 @@ import { IdentityStoreE } from './types';
import { dev } from '$app/environment';
let defaultServers: serverStoreI;
let beta = false;
if (dev) {
beta = true;
defaultServers = {
'https://server.discreetly.chat/': {
name: 'Discreetly Server',
@@ -23,6 +25,7 @@ if (dev) {
}
};
}
const configDefaults: ConfigurationI = {
signUpStatus: {
completedSignup: false,
@@ -31,7 +34,7 @@ const configDefaults: ConfigurationI = {
identityStore: IdentityStoreE.NO_IDENTITY,
numMessagesToSave: 500,
hashedPwd: undefined,
beta: false
beta: beta
};
export { defaultServers, configDefaults };

View File

@@ -1,6 +1,6 @@
import { alertAll, getCommitment, updateRooms } from '$lib/utils/';
import { getCommitment, updateRooms } from '$lib/utils/';
import { postInviteCode } from '$lib/services/server';
import { selectedServer, configStore } from '$lib/stores';
import { selectedServer, configStore, alertQueue } from '$lib/stores';
import { get } from 'svelte/store';
import type { JoinResponseI } from '$lib/types';
@@ -11,8 +11,7 @@ export async function inviteCode(newCode: string) {
try {
const idc = getCommitment();
if (!idc) {
// TODO convert this to alertAll at some point
alertAll('No identity commitment found');
alertQueue.enqueue('No identity commitment found');
throw new Error('No identity commitment found');
}
const result = (await postInviteCode(server, {

View File

@@ -15,6 +15,13 @@ export async function getServerData(serverUrl: string): Promise<ServerI> {
return get([serverUrl]) as Promise<ServerI>;
}
export async function getEthAddressRoomNames(
server: string,
ethAddress: string
): Promise<string[]> {
return get([server, `api/eth/group/${ethAddress}`]) as Promise<string[]>;
}
export async function postInviteCode(serverUrl: string, data: { code: string; idc: string }) {
return post([serverUrl, 'join'], data);
}

View File

@@ -1,5 +1,5 @@
import { storable, sessionable, encryptable } from './storeFactory';
import { derived, writable, type Readable } from 'svelte/store';
import { storable, sessionable, encryptable, queueable } from './storeFactory';
import { derived, writable } from 'svelte/store';
import { configDefaults } from '$lib/defaults';
import type {
ConfigurationI,
@@ -14,7 +14,6 @@ import type {
roomKeyStoreI,
keyStoreI
} from '$lib/types';
import { decrypt } from '$lib/crypto/crypto';
/* ------------------ Server State ------------------*/
/**
@@ -90,6 +89,8 @@ export const rateLimitStore = storable({} as rateLimitStoreI, 'rateLimit');
*/
export const keyStore = writable({} as keyStoreI);
export const alertQueue = queueable([] as string[]);
/**
* @description Configuration store, stores the user's settings
*/
@@ -130,13 +131,50 @@ export const identityStore = storable({} as IdentityStoreI, 'identity');
*/
export const identityKeyStore = encryptable({} as IdentityStoreI, 'identityencrypted');
export const identityExists = derived(
[identityStore, identityKeyStore],
([$identityStore, $identityKeyStore]) => {
if ($identityStore._commitment || $identityKeyStore._commitment) {
return true;
export const lockStateStore = derived(
[keyStore, passwordSet],
([$keyStore, $passwordSet]): 'unlocked' | 'locked' | null => {
if ($passwordSet) {
if ($keyStore instanceof CryptoKey) {
return 'unlocked';
} else {
return 'locked';
}
} else {
return false;
return null;
}
}
);
export const identityExists = derived(
[identityStore, identityKeyStore, lockStateStore],
([$identityStore, $identityKeyStore, $lockStateStore]):
| 'safe'
| 'unsafe'
| 'encrypted'
| null => {
const id = $identityKeyStore;
const id_ = $identityStore;
if ($lockStateStore == null) {
if (id_._commitment?.length > 0) {
return 'unsafe';
} else {
return null;
}
} else if ($lockStateStore === 'unlocked') {
if (id._commitment) {
return 'safe';
} else {
return null;
}
} else if ($lockStateStore === 'locked') {
if (typeof id === 'object') {
return 'encrypted';
} else {
return null;
}
} else {
return null;
}
}
);

View File

@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { writable, get } from 'svelte/store';
import type { Writable } from 'svelte/store';
import { keyStore } from '.';
import { keyStore, lockStateStore } from '.';
import { decrypt, encrypt } from '$lib/crypto/crypto';
import type { EncryptableT } from '$lib/types';
export function storable<Type>(data: Type, localStorageKey: string): Writable<Type> {
const store = writable<Type>(data);
@@ -73,29 +74,31 @@ export function sessionable<Type>(data: Type, sessionStorageKey: string): Writab
};
}
export function encryptable<Type>(data: Type, localStorageKey: string): Writable<Type> {
export function encryptable<Type>(data: Type, localStorageKey: string): EncryptableT<Type> {
const store = writable<Type>(data);
const { subscribe, set } = store;
const isBrowser = typeof window !== 'undefined';
if (isBrowser && localStorage.getItem(localStorageKey) !== null) {
const storedValue = localStorage.getItem(localStorageKey);
if (storedValue) {
try {
const key = get(keyStore);
if (!key) {
throw new Error('Key store not initialized, cannot encrypt data');
}
console.debug('Encryptable State: ', storedValue, key);
decrypt(storedValue, key).then((decryptedData) => {
if (decryptedData !== null) {
set(JSON.parse(decryptedData) as Type);
} else {
console.error('Error decrypting data');
function read() {
if (isBrowser && localStorage.getItem(localStorageKey) !== null) {
const storedValue = localStorage.getItem(localStorageKey);
if (storedValue) {
try {
const key = get(keyStore);
if (!(get(lockStateStore) === 'unlocked') || !key) {
throw new Error('Key store not initialized, cannot encrypt data');
}
});
} catch (e) {
console.warn(`Error reading local storage for key: ${localStorageKey}; ${e}`);
decrypt(storedValue, key).then((decryptedData) => {
if (decryptedData !== null) {
set(JSON.parse(decryptedData)) as Type;
} else {
console.error('Error decrypting data');
}
});
} catch (e) {
console.warn(`Error reading local storage for key: ${localStorageKey}; ${e}`);
}
}
}
}
@@ -134,6 +137,43 @@ export function encryptable<Type>(data: Type, localStorageKey: string): Writable
console.error('Error encrypting data');
}
});
},
read
};
}
export type QueueStore = ReturnType<typeof queueService>;
declare function queueService(): {
set: (value: any[]) => void;
subscribe: (run: (value: any[]) => any, invalidate?: any) => () => void;
update: (callBack: (value: any[]) => any[]) => void;
enqueue: (value: any) => void;
dequeue: () => any;
};
export function queueable<Type>(data: Type[]): ReturnType<typeof queueService> {
const store = writable<Type[]>(data);
const { subscribe, set } = store;
return {
subscribe,
set: (value: Type[]) => {
set(value);
},
update: (callBack: (value: Type[]) => Type[]) => {
const updatedStore = callBack(get(store));
set(updatedStore);
},
enqueue: (value: Type) => {
const updatedStore = get(store);
updatedStore.push(value);
set(updatedStore);
},
dequeue: () => {
const updatedStore = get(store);
const val = updatedStore.shift();
set(updatedStore);
return val;
}
};
}

View File

@@ -1,3 +1,4 @@
export * from './stores';
export * from './enums';
export * from './interfaces';
export * from './svelte';

View File

@@ -1,5 +1,7 @@
import type { ServerI, MessageI, HexColor } from 'discreetly-interfaces';
import type { RoomI } from './interfaces';
import type { Identity } from '@semaphore-protocol/identity';
import type { Writable } from 'svelte/store';
// Keyed by server URL
export interface serverStoreI {
@@ -58,3 +60,7 @@ export interface roomKeyStoreI {
}
export type keyStoreI = CryptoKey | undefined | null;
export interface EncryptableT<Type> extends Writable<Type> {
read: () => void;
}

15
src/lib/types/svelte.ts Normal file
View File

@@ -0,0 +1,15 @@
import type { Toast, ToastSettings } from '@skeletonlabs/skeleton';
import type { Subscriber, Invalidator, Unsubscriber } from 'svelte/motion';
export type toastStoreT = {
subscribe: (
this: void,
run: Subscriber<Toast[]>,
invalidate?: Invalidator<Toast[]> | undefined
) => Unsubscriber;
close: (id: string) => void;
trigger: (toast: ToastSettings) => string;
freeze: (index: number) => void;
unfreeze: (index: number) => void;
clear: () => void;
};

View File

@@ -1,18 +0,0 @@
import { getToastStore } from '@skeletonlabs/skeleton';
import { addConsoleMessage } from './console';
export function alertToast(alertMessage: string, timeout = 5000) {
const toastStore = getToastStore();
toastStore.trigger({ message: alertMessage, timeout: timeout });
console.warn(alertMessage);
}
export function alertAll(
alertMessage: string,
level: 'warning' | 'info' | 'userinput' | 'error' | 'space' | undefined = 'warning',
timeout = 5000
) {
alertToast(alertMessage, timeout);
console.warn(alertMessage);
addConsoleMessage(alertMessage, level);
}

View File

@@ -1,103 +1,90 @@
import { get } from 'svelte/store';
import { configStore, identityKeyStore, identityStore, keyStore } from '../stores';
import {
alertQueue,
configStore,
identityKeyStore,
identityStore,
identityExists,
keyStore,
lockStateStore
} from '../stores';
import { Identity } from '@semaphore-protocol/identity';
import type { IdentityStoreI } from '$lib/types';
import { addConsoleMessage } from './console';
export function createIdentity(regenerate = false): 'created' | 'exists' | 'unsafe' | 'error' {
const old_id = get(identityKeyStore) as unknown as IdentityStoreI;
if (!old_id._commitment || regenerate) {
const identityStatus = get(identityExists);
console.log(identityStatus);
if (!get(identityExists) || regenerate) {
console.debug('Creating identity');
const identity = new Identity() as unknown as IdentityStoreI;
const config = get(configStore);
const key = get(keyStore);
const lockState = get(lockStateStore);
if (config.hashedPwd && config.hashedPwd.length > 0) {
if (key) {
if (lockState === 'unlocked') {
try {
identityKeyStore.set(identity);
if (get(identityKeyStore)._commitment !== null) {
console.log('Identity Created! Congrats on your new journey');
if (get(identityExists) === 'safe') {
alertQueue.enqueue('Identity Created! Congrats on your new journey');
return 'created';
} else {
console.error('Error creating identity');
alertQueue.enqueue('Error creating identity');
return 'error';
}
} catch (e) {
console.error(`Error creating identity: ${e}`);
alertQueue.enqueue(`Error creating identity: ${e}`);
return 'error';
}
} else {
addConsoleMessage(
'Unlock your identity with /unlock or click on the lock in the corner',
'error'
);
alertQueue.enqueue('Unlock your account by clicking on the lock');
return 'error';
}
} else {
addConsoleMessage(
'For your security please set a password with /password or click on the lock in the corner',
'warning'
alertQueue.enqueue(
'For your security please set a password with /password or click on the lock in the corner'
);
identityStore.set(identity);
return 'unsafe';
}
} else {
console.warn('Identity already exists');
alertQueue.enqueue('Identity already exists');
return 'exists';
}
}
export function getIdentity(): IdentityStoreI {
export function getIdentity(): IdentityStoreI | null {
const decryptedIdentity = get(identityKeyStore) as unknown as IdentityStoreI;
if (decryptedIdentity !== null) {
if (decryptedIdentity._commitment) {
console.log(decryptedIdentity);
return decryptedIdentity;
} else {
const identity = get(identityStore);
if (identity !== null) {
console.warn('Identity not encrypted, set a password!');
if (identity._commitment?.length > 0) {
alertQueue.enqueue('Identity not encrypted, set a password!');
return identity;
} else {
console.warn('Identity not created, create an identity!');
alertQueue.enqueue('Identity not created, create an identity!');
}
}
throw new Error('Identity not created');
return null;
}
export function getCommitment() {
const id = get(identityKeyStore) as IdentityStoreI;
const id_ = get(identityStore);
if (id !== null && id !== undefined) {
export function getCommitment(): string | null {
const id = getIdentity();
if (id) {
return id._commitment;
}
if (id_ !== null && id_ !== undefined) {
console.warn('PLEASE ADD A PASSWORD!');
return id_._commitment;
} else {
return null;
}
}
export function getIdentityBackup() {
const id = get(identityKeyStore);
const id_ = get(identityStore);
if (id !== null && id !== undefined) {
export function getIdentityBackup(): string | null {
const id = getIdentity();
if (id) {
return JSON.stringify(id);
} else {
return null;
}
if (id_ !== null && id_ !== undefined) {
console.warn('PLEASE ADD A PASSWORD!');
return JSON.stringify(id_);
}
}
export function doesIdentityExist(): 'safe' | 'unsafe' | 'none' {
const id = get(identityKeyStore);
const id_ = get(identityStore);
if (id._commitment !== null && id._commitment !== undefined) {
return 'safe';
}
if (id_._commitment !== null && id_._commitment !== undefined) {
console.warn('PLEASE ADD A PASSWORD');
return 'unsafe';
}
return 'none';
}
export function encryptIdentity(identity: IdentityStoreI) {

View File

@@ -1,7 +1,5 @@
export * from './alert';
export * from './console';
export * from './identity';
export * from './inviteCode';
export * from './password';
export * from './rateLimit';
export * from './rooms';

View File

@@ -1,14 +1,22 @@
import { deriveKey, hashPassword } from '$lib/crypto/crypto';
import { get, writable } from 'svelte/store';
import { configStore, identityKeyStore, identityStore, keyStore } from '$lib/stores';
import { doesIdentityExist, encryptIdentity } from './identity';
import { get } from 'svelte/store';
import {
configStore,
identityKeyStore,
identityStore,
keyStore,
identityExists,
alertQueue,
roomKeyStore
} from '$lib/stores';
import { encryptIdentity } from './identity';
import type { IdentityStoreI } from '$lib/types';
export async function setPassword(password: string): Promise<'success' | string> {
const hashedPassword = await hashPassword(password);
let identity: IdentityStoreI | undefined;
if (hashedPassword !== null) {
const idStatus = doesIdentityExist();
const idStatus = get(identityExists);
/******************************
* STAGE1: DECRYPT/STORE EVERYTHING INTO MEMORY
******************************/
@@ -49,3 +57,18 @@ export async function setPassword(password: string): Promise<'success' | string>
}
return 'error';
}
export async function unlockPadlock(password: string) {
const hashedPassword = await hashPassword(password);
if (get(configStore).hashedPwd == hashedPassword) {
deriveKey(password).then((key) => {
keyStore.set(key);
// Don't remove these. There is no reactive way to automatically decrypt encrypted stores, so we have to trigger it manually when the keys are derived
identityKeyStore.read();
roomKeyStore.read();
});
} else {
alertQueue.enqueue('Incorrect Password');
keyStore.set(null);
}
}

View File

@@ -5,7 +5,8 @@ import {
selectedServer,
serverStore,
messageStore,
currentSelectedRoom
currentSelectedRoom,
alertQueue
} from '$lib/stores';
import { get } from 'svelte/store';
import {
@@ -44,8 +45,7 @@ async function getRoomIdsIfEmpty(server: string, roomIds: string[]): Promise<str
if (roomIds.length < 1) {
const idc = getCommitment();
if (!idc) {
// TODO convert this to alertAll at some point
console.error('No identity commitment found');
alertQueue.enqueue('No identity commitment found');
throw new Error('No identity commitment found');
}
return await getRoomIdsByIdentityCommitment(server, idc);

View File

@@ -1,12 +1,12 @@
<script lang="ts">
import { Modal, initializeStores } from '@skeletonlabs/skeleton';
import { Modal, getToastStore, initializeStores } from '@skeletonlabs/skeleton';
import { Toast, storePopup } from '@skeletonlabs/skeleton';
import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom';
import '../app.postcss';
import { onMount } from 'svelte';
import AppHeader from './AppHeader.svelte';
import Loading from '$lib/components/loading.svelte';
import { selectedServer } from '$lib/stores';
import { selectedServer, alertQueue } from '$lib/stores';
import { getServerList, isInputFieldFocused, setDefaultServers } from '$lib/utils/';
import { updateServer } from '$lib/utils/';
import { Drawer, getDrawerStore } from '@skeletonlabs/skeleton';
@@ -14,10 +14,12 @@
import SelectRoom from '$lib/components/SelectRoom.svelte';
import Console from './console/Console.svelte';
import Sidebar from './Sidebar.svelte';
import AppFooter from './AppFooter.svelte';
import AppFooter from './Footer.svelte';
initializeStores();
const toastStore = getToastStore();
const drawerStore = getDrawerStore();
// Hack to get BigInt <-> JSON compatibility
(BigInt.prototype as any).toJSON = function () {
@@ -46,6 +48,12 @@
}
}
});
setInterval(() => {
const toast = alertQueue.dequeue();
if (toast) {
toastStore.trigger({ message: toast });
}
}, 500);
});
</script>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { page } from '$app/stores';
import { passwordSet, configStore, keyStore } from '$lib/stores';
import { passwordSet, configStore, keyStore, alertQueue } from '$lib/stores';
import {
getModalStore,
TabAnchor,
@@ -23,7 +23,7 @@
import LockOpen from 'svelte-material-icons/LockOpenVariant.svelte';
import NoPassword from 'svelte-material-icons/LockOff.svelte';
import Door from 'svelte-material-icons/Door.svelte';
import { alertAll } from '$lib/utils';
import { unlockPadlock } from '$lib/utils';
const modalStore = getModalStore();
const drawerStore = getDrawerStore();
@@ -49,13 +49,7 @@
valueAttr: { type: 'password', minlength: 4, required: true },
response: async (r: string) => {
if (r != 'false' && r != '' && r != null && r != undefined) {
const hashedPassword = await hashPassword(r);
if ($configStore.hashedPwd == hashedPassword) {
$keyStore = await deriveKey(r);
} else {
alertAll('Incorrect Password');
$keyStore = null;
}
unlockPadlock(r);
}
}
};
@@ -65,13 +59,6 @@
function lock() {
$keyStore = null;
}
onMount(() => {
console.debug(
'PadLock:',
$passwordSet ? 'password set,' : 'password not set,',
$keyStore !== null && $keyStore !== undefined ? 'unlocked' : 'locked'
);
});
</script>
<div class="card p-4 w-72 shadow-xl" data-popup="popupMenu">
@@ -79,7 +66,7 @@
<!-- (optionally you can provide a label here) -->
<ul>
<li id="will-close">
<a href="/settings">
<a href="/about">
<Information />
<span class="flex-auto">About</span>
</a>

View File

@@ -15,9 +15,9 @@
import NoPassword from 'svelte-material-icons/LockOff.svelte';
import Plus from 'svelte-material-icons/Plus.svelte';
import { hashPassword, deriveKey } from '$lib/crypto/crypto';
import { configStore, keyStore, passwordSet } from '$lib/stores';
import { alertAll } from '$lib/utils';
import { configStore, keyStore, passwordSet, alertQueue } from '$lib/stores';
import { onMount } from 'svelte';
import { unlockPadlock } from '$lib/utils';
const modalStore = getModalStore();
@@ -30,13 +30,7 @@
valueAttr: { type: 'password', minlength: 4, required: true },
response: async (r: string) => {
if (r != 'false' && r != '' && r != null && r != undefined) {
const hashedPassword = await hashPassword(r);
if ($configStore.hashedPwd == hashedPassword) {
$keyStore = await deriveKey(r);
} else {
alertAll('Incorrect Password');
$keyStore = null;
}
unlockPadlock(r);
}
}
};
@@ -46,14 +40,6 @@
function lock() {
$keyStore = null;
}
onMount(() => {
console.debug(
'PadLock:',
$passwordSet ? 'password set,' : 'password not set,',
$keyStore !== null && $keyStore !== undefined ? 'unlocked' : 'locked'
);
});
</script>
<AppRail height="h-full">

View File

@@ -1,8 +1,14 @@
<script lang="ts">
import { currentSelectedRoom, keyStore, rateLimitStore, roomKeyStore } from '$lib/stores';
import {
currentSelectedRoom,
keyStore,
rateLimitStore,
roomKeyStore,
alertQueue
} from '$lib/stores';
import { genProof } from '$lib/crypto/rlnProver';
import type { Socket } from 'socket.io-client';
import { getIdentity, alertToast, clearMessageHistory, alertAll } from '$lib/utils';
import { getIdentity, clearMessageHistory } from '$lib/utils';
import Send from 'svelte-material-icons/Send.svelte';
import { decrypt, encrypt } from '$lib/crypto/crypto';
@@ -32,23 +38,25 @@
function checkStatus(): boolean {
if (!connected) {
alertToast('NOT CONNECTED TO CHAT SERVER');
alertQueue.enqueue('NOT CONNECTED TO CHAT SERVER');
sendingMessage = false;
return false;
}
if (messageText.length < 1) {
alertToast('MESSAGE IS EMPTY');
alertQueue.enqueue('MESSAGE IS EMPTY');
sendingMessage = false;
return false;
}
if (messageText.length > 2000) {
alertToast('MESSAGE IS TOO LONG, SENDING MAY FAIL UNDER NETWORK CONSTRAINED CONDITIONS');
alertQueue.enqueue(
'MESSAGE IS TOO LONG, SENDING MAY FAIL UNDER NETWORK CONSTRAINED CONDITIONS'
);
sendingMessage = false;
return false;
}
// This is 100% thanks to Violet for spamming the chat with spaces
if (messageText.replaceAll(' ', '') == '') {
alertToast('MESSAGE IS EMPTY');
alertQueue.enqueue('MESSAGE IS EMPTY');
sendingMessage = false;
return false;
}
@@ -56,7 +64,7 @@
}
function help() {
alertToast('Commands: /clear, /help');
alertQueue.enqueue('Commands: /clear, /help');
}
function processCommand(value: string) {
@@ -154,11 +162,11 @@
} catch (err: any) {
console.error('Error sending message: ', err);
if (err.message.includes('Merkle Proof')) {
alertToast(
alertQueue.enqueue(
"Couldn't generate Merkle Proof. Maybe you don't belong in the room or don't have an updated member list."
);
} else {
alertToast(err as string);
alertQueue.enqueue(err as string);
}
} finally {
sendingMessage = false;

View File

@@ -1,13 +1,14 @@
<script lang="ts">
import { deriveKey, hashPassword } from '$lib/crypto/crypto';
import { configStore, identityKeyStore, keyStore, passwordSet } from '$lib/stores';
import {
addConsoleMessage,
clearConsoleMessages,
doesIdentityExist,
setPassword
} from '$lib/utils/';
import { inviteCode } from '$lib/utils/inviteCode';
configStore,
identityKeyStore,
keyStore,
passwordSet,
identityExists
} from '$lib/stores';
import { addConsoleMessage, clearConsoleMessages, setPassword, unlockPadlock } from '$lib/utils/';
import { inviteCode } from '$lib/gateways/inviteCode';
import { createIdentity } from '$lib/utils/';
export let placeholder: string = 'Enter / Command';
@@ -79,20 +80,7 @@
addConsoleMessage('Locked!');
break;
case '/unlock':
const hashedPwd = await hashPassword(args[0]);
if (hashedPwd === $configStore.hashedPwd) {
if ($keyStore && !(args[1] === 'force')) {
addConsoleMessage(
'Already Unlocked! use `/unlock PASSWORD force` to override this and derive the key again',
'warning'
);
break;
}
$keyStore = await deriveKey(args[0]);
addConsoleMessage('Unlocked!');
} else {
addConsoleMessage(`Invalid password!`, 'warning');
}
unlockPadlock(args[0]);
break;
case '/export':
addConsoleMessage('Exporting Identity');
@@ -117,7 +105,7 @@
addConsoleMessage(`Identity: ${$identityKeyStore}`);
break;
case '/createIdentity':
const idStatus = doesIdentityExist();
const idStatus = $identityExists;
if (idStatus === 'safe') {
addConsoleMessage('✅ Identity Exists Already');
} else if (idStatus === 'unsafe') {

View File

@@ -1,8 +1,46 @@
<script lang="ts">
import Container from '$lib/components/Container.svelte';
import JoinMore from './JoinMore.svelte';
import EthereumWallet from '$lib/components/Gateways/EthereumWallet.svelte';
import InviteCodeGateway from '$lib/components/Gateways/InviteCode.svelte';
import SelectServer from '$lib/components/SelectServer.svelte';
import Card from '$lib/components/card.svelte';
import { configStore } from '$lib/stores';
</script>
<Container heading="Join More Communities">
<JoinMore />
<div class="variant-ghost-success p-4 rounded-token">
<h3 class="h4">Select Server, or add a new Server:</h3>
<SelectServer />
</div>
<div class="flex flex-row flex-wrap gap-5 justify-evenly">
<Card>
<svelte:fragment slot="header">Join via invite code:</svelte:fragment>
<svelte:fragment slot="description"
>If you were given an invite code, you can
</svelte:fragment>
<InviteCodeGateway code={$configStore.signUpStatus.inviteCode} />
</Card>
<Card>
<svelte:fragment slot="header">Discord Bot</svelte:fragment>
<svelte:fragment slot="description"
>Add the discord bot to your server Today!
</svelte:fragment>
<a
href="https://discord.com/api/oauth2/authorize?client_id=1142162852132700200&permissions=2147483648&scope=bot"
class="btn variant-ghost-primary">Invite Discord Bot!</a
>
</Card>
<Card>
<svelte:fragment slot="header">Join via Jubmojii:</svelte:fragment>
<svelte:fragment slot="description">Coming Soon!</svelte:fragment>
</Card>
<Card>
<svelte:fragment slot="header">Join via Ethereum Address:</svelte:fragment>
<svelte:fragment slot="description"
>Are you a genesis validator, daohack survivor, nouns holder? You can join using your
Ethereum address.
</svelte:fragment>
<EthereumWallet />
</Card>
</div>
</Container>

View File

@@ -1,13 +0,0 @@
<script lang="ts">
import Join from '$lib/components/Join.svelte';
import { configStore } from '$lib/stores';
</script>
<div class="card variant-ghost-tertiary">
<header class="card-header">
<h4 class="h4">Join More Rooms</h4>
</header>
<section class="p-2 mb-2">
<Join code={$configStore.signUpStatus.inviteCode} />
</section>
</div>

View File

@@ -1,5 +1,4 @@
<script lang="ts">
import { identityExists } from '$lib/stores';
import DeleteIdentity from './identity/DeleteIdentity.svelte';
import BackupIdentity from './identity/BackupIdentity.svelte';
import RestoreIdentity from './identity/RestoreIdentity.svelte';
@@ -8,6 +7,7 @@
import IdentityIcon from 'svelte-material-icons/Account.svelte';
import Eye from 'svelte-material-icons/Eye.svelte';
import Container from '../../lib/components/Container.svelte';
import { identityExists } from '$lib/stores';
</script>
<Container heading="Manage Settings">

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { identityKeyStore, keyStore } from '$lib/stores';
import { alertAll } from '$lib/utils';
import { alertQueue, identityKeyStore, keyStore } from '$lib/stores';
import { FileDropzone } from '@skeletonlabs/skeleton';
import { poseidon2 } from 'poseidon-lite/poseidon2';
import { poseidon1 } from 'poseidon-lite/poseidon1';
@@ -19,37 +18,37 @@
id = backup;
} catch (e) {
console.warn('Could not parse json as object');
alertAll('Invalid JSON detected');
alertQueue.enqueue('Invalid JSON detected');
return;
}
}
if (!id._nullifier) {
alertAll("_nullifier doesn't exist in backup");
alertQueue.enqueue("_nullifier doesn't exist in backup");
}
if (!id._trapdoor) {
alertAll("_trapdoor doesn't exist in backup");
alertQueue.enqueue("_trapdoor doesn't exist in backup");
}
if (!id._secret) {
alertAll("_secret doesn't exist in backup");
alertQueue.enqueue("_secret doesn't exist in backup");
}
const checkSecret = poseidon2([id._nullifier, id._trapdoor]);
if (checkSecret != id._secret) {
alertAll('Secret does not match secret from backup');
alertQueue.enqueue('Secret does not match secret from backup');
}
if (!id._commitment) {
alertAll("_commitment doesn't exist in backup");
alertQueue.enqueue("_commitment doesn't exist in backup");
}
const checkCommitment = poseidon1([id._secret]);
if (checkCommitment != id._commitment) {
alertAll('Commitment does not match commitment backup');
alertQueue.enqueue('Commitment does not match commitment backup');
}
console.log('Restoring identity from backup file...');
if ($keyStore !== undefined || $keyStore !== null) {
$identityKeyStore = id;
} else {
alertAll('Please set a password or unlock before restoring your identity');
alertQueue.enqueue('Please set a password or unlock before restoring your identity');
}
alertAll(
alertQueue.enqueue(
`Identity restored from backup file with identity commitment:
${$identityKeyStore._commitment}`
);
@@ -60,7 +59,7 @@
console.debug(`Backup/recovery file type detected as ${f?.type}`);
let unverifiedBackup: any;
if (!f) {
alertAll('No file selected');
alertQueue.enqueue('No file selected');
return;
}
if (f.type == 'application/json' || f.type == 'text/plain') {
@@ -69,7 +68,7 @@
restoreBackup(unverifiedBackup);
});
} else {
alertAll(
alertQueue.enqueue(
'Invalid file type, must be a JSON object with the _nullifier, _trapdoor, _secret, and _commitment as stringified bigints'
);
console.warn('Invalid file type');
@@ -80,7 +79,7 @@
const textBox = document.getElementById('jsonRecovery') as HTMLInputElement;
const json = textBox.value;
if (!json || json == '') {
alertAll('No JSON detected');
alertQueue.enqueue('No JSON detected');
return;
} else {
restoreBackup(json);

View File

@@ -45,5 +45,5 @@
</form>
</Container>
{:else}
<h2 class="h3">Password Set!</h2>
<Container heading="Password set" />
{/if}

View File

@@ -1,35 +1,67 @@
<script lang="ts">
import { configStore, identityKeyStore, identityStore, serverStore } from '$lib/stores';
import {
configStore,
identityExists,
identityKeyStore,
identityStore,
lockStateStore,
passwordSet,
serverStore
} from '$lib/stores';
import { IdentityStoreE } from '$lib/types';
import { alertQueue } from '$lib/stores';
function toggleBeta() {
$configStore.beta = !$configStore.beta;
}
function triggerAlert() {
alertQueue.enqueue('TEST');
}
</script>
<div id="status" class="flex flex-col gap-5">
<div>
<h2 class="h3">configStore</h2>
<div>Completed Signup: {JSON.stringify($configStore.signUpStatus.completedSignup)}</div>
<div>Identity Backedup: {JSON.stringify($configStore.signUpStatus.identityBackedUp)}</div>
<div>IdentityStore Type: {IdentityStoreE[$configStore.identityStore]}</div>
<div>Beta: {JSON.stringify($configStore.beta)}</div>
<div>Hashed Password: {JSON.stringify($configStore.hashedPwd)}</div>
</div>
<div>
<h2 class="h3">Identity Data</h2>
{#each Object.keys($identityStore) as key}
<div>Unprotected {key}: {JSON.stringify($identityStore[key])}</div>
{/each}
{#each Object.keys($identityKeyStore) as key}
<div>Protected {key}: {JSON.stringify($identityKeyStore[key])}</div>
{/each}
</div>
<div>
<h2 class="h3">Server Data</h2>
{#each Object.keys($serverStore) as key}
<div>{$serverStore[key].name}:</div>
<div class="ps-5">id: {$serverStore[key].id}</div>
<div class="ps-5">version: {$serverStore[key].version}</div>
<div class="ps-5">url: {key}</div>
{/each}
<div class="p-4">
<div id="status" class="flex flex-col gap-5">
<div>
<h2 class="h3">configStore</h2>
<div>Completed Signup: {JSON.stringify($configStore.signUpStatus.completedSignup)}</div>
<div>Identity Backedup: {JSON.stringify($configStore.signUpStatus.identityBackedUp)}</div>
<div>IdentityStore Type: {IdentityStoreE[$configStore.identityStore]}</div>
<div on:click={toggleBeta}>Beta: {JSON.stringify($configStore.beta)}</div>
<div>Hashed Password: {JSON.stringify($configStore.hashedPwd)}</div>
</div>
<div>
<h2 class="h3">Identity Data</h2>
{#if $identityExists == 'safe' || $identityExists == 'unsafe'}
{#each Object.keys($identityStore) as key}
<div>Unprotected {key}: {JSON.stringify($identityStore[key])}</div>
{/each}
{#each Object.keys($identityKeyStore) as key}
<div>Protected {key}: {JSON.stringify($identityKeyStore[key])}</div>
{/each}
{:else if $identityExists == 'encrypted'}
<div>Identity Exists but is encrypted</div>
{:else}
<div>No Identity Found</div>
{/if}
</div>
<div>
<h2 class="h3">Server Data</h2>
{#each Object.keys($serverStore) as key}
<div>{$serverStore[key].name}:</div>
<div class="ps-5">id: {$serverStore[key].id}</div>
<div class="ps-5">version: {$serverStore[key].version}</div>
<div class="ps-5">url: {key}</div>
{/each}
</div>
<div>
<h2 class="h3">Status States</h2>
<div>identityExists: {$identityExists}</div>
<div>Password Set: {$passwordSet}</div>
<div>Lock State: {$lockStateStore}</div>
</div>
</div>
<button class="btn variant-outline-primary m-4" on:click={triggerAlert}>Test Alert</button>
</div>
<style>

View File

@@ -1,21 +1,21 @@
<script lang="ts">
import { identityStore, configStore, consoleStore } from '$lib/stores';
import { createIdentity, doesIdentityExist } from '$lib/utils/';
import { configStore, identityExists } from '$lib/stores';
import { onMount } from 'svelte';
import ArrowRight from 'svelte-material-icons/ArrowRightBold.svelte';
import Text from 'svelte-material-icons/TextBox.svelte';
import Account from 'svelte-material-icons/AccountHardHat.svelte';
import { inviteCode } from '$lib/utils/inviteCode';
import { inviteCode } from '$lib/gateways/inviteCode';
import { addConsoleMessage } from '$lib/utils/console';
import Console from '../console/Console.svelte';
function checkForIdentity() {
const idStatus = doesIdentityExist();
const idStatus = $identityExists;
if (idStatus === 'safe') {
addConsoleMessage('✅ Identity Found');
} else if (idStatus === 'encrypted') {
addConsoleMessage('⚠️ Identity Found, but it is encrypted');
} else if (idStatus === 'unsafe') {
addConsoleMessage('⚠️ Identity Found, but it is unsafe');
} else if (idStatus === 'none') {
} else if (idStatus === null) {
addConsoleMessage('❌ No Identity Found');
}
}