diff --git a/index.js b/index.js index fab1499..bb8bbfe 100644 --- a/index.js +++ b/index.js @@ -55,9 +55,6 @@ app.use(stringReplace({ app.use('/', require('./routes/main')); app.use('/static', require('./routes/static')); app.use('/server', require('./routes/server')); -app.use('/encrypt', require('./routes/encrypt')); -app.use('/verify', require('./routes/verify')); -app.use('/proofs', require('./routes/proofs')); app.use('/util', require('./routes/util')); app.use('/', require('./routes/profile')); diff --git a/routes/encrypt.js b/routes/encrypt.js deleted file mode 100644 index 873f32f..0000000 --- a/routes/encrypt.js +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (C) 2021 Yarmo Mackenbach - -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU Affero General Public License as published by the Free -Software Foundation, either version 3 of the License, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more -details. - -You should have received a copy of the GNU Affero General Public License along -with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - -If your software can interact with users remotely through a computer network, -you should also make sure that it provides a way for users to get its source. -For example, if your program is a web application, its interface could display -a "Source" link that leads users to an archive of the code. There are many -ways you could offer source, and different solutions will be better for different -programs; see section 13 for the specific requirements. - -You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. For -more information on this, and how to apply and follow the GNU AGPL, see . -*/ -const router = require('express').Router(); - -router.get('/', function(req, res) { - res.render('encrypt', { mode: "auto" }) -}); - -router.get('/wkd', function(req, res) { - res.render('encrypt', { mode: "wkd" }) -}); -router.get('/wkd/:input', function(req, res) { - res.render('encrypt', { mode: "wkd", input: req.params.input }) -}); - -router.get('/hkp', function(req, res) { - res.render('encrypt', { mode: "hkp" }) -}); -router.get('/hkp/:input', function(req, res) { - res.render('encrypt', { mode: "hkp", input: req.params.input }) -}); - -router.get('/plaintext', function(req, res) { - res.render('encrypt', { mode: "plaintext" }) -}); - -router.get('/keybase', function(req, res) { - res.render('encrypt', { mode: "keybase" }) -}); -router.get('/keybase/:username', function(req, res) { - res.render('encrypt', { mode: "keybase", username: req.params.username }) -}); -router.get('/keybase/:username/:fingerprint', function(req, res) { - res.render('encrypt', { mode: "keybase", username: req.params.username, fingerprint: req.params.fingerprint }) -}); - -router.get('/:input', function(req, res) { - res.render('encrypt', { mode: "auto", input: req.params.input }) -}); - -module.exports = router; diff --git a/routes/proofs.js b/routes/proofs.js deleted file mode 100644 index 2130617..0000000 --- a/routes/proofs.js +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (C) 2021 Yarmo Mackenbach - -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU Affero General Public License as published by the Free -Software Foundation, either version 3 of the License, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more -details. - -You should have received a copy of the GNU Affero General Public License along -with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - -If your software can interact with users remotely through a computer network, -you should also make sure that it provides a way for users to get its source. -For example, if your program is a web application, its interface could display -a "Source" link that leads users to an archive of the code. There are many -ways you could offer source, and different solutions will be better for different -programs; see section 13 for the specific requirements. - -You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. For -more information on this, and how to apply and follow the GNU AGPL, see . -*/ -const router = require('express').Router(); - -router.get('/', function(req, res) { - res.render('proofs', { mode: "auto" }) -}); - -router.get('/wkd', function(req, res) { - res.render('proofs', { mode: "wkd" }) -}); -router.get('/wkd/:input', function(req, res) { - res.render('proofs', { mode: "wkd", input: req.params.input }) -}); - -router.get('/hkp', function(req, res) { - res.render('proofs', { mode: "hkp" }) -}); -router.get('/hkp/:input', function(req, res) { - res.render('proofs', { mode: "hkp", input: req.params.input }) -}); - -router.get('/plaintext', function(req, res) { - res.render('proofs', { mode: "plaintext" }) -}); - -router.get('/keybase', function(req, res) { - res.render('proofs', { mode: "keybase" }) -}); -router.get('/keybase/:username', function(req, res) { - res.render('proofs', { mode: "keybase", username: req.params.username }) -}); -router.get('/keybase/:username/:fingerprint', function(req, res) { - res.render('proofs', { mode: "keybase", username: req.params.username, fingerprint: req.params.fingerprint }) -}); - -router.get('/:input', function(req, res) { - res.render('proofs', { mode: "auto", input: req.params.input }) -}); - -module.exports = router; diff --git a/routes/verify.js b/routes/verify.js deleted file mode 100644 index 25361e3..0000000 --- a/routes/verify.js +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (C) 2021 Yarmo Mackenbach - -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU Affero General Public License as published by the Free -Software Foundation, either version 3 of the License, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more -details. - -You should have received a copy of the GNU Affero General Public License along -with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - -If your software can interact with users remotely through a computer network, -you should also make sure that it provides a way for users to get its source. -For example, if your program is a web application, its interface could display -a "Source" link that leads users to an archive of the code. There are many -ways you could offer source, and different solutions will be better for different -programs; see section 13 for the specific requirements. - -You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. For -more information on this, and how to apply and follow the GNU AGPL, see . -*/ -const router = require('express').Router(); - -router.get('/', function(req, res) { - res.render('verify', { mode: "auto" }) -}); - -router.get('/wkd', function(req, res) { - res.render('verify', { mode: "wkd" }) -}); -router.get('/wkd/:input', function(req, res) { - res.render('verify', { mode: "wkd", input: req.params.input }) -}); - -router.get('/hkp', function(req, res) { - res.render('verify', { mode: "hkp" }) -}); -router.get('/hkp/:input', function(req, res) { - res.render('verify', { mode: "hkp", input: req.params.input }) -}); - -router.get('/plaintext', function(req, res) { - res.render('verify', { mode: "plaintext" }) -}); - -router.get('/keybase', function(req, res) { - res.render('verify', { mode: "keybase" }) -}); -router.get('/keybase/:username', function(req, res) { - res.render('verify', { mode: "keybase", username: req.params.username }) -}); -router.get('/keybase/:username/:fingerprint', function(req, res) { - res.render('verify', { mode: "keybase", username: req.params.username, fingerprint: req.params.fingerprint }) -}); - -router.get('/:input', function(req, res) { - res.render('verify', { mode: "auto", input: req.params.input }) -}); - -module.exports = router; diff --git a/static/scripts.js b/static/scripts.js index ad99df0..aab38a9 100644 --- a/static/scripts.js +++ b/static/scripts.js @@ -215,8 +215,8 @@ async function displayProfile(opts) { ${data.fingerprint}

- Encrypt message - Verify signature + +
`; @@ -262,7 +262,6 @@ async function displayProfile(opts) { // Generate output for each claim claims.forEach((claim, i) => { - console.log(claim); const claimData = claim.serviceproviderData; if (!claimData.serviceprovider.name) { return; @@ -592,6 +591,59 @@ async function displayProfile(opts) { d.close(); }); }); + + // Register form listeners + const elFormEncrypt = document.body.querySelector("#dialog--encryptMessage form"); + elFormEncrypt.onsubmit = async function (evt) { + evt.preventDefault(); + + try { + // Encrypt the message + encrypted = await openpgp.encrypt({ + message: openpgp.message.fromText(elFormEncrypt.querySelector('.input').value), + publicKeys: keyData + }); + elFormEncrypt.querySelector('.output').value = encrypted.data; + } catch (e) { + console.error(e); + elFormEncrypt.querySelector('.output').value = `Could not encrypt message!\n==========================\n${e.message ? e.message : e}`; + } + }; + const elFormVerify = document.body.querySelector("#dialog--verifySignature form"); + elFormVerify.onsubmit = async function (evt) { + evt.preventDefault(); + + try { + // Try two different methods of signature reading + let signature = null, verified = null, readError = null; + try { + signature = await openpgp.message.readArmored(elFormVerify.querySelector('.input').value); + } catch(e) { + readError = e; + } + try { + signature = await openpgp.cleartext.readArmored(elFormVerify.querySelector('.input').value); + } catch(e) { + readError = e; + } + if (signature == null) { throw(readError) }; + + // Verify the signature + verified = await openpgp.verify({ + message: signature, + publicKeys: keyData + }); + + if (verified.signatures[0].valid) { + elFormVerify.querySelector('.output').value = `The message was signed by the profile's key.`; + } else { + elFormVerify.querySelector('.output').value = `The message was NOT signed by the profile's key.`; + } + } catch (e) { + console.error(e); + elFormVerify.querySelector('.output').value = `Could not verify signature!\n===========================\n${e.message ? e.message : e}`; + } + }; } async function fetchKeys(opts) { @@ -747,10 +799,7 @@ async function fetchWithTimeout(url, timeout = 3000) { } // General purpose -let elFormVerify = document.body.querySelector("#form-verify"), - elFormEncrypt = document.body.querySelector("#form-encrypt"), - elFormProofs = document.body.querySelector("#form-proofs"), - elFormSignatureProfile = document.body.querySelector("#form-generate-signature-profile"), +let elFormSignatureProfile = document.body.querySelector("#formGenerateSignatureProfile"), elProfileUid = document.body.querySelector("#profileUid"), elProfileMode = document.body.querySelector("#profileMode"), elProfileServer = document.body.querySelector("#profileServer"), @@ -771,133 +820,6 @@ if (elModeSelect) { elModeSelect.dispatchEvent(new Event("change")); } -if (elFormVerify) { - elFormVerify.onsubmit = function (evt) { - evt.preventDefault(); - - let opts = { - signature: null, - mode: null, - input: null, - server: null, - }; - - opts.signature = document.body.querySelector("#signature").value; - opts.mode = document.body.querySelector("#modeSelect").value; - - switch (opts.mode) { - default: - case "auto": - opts.input = document.body.querySelector("#auto_input").value; - break; - - case "wkd": - opts.input = document.body.querySelector("#wkd_input").value; - break; - - case "hkp": - opts.input = document.body.querySelector("#hkp_input").value; - opts.server = document.body.querySelector("#hkp_server").value; - break; - - case "plaintext": - opts.input = document.body.querySelector("#plaintext_input").value; - break; - - case "keybase": - opts.username = document.body.querySelector("#keybase_username").value; - opts.fingerprint = document.body.querySelector("#keybase_fingerprint").value; - break; - } - - // If no input was detect - if (!opts.input && !opts.username) { - opts.mode = "signature"; - } - - verifySignature(opts); - }; -} - -if (elFormEncrypt) { - elFormEncrypt.onsubmit = function (evt) { - evt.preventDefault(); - - let opts = { - message: null, - mode: null, - input: null, - server: null, - }; - - opts.message = document.body.querySelector("#message").value; - opts.mode = document.body.querySelector("#modeSelect").value; - - switch (opts.mode) { - default: - case "auto": - opts.input = document.body.querySelector("#auto_input").value; - break; - - case "wkd": - opts.input = document.body.querySelector("#wkd_input").value; - break; - - case "hkp": - opts.input = document.body.querySelector("#hkp_input").value; - opts.server = document.body.querySelector("#hkp_server").value; - break; - - case "plaintext": - opts.input = document.body.querySelector("#plaintext_input").value; - break; - - case "keybase": - opts.username = document.body.querySelector("#keybase_username").value; - opts.fingerprint = document.body.querySelector("#keybase_fingerprint").value; - break; - } - - encryptMessage(opts); - }; -} - -if (elFormProofs) { - elFormProofs.onsubmit = function (evt) { - evt.preventDefault(); - - let opts = { - mode: null, - input: null, - server: null, - }; - - opts.mode = document.body.querySelector("#modeSelect").value; - - switch (opts.mode) { - default: - case "auto": - opts.input = document.body.querySelector("#auto_input").value; - break; - - case "wkd": - opts.input = document.body.querySelector("#wkd_input").value; - break; - - case "hkp": - opts.input = document.body.querySelector("#hkp_input").value; - opts.server = document.body.querySelector("#hkp_server").value; - break; - - case "plaintext": - opts.input = document.body.querySelector("#plaintext_input").value; - break; - } - - verifyProofs(opts); - }; -} - if (elProfileUid) { let opts, profileUid = elProfileUid.innerHTML; switch (elProfileMode.innerHTML) { diff --git a/static/styles.css b/static/styles.css index 924dfc2..addf920 100644 --- a/static/styles.css +++ b/static/styles.css @@ -337,8 +337,7 @@ section.profile p, .demo p { border-radius: 24px; } -.buttons { - /* margin: 2.4rem 0; */ +/* .buttons { margin: 1.2rem 0; } .buttons a { @@ -353,7 +352,7 @@ section.profile p, .demo p { } .buttons a:hover { background-color: #ccc; -} +} */ .modes { display: none; } @@ -495,8 +494,9 @@ form .modesContainer input { } form input[type="submit"] { display: block; - width: 100%; + /* width: 100%; */ padding: 0.4rem 0.8rem; + margin: 8px 8px 12px 0; text-decoration: none; text-transform: uppercase; background-color: #fff; @@ -504,10 +504,24 @@ form input[type="submit"] { border-radius: 4px; cursor: pointer; } -form input[type="submit"]:hover { +button { + padding: 0.4rem 0.8rem; + margin-right: 8px; + text-decoration: none; + text-transform: uppercase; + background-color: #fff; + border: solid 1px var(--blue-700); + border-radius: 4px; + cursor: pointer; +} +form input[type="submit"]:hover, button:hover { background-color: var(--blue-700); color: #fff; } +.card--form form { + background-color: var(--purple-100) !important; + padding: 1rem; +} dialog { width: 100% !important; diff --git a/views/encrypt.pug b/views/encrypt.pug deleted file mode 100644 index 61d3d5e..0000000 --- a/views/encrypt.pug +++ /dev/null @@ -1,22 +0,0 @@ -extends templates/base.pug - -block js - script(type='application/javascript' src='/static/openpgp.min.js' charset='utf-8') - script(type='application/javascript' src='/static/doip.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.js' charset='utf-8') - -block content - section.narrow - noscript - p Keyoxide requires JavaScript to function. - - h1 Encrypt - form#form-encrypt(method='post') - h3 Recipient - label(for='modeSelect') Mode: - include partials/key_selector - - h3 Message - textarea#message(name='message') - p#result - input.bigBtn(type='submit' name='submit' value='ENCRYPT MESSAGE') diff --git a/views/profile.pug b/views/profile.pug index d5b1560..e183ad6 100644 --- a/views/profile.pug +++ b/views/profile.pug @@ -17,11 +17,29 @@ block content span#profileServer(style='display: none;') #{server} span#profileMode(style='display: none;') #{mode} + dialog#dialog--encryptMessage + div + form(method='post') + textarea.input(name='message' placeholder='Message') + input(type='submit' name='submit' value='ENCRYPT MESSAGE') + textarea.output(name='message' placeholder='Waiting for input' readonly) + form(method="dialog") + input(type="submit" value="Close") + + dialog#dialog--verifySignature + div + form(method='post') + textarea.input(name='signature' placeholder='Signature') + input(type='submit' name='submit' value='VERIFY SIGNATURE') + textarea.output(name='message' placeholder='Waiting for input' readonly) + form(method="dialog") + input(type="submit" value="Close") + #profileDialogs if (mode == 'sig') - #profileSigInput.card - form#form-generate-signature-profile(method='post') + #profileSigInput.card.card--form + form#formGenerateSignatureProfile(method='post') label(for="plaintext_input") Please enter the raw profile signature below and press "Generate profile". textarea#plaintext_input(name='plaintext_input') input(type='submit', name='submit', value='Generate profile') diff --git a/views/verify.pug b/views/verify.pug deleted file mode 100644 index d50f8a9..0000000 --- a/views/verify.pug +++ /dev/null @@ -1,25 +0,0 @@ -extends templates/base.pug - -block js - script(type='application/javascript' src='/static/openpgp.min.js' charset='utf-8') - script(type='application/javascript' src='/static/doip.js' charset='utf-8') - script(type='application/javascript' src='/static/scripts.js' charset='utf-8') - -block content - section.narrow - noscript - p Keyoxide requires JavaScript to function. - - h1 Verify - form#form-verify(method='post') - h3 Signer - label(for='modeSelect') Mode: - include partials/key_selector - - h3 Signature - textarea#signature(name='signature') - - h3 Result - p#result - p#resultContent - input.bigBtn(type='submit' name='submit' value='VERIFY SIGNATURE')