Merge branch 'dev' into js-and-css-impromement

This commit is contained in:
KiddyTheKid 2021-01-10 15:54:59 +01:00
commit b921cdbac6
11 changed files with 131 additions and 57 deletions

View file

@ -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. 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 ## Contributing
Anyone can contribute if they'd like! No need to be a programmer or technically-oriented for that matter. Anyone can contribute if they'd like! No need to be a programmer or technically-oriented for that matter.

View file

@ -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!

View file

@ -5,7 +5,7 @@
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"bent": "^7.3.12", "bent": "^7.3.12",
"doipjs": "^0.9.0", "doipjs": "^0.9.3",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"express": "^4.17.1", "express": "^4.17.1",
"express-validator": "^6.8.0", "express-validator": "^6.8.0",

View file

@ -241,37 +241,8 @@ async function displayProfile(opts) {
if (opts.mode == 'sig') { if (opts.mode == 'sig') {
try { try {
sigVerification = await doip.signatures.verify(opts.input); sigVerification = await doip.signatures.verify(opts.input);
keyData = sigVerification.publicKey.data;
if (sigVerification.errors.length > 0) { fingerprint = sigVerification.publicKey.fingerprint;
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];
} catch (e) { } catch (e) {
feedback += `<p>There was a problem reading the signature.</p>`; feedback += `<p>There was a problem reading the signature.</p>`;
feedback += `<code>${e}</code>`; feedback += `<code>${e}</code>`;
@ -307,11 +278,13 @@ async function displayProfile(opts) {
// Determine WKD or HKP link // Determine WKD or HKP link
let keyUriMode = opts.mode; let keyUriMode = opts.mode;
let keyUriServer = null;
let keyUriId = opts.input; let keyUriId = opts.input;
if (opts.mode === 'sig') { if (opts.mode === 'sig') {
const keyUriMatch = sigKeyUri.match(/(.*):(.*)/); const keyUriMatch = sigVerification.publicKey.uri.match(/([^:]*)(?:\:(.*))?:(.*)/);
keyUriMode = keyUriMatch[1]; keyUriMode = keyUriMatch[1];
keyUriId = keyUriMatch[2]; keyUriServer = keyUriMatch[2];
keyUriId = keyUriMatch[3];
} }
switch (keyUriMode) { switch (keyUriMode) {
@ -342,12 +315,12 @@ async function displayProfile(opts) {
} }
} }
if (!keyLink) { 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; break;
case "hkp": 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; break;
case "keybase": case "keybase":

View file

@ -383,6 +383,18 @@ a.proofQR:hover {
margin: 32px auto; 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) { @media (max-width: 680px) {
#profileHeader { #profileHeader {
flex-direction: column; flex-direction: column;

View file

@ -2,6 +2,9 @@ extends template.base.pug
block content block content
.content .content
noscript
p Keyoxide requires JavaScript to function.
h1 Encrypt h1 Encrypt
form#form-encrypt(method='post') form#form-encrypt(method='post')
h3 Recipient h3 Recipient

View file

@ -21,6 +21,8 @@ block content
a(href='/guides/openpgp-proofs') How OpenPGP identity proofs work a(href='/guides/openpgp-proofs') How OpenPGP identity proofs work
br br
a(href='/guides/web-key-directory') Uploading keys using web key directory a(href='/guides/web-key-directory') Uploading keys using web key directory
br
a(href='/guides/signature-profiles') Using signature profiles
.guides__section .guides__section
h3 Adding proofs h3 Adding proofs

View file

@ -8,6 +8,8 @@ head
main.container.container--profile main.container.container--profile
.content .content
noscript
p Keyoxide requires JavaScript to function.
span#profileUid(style='display: none;') #{uid} span#profileUid(style='display: none;') #{uid}
span#profileServer(style='display: none;') #{server} span#profileServer(style='display: none;') #{server}
span#profileMode(style='display: none;') #{mode} span#profileMode(style='display: none;') #{mode}

View file

@ -2,6 +2,9 @@ extends template.base.pug
block content block content
.content .content
noscript
p Keyoxide requires JavaScript to function.
h1 Proofs h1 Proofs
form#form-proofs(method='post') form#form-proofs(method='post')
h3 Public key h3 Public key

View file

@ -2,6 +2,9 @@ extends template.base.pug
block content block content
.content .content
noscript
p Keyoxide requires JavaScript to function.
h1 Verify h1 Verify
form#form-verify(method='post') form#form-verify(method='post')
h3 Signer h3 Signer

View file

@ -703,10 +703,10 @@ doctypes@^1.1.0:
resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9"
integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=
doipjs@^0.9.0: doipjs@^0.9.3:
version "0.9.0" version "0.9.3"
resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.0.tgz#628af8316ea40904d8695ef372e9f0d0211c25d2" resolved "https://registry.yarnpkg.com/doipjs/-/doipjs-0.9.3.tgz#a091fe300ebf23db3079084d9ec13f14a34440e5"
integrity sha512-Tw9Ep9vyWNFx4cBmNNtkE/gLakBY32+A09WLosBpAdtvm573h0N/Jww/IL5cr0gu5947pbqxUCnwkQySRB3N1A== integrity sha512-77nOVl09pCcThRap8D1o7nu1cJgQr8iYOHNxQEn/pMK3j9JJ0vs7N6nBghyDXXSV1BhuP+1y0cizO3iwj7AfxA==
dependencies: dependencies:
bent "^7.3.12" bent "^7.3.12"
browserify "^17.0.0" browserify "^17.0.0"