From d5f02f48fdfe3f156bd3d28fecb6135ce7a77527 Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sat, 9 Jan 2021 15:24:44 +0100 Subject: [PATCH 1/7] Update deps --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d2e9b06..1531bbf 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "dependencies": { "bent": "^7.3.12", - "doipjs": "^0.9.0", + "doipjs": "^0.9.1", "dotenv": "^8.2.0", "express": "^4.17.1", "express-validator": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index b077b4b..f477b64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -703,10 +703,10 @@ doctypes@^1.1.0: resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= -doipjs@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.0.tgz#628af8316ea40904d8695ef372e9f0d0211c25d2" - integrity sha512-Tw9Ep9vyWNFx4cBmNNtkE/gLakBY32+A09WLosBpAdtvm573h0N/Jww/IL5cr0gu5947pbqxUCnwkQySRB3N1A== +doipjs@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.1.tgz#1a2e33d377134cec7a5b601ec496a94b519052c4" + integrity sha512-BSgyuIszu13F6h8g1p6JoBaHNMOPFKcwmKzsFvtIKln5mqtioqEQ8ILnJ8TbeGHQolY7pppCkWqi/0cHfxRtyw== dependencies: bent "^7.3.12" browserify "^17.0.0" From 91999ca3b7a0fa1ce5776d93df906942c0b344aa Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sat, 9 Jan 2021 16:27:53 +0100 Subject: [PATCH 2/7] Update deps --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1531bbf..a320da7 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "dependencies": { "bent": "^7.3.12", - "doipjs": "^0.9.1", + "doipjs": "^0.9.2", "dotenv": "^8.2.0", "express": "^4.17.1", "express-validator": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index f477b64..bba6914 100644 --- a/yarn.lock +++ b/yarn.lock @@ -703,10 +703,10 @@ doctypes@^1.1.0: resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= -doipjs@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.1.tgz#1a2e33d377134cec7a5b601ec496a94b519052c4" - integrity sha512-BSgyuIszu13F6h8g1p6JoBaHNMOPFKcwmKzsFvtIKln5mqtioqEQ8ILnJ8TbeGHQolY7pppCkWqi/0cHfxRtyw== +doipjs@^0.9.2: + version "0.9.2" + resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.2.tgz#da5f44b7eb5dbd899d7217de361245b6e90f6fa4" + integrity sha512-xistbQk4iViiLyufmG6m5KXli1b8iDrhsQk9cJoJiQI1Zm7OPVEpoJ0daqUMuPJQysfO2m1NrhKYgcACTvTU0A== dependencies: bent "^7.3.12" browserify "^17.0.0" From a0dd7cd363306f3d43826e3b5393e55a33fd68b9 Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sat, 9 Jan 2021 16:28:42 +0100 Subject: [PATCH 3/7] Use data provided by doip sig verify --- static/scripts.js | 43 ++++++++----------------------------------- 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/static/scripts.js b/static/scripts.js index 28f4e66..b6472f8 100644 --- a/static/scripts.js +++ b/static/scripts.js @@ -241,37 +241,8 @@ async function displayProfile(opts) { if (opts.mode == 'sig') { try { sigVerification = await doip.signatures.verify(opts.input); - - if (sigVerification.errors.length > 0) { - throw(sigVerification.errors.join(', ')) - } - - keyData = sigVerification.publicKey - fingerprint = sigVerification.fingerprint - - const sigData = await openpgp.cleartext.readArmored(opts.input); - const sigText = sigData.getText(); - let sigKeys = []; - sigText.split('\n').forEach((line, i) => { - const match = line.match(/^(.*)\=(.*)$/i); - if (!match || !match[1]) { - return; - } - switch (match[1].toLowerCase()) { - case 'key': - sigKeys.push(match[2]); - break; - - default: - break; - } - }); - - if (sigKeys.length === 0) { - throw('No key URI found'); - } - - sigKeyUri = sigKeys[0]; + keyData = sigVerification.publicKey.data; + fingerprint = sigVerification.publicKey.fingerprint; } catch (e) { feedback += `

There was a problem reading the signature.

`; feedback += `${e}`; @@ -307,11 +278,13 @@ async function displayProfile(opts) { // Determine WKD or HKP link let keyUriMode = opts.mode; + let keyUriServer = null; let keyUriId = opts.input; if (opts.mode === 'sig') { - const keyUriMatch = sigKeyUri.match(/(.*):(.*)/); + const keyUriMatch = sigVerification.publicKey.uri.match(/([^:]*)(?:\:(.*))?:(.*)/); keyUriMode = keyUriMatch[1]; - keyUriId = keyUriMatch[2]; + keyUriServer = keyUriMatch[2]; + keyUriId = keyUriMatch[3]; } switch (keyUriMode) { @@ -342,12 +315,12 @@ async function displayProfile(opts) { } } if (!keyLink) { - keyLink = `https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x${fingerprint}`; + keyLink = `https://${keyUriServer ? keyUriServer : 'keys.openpgp.org'}/pks/lookup?op=get&options=mr&search=0x${fingerprint}`; } break; case "hkp": - keyLink = `https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x${fingerprint}`; + keyLink = `https://${keyUriServer ? keyUriServer : 'keys.openpgp.org'}/pks/lookup?op=get&options=mr&search=0x${fingerprint}`; break; case "keybase": From 03234520d407d48252be79c709c2cf0f5739bdc1 Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sun, 10 Jan 2021 12:36:34 +0100 Subject: [PATCH 4/7] Update deps --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a320da7..fbdb814 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "dependencies": { "bent": "^7.3.12", - "doipjs": "^0.9.2", + "doipjs": "^0.9.3", "dotenv": "^8.2.0", "express": "^4.17.1", "express-validator": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index bba6914..7472ab4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -703,10 +703,10 @@ doctypes@^1.1.0: resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= -doipjs@^0.9.2: - version "0.9.2" - resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.2.tgz#da5f44b7eb5dbd899d7217de361245b6e90f6fa4" - integrity sha512-xistbQk4iViiLyufmG6m5KXli1b8iDrhsQk9cJoJiQI1Zm7OPVEpoJ0daqUMuPJQysfO2m1NrhKYgcACTvTU0A== +doipjs@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.3.tgz#a091fe300ebf23db3079084d9ec13f14a34440e5" + integrity sha512-77nOVl09pCcThRap8D1o7nu1cJgQr8iYOHNxQEn/pMK3j9JJ0vs7N6nBghyDXXSV1BhuP+1y0cizO3iwj7AfxA== dependencies: bent "^7.3.12" browserify "^17.0.0" From 20a1e1cd75356eeb86360f1a97b2bec3e7a741d7 Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sun, 10 Jan 2021 12:51:18 +0100 Subject: [PATCH 5/7] Remove obsolete twitter requirement --- README.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/README.md b/README.md index 2552158..99e790b 100644 --- a/README.md +++ b/README.md @@ -20,23 +20,6 @@ The Docker container allows you to easily self-host the [Keyoxide](https://keyox Keyoxide will now be available by visiting http://localhost:3000. -To add support for Twitter account verification, make a [developer account](https://developer.twitter.com/en), [obtain a Bearer token](https://developer.twitter.com/en/docs/basics/authentication/oauth-2-0) and run: - -`docker run -d -p 3000:3000 -e "TWITTER_API_AUTH=XXXXXXXXXXXXXXXXXX" keyoxide/keyoxide:stable` - -### Docker-compose - -To run Keyoxide using docker-compose, add the following snippet to your `docker-compose.yml`: - -```yml -keyoxide: - image: keyoxide/keyoxide:stable - ports: - - 3000:3000 - environment: - - TWITTER_API_AUTH=XXXXXXXXXXXXXXXXXX -``` - ## Contributing Anyone can contribute if they'd like! No need to be a programmer or technically-oriented for that matter. From 7c6e67297ddbeaa9395dd0d33d575844b4cc0a65 Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sun, 10 Jan 2021 13:54:08 +0100 Subject: [PATCH 6/7] Add signature profile guide --- content/guides/signature-profiles.md | 93 ++++++++++++++++++++++++++++ views/guides.pug | 2 + 2 files changed, 95 insertions(+) create mode 100644 content/guides/signature-profiles.md diff --git a/content/guides/signature-profiles.md b/content/guides/signature-profiles.md new file mode 100644 index 0000000..c663f36 --- /dev/null +++ b/content/guides/signature-profiles.md @@ -0,0 +1,93 @@ +# Creating signature profiles + +Let's create a signature profile. This is a profile that can be verified by Keyoxide but the data for which lives in a clear-signed text document rather than as notations in the key itself. + +[[toc]] + +## Writing the plaintext document + +Using terminal tools like vim, emacs, nano or graphical tools like notepad, create a new document. The content should eventually look like this: + +``` +Hey there! Here's a signature profile with doip-related proofs. + +openpgp4fpr:3637202523e7c1309ab79e99ef2dc5827b445f4b +proof=dns:doip.rocks +``` + +You can add as much "regular" text as you'd like. The point of these signature profiles is that they are both human-friendly and machine-readable. In this case, the first line is meant for humans. + +The second thing to add is the fingerprint of the key that will sign this message. This is done by typing **openpgp4fpr:** followed by the fingerprint. + +Note: this line is also intended for humans and corresponds to the text that is usually used to verify the claims. Though it can be handy for humans when reading the signature profile, the line is not strictly necessary. + +Finally, you can add proofs by adding a new line beginning with **proof=** followed by the claim that is given by the [guides](/guides). So, for example, **proof=dns:doip.rocks** verifies a domain name and **proof@metacode.biz=https://twitter.com/USERNAME/status/1234567891234567891** verifies a Twitter account. + +You can add as many claims as you wish as long as each is on their own line. + +## Signing the document + +You will now sign this document, making it untemperable and possible to prove beyond doubt that you, as holder of the private key, and only you could have signed the document. + +Assuming you have an OpenPGP key with signing capabilities, execute the following command in the terminal: + +``` +gpg -u EMAIL_ADDRESS --sender EMAIL_ADDRESS --clear-sign FILENAME +``` + +Replace EMAIL_ADDRESS and FILENAME with the correct values. As an example: + +``` +gpg -u test@doip.rocks --sender test@doip.rocks --clear-sign sigpro.txt +``` + +This will generate a file named **sigpro.txt.asc** with the following content: + +``` +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +Hey there! Here's a signature profile with doip-related proofs. + +openpgp4fpr:3637202523e7c1309ab79e99ef2dc5827b445f4b +proof=dns:doip.rocks +-----BEGIN PGP SIGNATURE----- + +iQHfBAEBCgBJFiEENjcgJSPnwTCat56Z7y3FgntEX0sFAl/5rvsaGGh0dHBzOi8v +a2V5cy5vcGVucGdwLm9yZy8QHHRlc3RAZG9pcC5yb2NrcwAKCRDvLcWCe0RfSz45 +C/9msqmNZlTXa99Oec82Za24LPCKuUDLwNEdnO4s8uzDmjFcNSGeM55RxfVJOOPX +zT4b91GgHy/q8+4THZbsF+3Lu6CCUTe33cDQVpdcPA8Gpm7ipjLM2xSdhspqOzhu +PvWJzk8H7CIk+iuv9IYatr7caR8x1G/NN+r0YpkKyI27oVQu4oOBvGPl30R/6734 +JuFCY6oRe9spXzCZ7qbPVzqzuflPZHvgGMIj29x8lmtPgOAYhMbdhZi5RvfP9jDB +huUdRPE9ATk09hztOHaMNTTbxOLGtEQXog3ef5iYLUT3/KjG8a79Cqq51OS+6zVC +lUbUGQISCBJ68qfLbxXMGcL6kPiOm9XQbGZI+QcZI7vOSafPr/+FKbFonIgjTFNY +WJSTyVzhAcH0OPl/vL0DMjNIInIUelYUmaBM+MEXIgLcwtSoICLJDRpCybVjzoZi +evqL4ZA7Th3KZYcF6buPvBdl8tg8nsK2KWHDPCpYRW/RYN3D0QZkx9v/Cxks400U +MIQ= +=WGb1 +-----END PGP SIGNATURE----- +``` + +This document is a fully functional signature profile! Test it out [here](/sig). + +### The process of fetching keys + +Keyoxide verifies the validity of the signature before verifying the individual claims. To this end, it needs to find the key that signed this profile. + +Keyoxide always first checks whether it can fetch the public key using [Web Key Directory](/guides/web-key-directory) with the email address provided as **sender**. + +If this fails, Keyoxide tries to fetch the key using a keyserver. By default, it will use [keys.openpgp.org](https://keys.openpgp.org) (which tends to be the most reliable of keyservers). To set your preferred keyserver, execute the following command instead: + +``` +gpg -u EMAIL_ADDRESS --sender EMAIL_ADDRESS --sig-keyserver-url https://KEYSERVER_DOMAIN/ --clear-sign FILENAME +``` + +## Why put claims in a signed document/signature profile? + +Storing claims inside the key as notations is a powerful method. Wherever the public key goes, so go the identity claims. This allows one to use the existing vast network of key sharing tools to also share these identity claims. + +There are drawbacks to this: you lose granularity. You cannot pick and choose the claims you want to send to certain people or use for certain purposes. There is also the possibility that notations in keys could be scraped as the keys are pubicly available. + +Putting (certain) claims in a signature profile solves both drawbacks. You can choose which claims to be associated with each other and you can choose which persons can see this by only sending it to them. You can even encrypt the signature profile! Since the signature profile is not publicly available (unless you make it so), there is no possibility to scrape the contents of it. + +Note that there is one catch: the person you send it to could publish it. Only send claims you wish to keep secret to people you trust! diff --git a/views/guides.pug b/views/guides.pug index 2f50f85..9f7c590 100644 --- a/views/guides.pug +++ b/views/guides.pug @@ -21,6 +21,8 @@ block content a(href='/guides/openpgp-proofs') How OpenPGP identity proofs work br a(href='/guides/web-key-directory') Uploading keys using web key directory + br + a(href='/guides/signature-profiles') Using signature profiles .guides__section h3 Adding proofs From a2afafa0889ceb476047f69b19dd641b36ce487e Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sun, 10 Jan 2021 15:11:44 +0100 Subject: [PATCH 7/7] Add noscript block --- static/styles.css | 12 ++++++++++++ views/encrypt.pug | 3 +++ views/profile.pug | 2 ++ views/proofs.pug | 3 +++ views/verify.pug | 3 +++ 5 files changed, 23 insertions(+) diff --git a/static/styles.css b/static/styles.css index 815bca4..1138810 100644 --- a/static/styles.css +++ b/static/styles.css @@ -361,6 +361,18 @@ a.proofQR:hover { margin: 32px auto; } +noscript { + display: block; + margin-bottom: 2rem; + padding: 8px; + background-color: #f0e68c; + text-align: center; +} +noscript p { + margin: 0; + font-size: 1rem; +} + @media (max-width: 680px) { #profileHeader { flex-direction: column; diff --git a/views/encrypt.pug b/views/encrypt.pug index cd1b4f6..1ee7aa4 100644 --- a/views/encrypt.pug +++ b/views/encrypt.pug @@ -2,6 +2,9 @@ extends template.base.pug block content .content + noscript + p Keyoxide requires JavaScript to function. + h1 Encrypt form#form-encrypt(method='post') h3 Recipient diff --git a/views/profile.pug b/views/profile.pug index a8546d2..83c02f4 100644 --- a/views/profile.pug +++ b/views/profile.pug @@ -8,6 +8,8 @@ head main.container.container--profile .content + noscript + p Keyoxide requires JavaScript to function. span#profileUid(style='display: none;') #{uid} span#profileServer(style='display: none;') #{server} span#profileMode(style='display: none;') #{mode} diff --git a/views/proofs.pug b/views/proofs.pug index 8e22f37..d61034c 100644 --- a/views/proofs.pug +++ b/views/proofs.pug @@ -2,6 +2,9 @@ extends template.base.pug block content .content + noscript + p Keyoxide requires JavaScript to function. + h1 Proofs form#form-proofs(method='post') h3 Public key diff --git a/views/verify.pug b/views/verify.pug index 7db1a6f..cdf898a 100644 --- a/views/verify.pug +++ b/views/verify.pug @@ -2,6 +2,9 @@ extends template.base.pug block content .content + noscript + p Keyoxide requires JavaScript to function. + h1 Verify form#form-verify(method='post') h3 Signer