+ Format handler
* Creator view updated * Some small changes
This commit is contained in:
@@ -16,13 +16,13 @@ Attackers are using password dictionaries with more then one million passwords.
|
|||||||
## QR-Code schema
|
## QR-Code schema
|
||||||
An OffPass QR-Code must follow this data schema or else OffPass wouldn't be able to read it. **The following examples are data after decryption.**
|
An OffPass QR-Code must follow this data schema or else OffPass wouldn't be able to read it. **The following examples are data after decryption.**
|
||||||
```
|
```
|
||||||
name|password|email|website_url|(custom1)data1|(custom2)data2
|
name|username|password|email|website_url|(custom1)data1|(custom2)data2
|
||||||
```
|
```
|
||||||
Als Beispiel:
|
Als Beispiel:
|
||||||
```
|
```
|
||||||
Main Steam Account|super_secret_example123|info@example.de|https://store.steampowered.com/login/|(2fa_backup)R1337
|
Main Steam Account|mondei1|super_secret_example123|info@example.de|https://store.steampowered.com/login/|(2fa_backup)R1337
|
||||||
|
|
||||||
ProtonMail|mail_pw123|klier.nicolas@protonmail.com||
|
ProtonMail||mail_pw123|klier.nicolas@protonmail.com||
|
||||||
```
|
```
|
||||||
These characters are reserved and cannot be used for any fields: `|%§`
|
These characters are reserved and cannot be used for any fields: `|%§`
|
||||||
|
|
||||||
@@ -35,9 +35,9 @@ The compression key is stored like that: `§key`, the decryption key is stored l
|
|||||||
|
|
||||||
For example:
|
For example:
|
||||||
```
|
```
|
||||||
%session_key%§xa|passwords_not2134|email_too@example.com|§q|(§a)§gh|(uncompressed)value
|
%session_key%§xa|mondei1|passwords_not2134|email_too@example.com|§q|(§a)§gh|(uncompressed)value
|
||||||
|
|
||||||
-> Google|passwords_not2134|email_either@example.com|https://accounts.google.com|(2fa_backup)245131,...|(uncompressed)value
|
-> Google|mondei1|passwords_not2134|email_either@example.com|https://accounts.google.com|(2fa_backup)245131,...|(uncompressed)value
|
||||||
```
|
```
|
||||||
|
|
||||||
This can has two advantages:
|
This can has two advantages:
|
||||||
@@ -51,7 +51,7 @@ But one disadvantage:
|
|||||||
OffPass will first look if the scanned QR-Code is actually an OffPass QR-Code. This is done by checking the first three charcters:
|
OffPass will first look if the scanned QR-Code is actually an OffPass QR-Code. This is done by checking the first three charcters:
|
||||||
|
|
||||||
```
|
```
|
||||||
op:jA0ECQMC+t514sews8e70jsBw4SWsYYgPGzi5Ps0OGr8/tVGngopmHDQpSpMkNtkWZU573zNsFyk VVN3elnAY0D+EIIzTpKxq0F3fQ==
|
op1:jA0ECQMC+t514sews8e70jsBw4SWsYYgPGzi5Ps0OGr8/tVGngopmHDQpSpMkNtkWZU573zNsFykVVN3elnAY0D+EIIzTpKxq0F3fQ==
|
||||||
```
|
```
|
||||||
|
|
||||||
This `op:` tells the program that this is actully a OffPass QR-Code. If this is not present, OffPass will abort further steps and notify the user that this is not an OffPass QR-Code.
|
This `op1:` tells the program that this is actully a OffPass QR-Code and which version. If this is not present, OffPass will abort further steps and notify the user that this is not an OffPass QR-Code.
|
||||||
105
package-lock.json
generated
105
package-lock.json
generated
@@ -42,6 +42,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/jquery": {
|
||||||
|
"version": "3.3.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.31.tgz",
|
||||||
|
"integrity": "sha512-Lz4BAJihoFw5nRzKvg4nawXPzutkv7wmfQ5121avptaSIXlDNJCUuxZxX/G+9EVidZGuO0UBlk+YjKbwRKJigg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/sizzle": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "12.11.6",
|
"version": "12.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.11.6.tgz",
|
||||||
@@ -57,6 +66,12 @@
|
|||||||
"@types/bn.js": "*"
|
"@types/bn.js": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/sizzle": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"asn1.js": {
|
"asn1.js": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.2.0.tgz",
|
||||||
@@ -67,6 +82,32 @@
|
|||||||
"minimalistic-assert": "^1.0.0"
|
"minimalistic-assert": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-polyfill": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.26.0",
|
||||||
|
"core-js": "^2.5.0",
|
||||||
|
"regenerator-runtime": "^0.10.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"babel-runtime": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^2.4.0",
|
||||||
|
"regenerator-runtime": "^0.11.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.8",
|
"version": "4.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
|
||||||
@@ -131,6 +172,11 @@
|
|||||||
"typedarray": "^0.0.6"
|
"typedarray": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.6.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz",
|
||||||
|
"integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA=="
|
||||||
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
@@ -193,6 +239,11 @@
|
|||||||
"integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
|
"integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"es6-promise": {
|
||||||
|
"version": "4.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||||
|
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
|
||||||
|
},
|
||||||
"extract-zip": {
|
"extract-zip": {
|
||||||
"version": "1.6.7",
|
"version": "1.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
|
||||||
@@ -242,6 +293,16 @@
|
|||||||
"universalify": "^0.1.0"
|
"universalify": "^0.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fsm-as-promised": {
|
||||||
|
"version": "0.13.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsm-as-promised/-/fsm-as-promised-0.13.2.tgz",
|
||||||
|
"integrity": "sha1-X04RCGgotwoZItx7T4HAgX1ugjg=",
|
||||||
|
"requires": {
|
||||||
|
"es6-promise": "^4.0.2",
|
||||||
|
"lodash": "^4.16.2",
|
||||||
|
"stampit": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||||
@@ -291,6 +352,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
},
|
},
|
||||||
|
"instascan": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/instascan/-/instascan-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-3llJ9z9pj43/aN8Ke89pQqeZ7kQ=",
|
||||||
|
"requires": {
|
||||||
|
"babel-polyfill": "^6.9.1",
|
||||||
|
"fsm-as-promised": "^0.13.0",
|
||||||
|
"visibilityjs": "^1.2.3",
|
||||||
|
"webrtc-adapter": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
@@ -321,6 +393,11 @@
|
|||||||
"json-buffer": "3.0.0"
|
"json-buffer": "3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||||
|
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||||
|
},
|
||||||
"lowercase-keys": {
|
"lowercase-keys": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
|
||||||
@@ -446,6 +523,11 @@
|
|||||||
"util-deprecate": "~1.0.1"
|
"util-deprecate": "~1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
||||||
|
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
|
||||||
|
},
|
||||||
"responselike": {
|
"responselike": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
|
||||||
@@ -470,11 +552,21 @@
|
|||||||
"truncate-utf8-bytes": "^1.0.0"
|
"truncate-utf8-bytes": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sdp": {
|
||||||
|
"version": "1.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/sdp/-/sdp-1.5.4.tgz",
|
||||||
|
"integrity": "sha1-jgOPbdsUvXZa4fS1IW4SCUUR4NA="
|
||||||
|
},
|
||||||
"slide": {
|
"slide": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
|
||||||
"integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc="
|
"integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc="
|
||||||
},
|
},
|
||||||
|
"stampit": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/stampit/-/stampit-3.2.1.tgz",
|
||||||
|
"integrity": "sha1-lTpBpJRYoLKG/7HjydbOcDblids="
|
||||||
|
},
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
@@ -541,6 +633,19 @@
|
|||||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"visibilityjs": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/visibilityjs/-/visibilityjs-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-Y+aL3OUX88b+/VSmkmC2ApuLbf0grzbNLpCfIDSw3BzTU6PqcPsdgIOaw8b+eZoy+DdQqnVN3y/Evow9vQq9Ig=="
|
||||||
|
},
|
||||||
|
"webrtc-adapter": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WCiaY9BUxls2+w7zieovbQx/XZg=",
|
||||||
|
"requires": {
|
||||||
|
"sdp": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
|||||||
@@ -4,16 +4,17 @@
|
|||||||
"description": "OffPass, a special password manager. All your passwords are not stored in an encrypted container but offline.",
|
"description": "OffPass, a special password manager. All your passwords are not stored in an encrypted container but offline.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"instascan": "^1.0.0",
|
||||||
"openpgp": "^4.6.2"
|
"openpgp": "^4.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/jquery": "^3.3.31",
|
||||||
"@types/openpgp": "^4.4.7",
|
"@types/openpgp": "^4.4.7",
|
||||||
"electron": "^7.0.0"
|
"electron": "^7.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"start": "tsc && electron src/main.js",
|
"start": "tsc && electron src/main.js"
|
||||||
"clean": "del /S src\\js\\*.js && del src\\*.js"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -21,8 +21,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.options div:hover {
|
.options div:hover {
|
||||||
|
transform: scale(1.02);
|
||||||
|
box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.5);
|
||||||
background-color: rgba(255, 255, 255, .2);
|
background-color: rgba(255, 255, 255, .2);
|
||||||
border: 1px rgba(255, 255, 255, 0.8) solid;
|
border: 1px rgba(255, 255, 255, 0.9) solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.options div i {
|
.options div i {
|
||||||
|
|||||||
@@ -7,39 +7,40 @@
|
|||||||
}
|
}
|
||||||
#create_setup .options {
|
#create_setup .options {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
grid-template-columns: .2fr 1fr;
|
||||||
grid-template-rows: .25fr .25fr .25fr;
|
grid-template-rows: repeat(8, 1fr);
|
||||||
row-gap: 50px;
|
row-gap: 20px;
|
||||||
column-gap: 50px;
|
column-gap: 90px;
|
||||||
margin-left: 50px;
|
margin-left: 50px;
|
||||||
width: calc(100% - 100px);
|
width: calc(100% - 100px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#name, #username, #url, #email, #password, #algorithm, #advanced {
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
grid-column: 1;
|
||||||
|
line-height: 2;
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
|
|
||||||
#name {
|
#name {
|
||||||
grid-column: 1;
|
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
}
|
}
|
||||||
|
#username {
|
||||||
#url {
|
|
||||||
grid-column: 2 / 4;
|
|
||||||
grid-row: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#email {
|
|
||||||
grid-column: 1;
|
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
}
|
}
|
||||||
|
#email {
|
||||||
#password {
|
|
||||||
grid-column: 1 / 4;
|
|
||||||
grid-row: 3;
|
grid-row: 3;
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid white;
|
|
||||||
}
|
}
|
||||||
#password input {
|
#password {
|
||||||
border: none;
|
grid-row: 4;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
#password i {
|
#url {
|
||||||
|
grid-row: 5;
|
||||||
border-left: none;
|
}
|
||||||
|
#algorithm {
|
||||||
|
grid-row: 6;
|
||||||
}
|
}
|
||||||
@@ -9,12 +9,13 @@ body {
|
|||||||
/*background-color: #2A2C2B;*/
|
/*background-color: #2A2C2B;*/
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h3 {
|
h1, h3 {
|
||||||
font-family: 'Oxygen', sans-serif;
|
font-family: 'Oxygen', sans-serif;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
p, span {
|
p, span, label {
|
||||||
font-family: 'Source Sans Pro', sans-serif;
|
font-family: 'Source Sans Pro', sans-serif;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@@ -55,6 +56,28 @@ input:focus {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inputico {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid white !important;
|
||||||
|
}
|
||||||
|
.inputico:focus {
|
||||||
|
border: 1px rgb(200, 200, 200, 1) solid;
|
||||||
|
background-color: rgba(29, 29, 29, 0.3);
|
||||||
|
color: rgb(200, 200, 200, 1);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.inputico input {
|
||||||
|
border: none !important;
|
||||||
|
width: 97%;
|
||||||
|
}
|
||||||
|
.inputico i {
|
||||||
|
height: 15px;
|
||||||
|
position: absolute;
|
||||||
|
right:0;
|
||||||
|
top:5px;
|
||||||
|
}
|
||||||
|
|
||||||
#taskbar {
|
#taskbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -28,14 +28,14 @@
|
|||||||
z-index: -5;
|
z-index: -5;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
backdrop-filter: blur(20px);
|
backdrop-filter: blur(50px);
|
||||||
background: linear-gradient(0deg, rgba(0,0,0,.75) 80%, rgba(94,94,94,.75) 100%);
|
background-color: rgba(0,0,0,0.4);
|
||||||
box-shadow: 0px -10px 34px -10px rgba(0,0,0,0.75);
|
box-shadow: 0px -10px 34px -10px rgba(0,0,0,0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
#password {
|
#password {
|
||||||
font-family: 'Consolas';
|
font-family: 'Consolas';
|
||||||
font-weight: 200;
|
font-weight: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show {
|
.show {
|
||||||
|
|||||||
29
src/css/welcome.css
Normal file
29
src/css/welcome.css
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#welcome {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcome div {
|
||||||
|
text-align: center;
|
||||||
|
width: 100vw;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: 15%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcome img {
|
||||||
|
height: 166px;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcome a {
|
||||||
|
font-size: 16pt;
|
||||||
|
}
|
||||||
|
#welcome i {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
@@ -1,12 +1,24 @@
|
|||||||
<div id="create_setup" class="main" style="left: 150%;">
|
<div id="create_setup" class="main" style="left: 150%;">
|
||||||
<link rel="stylesheet" href="../css/create.css">
|
|
||||||
<h1>New QR-Code</h1>
|
<h1>New QR-Code</h1>
|
||||||
<div class="options">
|
<div class="options">
|
||||||
|
<label>Password Titel</label>
|
||||||
|
<label>Username</label>
|
||||||
|
<label>E-Mail</label>
|
||||||
|
<label>Password</label>
|
||||||
|
<label>Login URL</label>
|
||||||
|
<label>Algorithm</label>
|
||||||
<input placeholder="Name" id="name">
|
<input placeholder="Name" id="name">
|
||||||
<input placeholder="Login URL (example: https://example.com/login, https://login.example.com)" id="url">
|
<input placeholder="Username" id="username">
|
||||||
<input placeholder="E-Mail" id="email">
|
<input placeholder="E-Mail" id="email">
|
||||||
<input type="checkbox" id="compression">
|
<div id="password" class="inputico">
|
||||||
<select title="Hash Algorithm">
|
<input placeholder="Password">
|
||||||
|
<div>
|
||||||
|
<i class="fas fa-random"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<input placeholder="Login URL (example: https://example.com/login, https://login.example.com)" id="url">
|
||||||
|
<select title="Hash Algorithm" id="algorithm">
|
||||||
<option selected>Argon2i</option>
|
<option selected>Argon2i</option>
|
||||||
<!--<option>Argon2d</option>-->
|
<!--<option>Argon2d</option>-->
|
||||||
<!--<option>Argon2id</option>-->
|
<!--<option>Argon2id</option>-->
|
||||||
@@ -14,10 +26,5 @@
|
|||||||
<option>Bcrypt</option>
|
<option>Bcrypt</option>
|
||||||
<option>SHA-512</option>
|
<option>SHA-512</option>
|
||||||
</select>
|
</select>
|
||||||
<div id="password">
|
|
||||||
<input placeholder="Password">
|
|
||||||
<i class="fas fa-random"></i>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<script src="../js/create.js"></script>
|
|
||||||
</div>
|
</div>
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
<title>OffPass</title>
|
<title>OffPass</title>
|
||||||
|
|
||||||
<script type="text/javascript" src="../assets/instascan.min.js"></script>
|
<script type="text/javascript" src="../assets/instascan.min.js"></script>
|
||||||
|
<script type="text/javascript" src="../js/scanner.js"></script>
|
||||||
|
<script type="text/javascript" src="../ts/format.js"></script>
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro&display=swap" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Oxygen:700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Oxygen:700&display=swap" rel="stylesheet">
|
||||||
@@ -24,8 +26,6 @@
|
|||||||
<h1>Welcome to OffPass</h1>
|
<h1>Welcome to OffPass</h1>
|
||||||
<p>Please enter your master password</p>
|
<p>Please enter your master password</p>
|
||||||
<input id="master" placeholder="Master password..." type="password" autofocus><br>
|
<input id="master" placeholder="Master password..." type="password" autofocus><br>
|
||||||
|
|
||||||
<a href="#">Or create a new QR-Code</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="error">
|
<div id="error">
|
||||||
@@ -38,11 +38,26 @@
|
|||||||
window.$ = window.jQuery = require('../assets/jquery-3.4.1.min.js');
|
window.$ = window.jQuery = require('../assets/jquery-3.4.1.min.js');
|
||||||
|
|
||||||
const { Loader } = require('../js/loader.js');
|
const { Loader } = require('../js/loader.js');
|
||||||
|
const { Format } = require('../js/format.js');
|
||||||
const { remote } = require('electron');
|
const { remote } = require('electron');
|
||||||
const pgp = require('openpgp');
|
const pgp = require('openpgp');
|
||||||
let master_password = "";
|
let master_password = "";
|
||||||
|
|
||||||
const loader = new Loader(document.getElementById('content'));
|
const loader = new Loader(document.getElementById('content'));
|
||||||
|
const format = new Format("%AzTka312K1%Google|mondei1|passwords_not2134|email_either@example.com|https://accounts.google.com|(2fa_backup)245131,...|(uncompressed)value");
|
||||||
|
format.parse();
|
||||||
|
|
||||||
|
console.log(format.build({
|
||||||
|
decryptionKey: "az35LKuJ$w",
|
||||||
|
title: "Steam",
|
||||||
|
password: "lol_my-password1412%$",
|
||||||
|
custom: [
|
||||||
|
{
|
||||||
|
key: "2fa_secret",
|
||||||
|
value: "R24829"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
|
||||||
// Slide
|
// Slide
|
||||||
$('#master').keypress(async (e) => {
|
$('#master').keypress(async (e) => {
|
||||||
@@ -87,54 +102,6 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function startWatching() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
Instascan.Camera.getCameras().then(function (cameras) {
|
|
||||||
if (cameras.length > 0) {
|
|
||||||
scanner.start(cameras[0]);
|
|
||||||
navigator.mediaDevices.getUserMedia({video: true}).then((stream) => {
|
|
||||||
preview.srcObject = stream;
|
|
||||||
resolve(true);
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
resolve(false);
|
|
||||||
}
|
|
||||||
}).catch(function (e) {
|
|
||||||
showError("No camera found.");
|
|
||||||
$('#wait').animate({
|
|
||||||
left: '150%'
|
|
||||||
}, 200);
|
|
||||||
$('#master_prompt').animate({
|
|
||||||
left: '0'
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
navigator.mediaDevices.getUserMedia({video: true});
|
|
||||||
const preview = document.getElementById('preview');
|
|
||||||
|
|
||||||
let scanner = new Instascan.Scanner({ video: preview, mirror: false });
|
|
||||||
|
|
||||||
scanner.addListener('scan', async (content) => {
|
|
||||||
content = "-----BEGIN PGP MESSAGE-----\n\n" + content + "\n-----END PGP MESSAGE-----";
|
|
||||||
console.log(content)
|
|
||||||
pgp.decrypt({
|
|
||||||
message: await pgp.message.readArmored(content),
|
|
||||||
passwords: [ master_password ],
|
|
||||||
format: 'string'
|
|
||||||
}).then((plaintext) => {
|
|
||||||
const scanned = $('#scanned');
|
|
||||||
scanned.css('top', '85%');
|
|
||||||
scanned.css('z-index', '2');
|
|
||||||
scanned.addClass("fadeInUp");
|
|
||||||
$('#password').text(plaintext.data)
|
|
||||||
console.log(plaintext.data);
|
|
||||||
}).catch((err) => {
|
|
||||||
if (err) showError("Wrong master password");
|
|
||||||
})
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function slide_left(from, to, duration = 300) {
|
function slide_left(from, to, duration = 300) {
|
||||||
$('#' + from).animate({
|
$('#' + from).animate({
|
||||||
left: '-150%'
|
left: '-150%'
|
||||||
|
|||||||
8
src/html/welcome.html
Normal file
8
src/html/welcome.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<div id="welcome" class="animated fadeInUp">
|
||||||
|
<div>
|
||||||
|
<img src="../assets/icon.png">
|
||||||
|
<h1>Welcome</h1>
|
||||||
|
<p>to OffPass, the next level of password storage.</p>
|
||||||
|
<a href="#">Let's start<i class="fas fa-arrow-right"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
0
src/js/create.ts
Normal file
0
src/js/create.ts
Normal file
81
src/js/format.js
Normal file
81
src/js/format.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
"use strict";
|
||||||
|
/**
|
||||||
|
* This script is responsible to handle the data stored on QR-Codes.
|
||||||
|
* For detailed information, please take a look at DEVELOPMENT.md in
|
||||||
|
* the projects root directory.
|
||||||
|
*/
|
||||||
|
exports.__esModule = true;
|
||||||
|
var Format = /** @class */ (function () {
|
||||||
|
/**
|
||||||
|
* Format handler
|
||||||
|
* @param text The unparsed text provided on a QR-Code
|
||||||
|
*/
|
||||||
|
function Format(text) {
|
||||||
|
// Example: %session_key%§xa|mondei1|passwords_not2134|email_too@example.com|§q|(§a)§gh|(uncompressed)value
|
||||||
|
// Google|mondei1|passwords_not2134|email_either@example.com|https://accounts.google.com|(2fa_backup)245131,...|(uncompressed)value
|
||||||
|
this.text = null;
|
||||||
|
this.format = {
|
||||||
|
title: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
email: "",
|
||||||
|
loginURL: null
|
||||||
|
};
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
Format.prototype.isCompatible = function () {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
Format.prototype.decrypt = function () {
|
||||||
|
if (this.isCompatible()) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Format.prototype.parse = function () {
|
||||||
|
var parts = this.text.split('|');
|
||||||
|
// Parse static values
|
||||||
|
this.format.title = parts[0];
|
||||||
|
// Check if a decryption key exists at the start
|
||||||
|
if (this.format.title.startsWith('%')) {
|
||||||
|
this.format.decryptionKey = "";
|
||||||
|
// Extract
|
||||||
|
for (var i = 1; i < this.format.title.length; i++) {
|
||||||
|
var char = this.format.title.charAt(i);
|
||||||
|
if (char != '%') {
|
||||||
|
this.format.decryptionKey += char;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove decryption key from first value
|
||||||
|
this.format.title = this.format.title.substr(this.format.decryptionKey.length + 2, this.format.title.length); // + 2 because of the two '%'
|
||||||
|
}
|
||||||
|
this.format.username = parts[1];
|
||||||
|
this.format.password = parts[2];
|
||||||
|
this.format.email = parts[3];
|
||||||
|
this.format.loginURL = new URL(parts[4]);
|
||||||
|
console.log(this.format);
|
||||||
|
};
|
||||||
|
Format.prototype.build = function (data) {
|
||||||
|
if (data == undefined)
|
||||||
|
data = this.format;
|
||||||
|
var raw = "";
|
||||||
|
if (data.decryptionKey != undefined) {
|
||||||
|
raw += "%" + data.decryptionKey + "%";
|
||||||
|
}
|
||||||
|
raw += data.title + "|";
|
||||||
|
raw += data.username + "|";
|
||||||
|
raw += data.password + "|";
|
||||||
|
raw += data.email + "|";
|
||||||
|
raw += data.loginURL + "|";
|
||||||
|
if (data.custom != undefined) {
|
||||||
|
data.custom.forEach(function (element) {
|
||||||
|
raw += "(" + element.key + ")" + element.value + "|";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
raw = raw.substr(0, raw.length - 1); // Remove the last |
|
||||||
|
return raw;
|
||||||
|
};
|
||||||
|
return Format;
|
||||||
|
}());
|
||||||
|
exports.Format = Format;
|
||||||
105
src/js/format.ts
Normal file
105
src/js/format.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* This script is responsible to handle the data stored on QR-Codes.
|
||||||
|
* For detailed information, please take a look at DEVELOPMENT.md in
|
||||||
|
* the projects root directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ICustom {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFormat {
|
||||||
|
decryptionKey?: string;
|
||||||
|
title: string;
|
||||||
|
username?: string;
|
||||||
|
password: string;
|
||||||
|
email?: string;
|
||||||
|
loginURL?: URL;
|
||||||
|
custom?: Array<ICustom>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Format {
|
||||||
|
// Example: %session_key%§xa|mondei1|passwords_not2134|email_too@example.com|§q|(§a)§gh|(uncompressed)value
|
||||||
|
// Google|mondei1|passwords_not2134|email_either@example.com|https://accounts.google.com|(2fa_backup)245131,...|(uncompressed)value
|
||||||
|
text: string = null;
|
||||||
|
format: IFormat = {
|
||||||
|
title: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
email: "",
|
||||||
|
loginURL: null
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format handler
|
||||||
|
* @param text The unparsed text provided on a QR-Code
|
||||||
|
*/
|
||||||
|
constructor(text?: string) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
isCompatible(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypt() {
|
||||||
|
if(this.isCompatible()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse() {
|
||||||
|
const parts = this.text.split('|');
|
||||||
|
|
||||||
|
// Parse static values
|
||||||
|
this.format.title = parts[0];
|
||||||
|
|
||||||
|
// Check if a decryption key exists at the start
|
||||||
|
if(this.format.title.startsWith('%')) {
|
||||||
|
this.format.decryptionKey = "";
|
||||||
|
// Extract
|
||||||
|
for(let i = 1; i < this.format.title.length; i++) {
|
||||||
|
const char = this.format.title.charAt(i);
|
||||||
|
|
||||||
|
if (char != '%') {
|
||||||
|
this.format.decryptionKey += char;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove decryption key from first value
|
||||||
|
this.format.title = this.format.title.substr(this.format.decryptionKey.length + 2, this.format.title.length) // + 2 because of the two '%'
|
||||||
|
}
|
||||||
|
|
||||||
|
this.format.username = parts[1];
|
||||||
|
this.format.password = parts[2];
|
||||||
|
this.format.email = parts[3];
|
||||||
|
this.format.loginURL = new URL(parts[4]);
|
||||||
|
|
||||||
|
console.log(this.format);
|
||||||
|
}
|
||||||
|
|
||||||
|
build(data?: IFormat): string {
|
||||||
|
if (data == undefined) data = this.format;
|
||||||
|
|
||||||
|
let raw = "";
|
||||||
|
if(data.decryptionKey != undefined) {
|
||||||
|
raw += "%" + data.decryptionKey + "%";
|
||||||
|
}
|
||||||
|
raw += data.title + "|";
|
||||||
|
raw += data.username + "|";
|
||||||
|
raw += data.password + "|";
|
||||||
|
raw += data.email + "|";
|
||||||
|
raw += data.loginURL + "|";
|
||||||
|
|
||||||
|
if (data.custom != undefined) {
|
||||||
|
data.custom.forEach(element => {
|
||||||
|
raw += `(${element.key})${element.value}|`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
raw = raw.substr(0, raw.length - 1); // Remove the last |
|
||||||
|
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,11 +61,6 @@ var Loader = /** @class */ (function () {
|
|||||||
css.setAttribute("href", "../css/" + module_name + ".css");
|
css.setAttribute("href", "../css/" + module_name + ".css");
|
||||||
_this.head.appendChild(css);
|
_this.head.appendChild(css);
|
||||||
var html_path = path_1.resolve("src/html/", module_name + ".html");
|
var html_path = path_1.resolve("src/html/", module_name + ".html");
|
||||||
// Load js file
|
|
||||||
var js = document.createElement("script");
|
|
||||||
js.setAttribute("type", "text/javascript");
|
|
||||||
js.setAttribute("src", "../js/" + module_name + ".js");
|
|
||||||
_this.head.appendChild(js);
|
|
||||||
// Load html file
|
// Load html file
|
||||||
fs_1.readFile(html_path, 'utf8', function (err, data) {
|
fs_1.readFile(html_path, 'utf8', function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -74,6 +69,11 @@ var Loader = /** @class */ (function () {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_this.content.innerHTML += data;
|
_this.content.innerHTML += data;
|
||||||
|
// Load js file
|
||||||
|
var js = document.createElement("script");
|
||||||
|
js.setAttribute("type", "text/javascript");
|
||||||
|
js.setAttribute("src", "../js/" + module_name + ".js");
|
||||||
|
_this.head.appendChild(js);
|
||||||
// Push to loaded modules
|
// Push to loaded modules
|
||||||
var mod = { name: module_name, js: js, css: css, html: document.getElementById(module_name) };
|
var mod = { name: module_name, js: js, css: css, html: document.getElementById(module_name) };
|
||||||
_this.modules.push(mod);
|
_this.modules.push(mod);
|
||||||
@@ -85,22 +85,15 @@ var Loader = /** @class */ (function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
Loader.prototype.unload = function (module_name) {
|
Loader.prototype.unload = function (module_name) {
|
||||||
return __awaiter(this, void 0, void 0, function () {
|
|
||||||
return __generator(this, function (_a) {
|
|
||||||
this.modules.forEach(function (element) {
|
this.modules.forEach(function (element) {
|
||||||
if (element.name == module_name) {
|
if (element.name == module_name) {
|
||||||
console.log(element);
|
console.log(element);
|
||||||
/*
|
|
||||||
element.js.parentElement.removeChild(element.js);
|
|
||||||
element.css.parentElement.removeChild(element.css);
|
|
||||||
element.html.parentElement.removeChild(element.html);*/
|
|
||||||
element.html.remove();
|
element.html.remove();
|
||||||
element.css.remove();
|
element.css.remove();
|
||||||
element.js.remove();
|
element.js.remove();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
console.error("Tried to remove module which is not loaded:", module_name);
|
||||||
return [2 /*return*/];
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
return Loader;
|
return Loader;
|
||||||
|
|||||||
@@ -32,12 +32,6 @@ export class Loader {
|
|||||||
|
|
||||||
const html_path: string = res("src/html/", module_name + ".html");
|
const html_path: string = res("src/html/", module_name + ".html");
|
||||||
|
|
||||||
// Load js file
|
|
||||||
const js = document.createElement("script");
|
|
||||||
js.setAttribute("type", "text/javascript");
|
|
||||||
js.setAttribute("src", "../js/" + module_name + ".js");
|
|
||||||
this.head.appendChild(js);
|
|
||||||
|
|
||||||
// Load html file
|
// Load html file
|
||||||
readFile(html_path, 'utf8', (err, data) => {
|
readFile(html_path, 'utf8', (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -47,6 +41,12 @@ export class Loader {
|
|||||||
else {
|
else {
|
||||||
this.content.innerHTML += data;
|
this.content.innerHTML += data;
|
||||||
|
|
||||||
|
// Load js file
|
||||||
|
const js = document.createElement("script");
|
||||||
|
js.setAttribute("type", "text/javascript");
|
||||||
|
js.setAttribute("src", "../js/" + module_name + ".js");
|
||||||
|
this.head.appendChild(js);
|
||||||
|
|
||||||
// Push to loaded modules
|
// Push to loaded modules
|
||||||
const mod: IModules = { name: module_name, js: js, css: css, html: <HTMLDivElement>document.getElementById(module_name) };
|
const mod: IModules = { name: module_name, js: js, css: css, html: <HTMLDivElement>document.getElementById(module_name) };
|
||||||
this.modules.push(mod);
|
this.modules.push(mod);
|
||||||
@@ -57,18 +57,17 @@ export class Loader {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async unload(module_name) {
|
unload(module_name) {
|
||||||
this.modules.forEach(element => {
|
this.modules.forEach(element => {
|
||||||
if (element.name == module_name) {
|
if (element.name == module_name) {
|
||||||
console.log(element);
|
console.log(element);
|
||||||
/*
|
|
||||||
element.js.parentElement.removeChild(element.js);
|
|
||||||
element.css.parentElement.removeChild(element.css);
|
|
||||||
element.html.parentElement.removeChild(element.html);*/
|
|
||||||
element.html.remove();
|
element.html.remove();
|
||||||
element.css.remove();
|
element.css.remove();
|
||||||
element.js.remove();
|
element.js.remove();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
console.error("Tried to remove module which is not loaded:", module_name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
async function startWatching() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Instascan.Camera.getCameras().then(function (cameras) {
|
||||||
|
if (cameras.length > 0) {
|
||||||
|
scanner.start(cameras[0]);
|
||||||
|
navigator.mediaDevices.getUserMedia({video: true}).then((stream) => {
|
||||||
|
preview.srcObject = stream;
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
}).catch(function (e) {
|
||||||
|
showError("No camera found.");
|
||||||
|
$('#wait').animate({
|
||||||
|
left: '150%'
|
||||||
|
}, 200);
|
||||||
|
$('#master_prompt').animate({
|
||||||
|
left: '0'
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
navigator.mediaDevices.getUserMedia({video: true});
|
||||||
|
const preview = document.getElementById('preview');
|
||||||
|
|
||||||
|
let scanner = new Instascan.Scanner({ video: preview, mirror: false });
|
||||||
|
|
||||||
|
scanner.addListener('scan', async (content) => {
|
||||||
|
content = "-----BEGIN PGP MESSAGE-----\n\n" + content + "\n-----END PGP MESSAGE-----";
|
||||||
|
console.log(content)
|
||||||
|
pgp.decrypt({
|
||||||
|
message: await pgp.message.readArmored(content),
|
||||||
|
passwords: [ master_password ],
|
||||||
|
format: 'string'
|
||||||
|
}).then((plaintext) => {
|
||||||
|
const scanned = $('#scanned');
|
||||||
|
scanned.css('top', '85%');
|
||||||
|
scanned.css('z-index', '2');
|
||||||
|
scanned.addClass("fadeInUp");
|
||||||
|
$('#password').text(plaintext.data)
|
||||||
|
console.log(plaintext.data);
|
||||||
|
}).catch((err) => {
|
||||||
|
if (err) showError("Wrong master password");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
8
src/js/welcome.js
Normal file
8
src/js/welcome.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const welcome_container = document.getElementById('welcome');
|
||||||
|
|
||||||
|
$('#welcome a').click((e) => {
|
||||||
|
$('#master_prompt').css('left', '150%');
|
||||||
|
$('#master_prompt').css('display', 'block');
|
||||||
|
slide_left('welcome', 'master_prompt');
|
||||||
|
$('#master_prompt').css('left', '0');
|
||||||
|
});
|
||||||
@@ -1,2 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"module": "commonjs"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user