Add support for keys hosted on keybase

This commit is contained in:
Yarmo Mackenbach 2020-07-05 15:04:12 +02:00
parent 140f645055
commit e3e55778f1
4 changed files with 107 additions and 31 deletions

View file

@ -205,7 +205,8 @@ async function displayProfile(opts) {
let userData = keyData.user.user.userId;
// Determine WKD or HKP link
if (opts.mode == "wkd") {
switch (opts.mode) {
case "wkd":
const [, localPart, domain] = /(.*)@(.*)/.exec(opts.input);
const localEncoded = await computeWKDLocalPart(localPart.toLowerCase());
const urlAdvanced = `https://openpgpkey.${domain}/.well-known/openpgpkey/${domain}/hu/${localEncoded}`;
@ -234,8 +235,15 @@ async function displayProfile(opts) {
if (!keyLink) {
keyLink = `https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x${keyData.fingerprint}`;
}
} else {
break;
case "hkp":
keyLink = `https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x${keyData.fingerprint}`;
break;
case "keybase":
keyLink = opts.keyLink;
break;
}
// Fill in various data
@ -261,10 +269,13 @@ async function displayProfile(opts) {
feedback += `<div class="profileDataItem__label">fingerprint</div>`;
feedback += `<div class="profileDataItem__value"><a href="${keyLink}">${keyData.fingerprint}</a></div>`;
feedback += `</div>`;
if (opts.mode == "hkp") {
feedback += `<div class="profileDataItem">`;
feedback += `<div class="profileDataItem__label">qrcode</div>`;
feedback += `<div class="profileDataItem__value"><a href="/util/qr/${keyData.fingerprint}">fingerprint</a></div>`;
feedback += `</div>`;
}
if (keyData.notations.length > 0) {
feedback += `<div class="profileDataItem profileDataItem--separator profileDataItem--noLabel">`;
@ -589,6 +600,27 @@ async function fetchKeys(opts) {
}
break;
case "keybase":
opts.keyLink = `https://keybase.io/${opts.username}/pgp_keys.asc?fingerprint=${opts.fingerprint}`;
opts.input = `${opts.username}/${opts.fingerprint}`;
try {
opts.plaintext = await fetch(opts.keyLink).then(function(response) {
if (response.status === 200) {
return response;
}
})
.then(response => response.blob())
.then(response => response.text());
} catch (e) {
throw("Error: No public keys could be fetched from the Keybase account.");
}
output.publicKey = (await openpgp.key.readArmored(opts.plaintext)).keys[0];
if (!output.publicKey) {
throw("Error: No public keys could be read from the Keybase account.");
}
break;
case "signature":
sig = (await openpgp.signature.readArmored(opts.signature));
if ('compressed' in sig.packets[0]) {
@ -738,10 +770,15 @@ if (elFormVerify) {
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) {
if (!opts.input && !opts.username) {
opts.mode = "signature";
}
@ -781,6 +818,11 @@ if (elFormEncrypt) {
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);
@ -850,6 +892,15 @@ if (elProfileUid) {
mode: elProfileMode.innerHTML
}
break;
case "keybase":
let match = profileUid.match(/(.*)\/(.*)/);
opts = {
username: match[1],
fingerprint: match[2],
mode: elProfileMode.innerHTML
}
break;
}
displayProfile(opts);
}

View file

@ -21,16 +21,19 @@ $router->map('GET', '/verify', function() {}, 'verify');
$router->map('GET', '/encrypt', function() {}, 'encrypt');
$router->map('GET', '/proofs', function() {}, 'proofs');
$router->map('GET', '/verify/hkp/[**:uid]', function() {}, 'verifyHKP');
$router->map('GET', '/encrypt/hkp/[**:uid]', function() {}, 'encryptHKP');
$router->map('GET', '/proofs/hkp/[**:uid]', function() {}, 'proofsHKP');
$router->map('GET', '/verify/wkd/[**:uid]', function() {}, 'verifyWKD');
$router->map('GET', '/encrypt/wkd/[**:uid]', function() {}, 'encryptWKD');
$router->map('GET', '/proofs/wkd/[**:uid]', function() {}, 'proofsWKD');
$router->map('GET', '/verify/keybase/[:uid]/[:fp]', function() {}, 'verifyKeybase');
$router->map('GET', '/verify/[**:uid]', function() {}, 'verifyAUTO');
$router->map('GET', '/encrypt/hkp/[**:uid]', function() {}, 'encryptHKP');
$router->map('GET', '/encrypt/wkd/[**:uid]', function() {}, 'encryptWKD');
$router->map('GET', '/encrypt/keybase/[:uid]/[:fp]', function() {}, 'encryptKeybase');
$router->map('GET', '/encrypt/[**:uid]', function() {}, 'encryptAUTO');
$router->map('GET', '/proofs/hkp/[**:uid]', function() {}, 'proofsHKP');
$router->map('GET', '/proofs/wkd/[**:uid]', function() {}, 'proofsWKD');
$router->map('GET', '/proofs/[**:uid]', function() {}, 'proofsAUTO');
$router->map('GET', '/hkp/[**:uid]', function() {}, 'profileHKP');
$router->map('GET', '/wkd/[**:uid]', function() {}, 'profileWKD');
$router->map('GET', '/keybase/[:uid]/[:fp]', function() {}, 'profileKeybase');
$router->map('GET', '/[**:uid]', function() {}, 'profile');
// Router matching
@ -59,6 +62,10 @@ if(is_array($match) && is_callable($match['target'])) {
echo $templates->render('verify', ['title' => 'Verify — ', 'mode' => 'wkd', 'wkd_input' => $match['params']['uid']]);
break;
case 'verifyKeybase':
echo $templates->render('verify', ['title' => 'Verify — ', 'mode' => 'keybase', 'keybase_username' => htmlspecialchars($match['params']['uid']), 'keybase_fingerprint' => htmlspecialchars($match['params']['fp'])]);
break;
case 'encrypt':
echo $templates->render('encrypt', ['title' => 'Encrypt — ', 'mode' => 'auto']);
break;
@ -75,6 +82,10 @@ if(is_array($match) && is_callable($match['target'])) {
echo $templates->render('encrypt', ['title' => 'Encrypt — ', 'mode' => 'wkd', 'wkd_input' => $match['params']['uid']]);
break;
case 'encryptKeybase':
echo $templates->render('encrypt', ['title' => 'Encrypt — ', 'mode' => 'keybase', 'keybase_username' => htmlspecialchars($match['params']['uid']), 'keybase_fingerprint' => htmlspecialchars($match['params']['fp'])]);
break;
case 'proofs':
echo $templates->render('proofs', ['title' => 'Proofs — ', 'mode' => 'auto']);
break;
@ -103,6 +114,10 @@ if(is_array($match) && is_callable($match['target'])) {
echo $templates->render('profile', ['mode' => 'wkd', 'uid' => htmlspecialchars($match['params']['uid'])]);
break;
case 'profileKeybase':
echo $templates->render('profile', ['mode' => 'keybase', 'uid' => htmlspecialchars($match['params']['uid']).'/'.htmlspecialchars($match['params']['fp'])]);
break;
case 'guides':
echo $templates->render('guides');
break;

View file

@ -10,6 +10,7 @@
<option value="wkd" <?php if ($mode=="wkd"): ?>selected<?php endif ?>>Web Key Directory</option>
<option value="hkp" <?php if ($mode=="hkp"): ?>selected<?php endif ?>>Keyserver</option>
<option value="plaintext" <?php if ($mode=="plaintext"): ?>selected<?php endif ?>>Plaintext</option>
<option value="keybase" <?php if ($mode=="keybase"): ?>selected<?php endif ?>>Keybase</option>
</select>
<div class="modesContainer">
<div class='modes modes--auto <?php if ($mode=="auto"): ?>modes--visible<?php endif ?>'>
@ -25,6 +26,10 @@
<div class='modes modes--plaintext <?php if ($mode=="plaintext"): ?>modes--visible<?php endif ?>'>
<textarea name="plaintext_input" id="plaintext_input"></textarea>
</div>
<div class='modes modes--keybase <?php if ($mode=="keybase"): ?>modes--visible<?php endif ?>'>
<input type="text" name="keybase_username" id="keybase_username" placeholder="username" value="<?=$this->escape($keybase_username)?>">
<input type="text" name="keybase_fingerprint" id="keybase_fingerprint" placeholder="fingerprint" value="<?=$this->escape($keybase_fingerprint)?>">
</div>
</div>
<h3>Message</h3>
<textarea name="message" id="message"></textarea>

View file

@ -10,6 +10,7 @@
<option value="wkd" <?php if ($mode=="wkd"): ?>selected<?php endif ?>>Web Key Directory</option>
<option value="hkp" <?php if ($mode=="hkp"): ?>selected<?php endif ?>>Keyserver</option>
<option value="plaintext" <?php if ($mode=="plaintext"): ?>selected<?php endif ?>>Plaintext</option>
<option value="keybase" <?php if ($mode=="keybase"): ?>selected<?php endif ?>>Keybase</option>
</select>
<div class="modesContainer">
<div class='modes modes--auto <?php if ($mode=="auto"): ?>modes--visible<?php endif ?>'>
@ -25,6 +26,10 @@
<div class='modes modes--plaintext <?php if ($mode=="plaintext"): ?>modes--visible<?php endif ?>'>
<textarea name="plaintext_input" id="plaintext_input"></textarea>
</div>
<div class='modes modes--keybase <?php if ($mode=="keybase"): ?>modes--visible<?php endif ?>'>
<input type="text" name="keybase_username" id="keybase_username" placeholder="username" value="<?=$this->escape($keybase_username)?>">
<input type="text" name="keybase_fingerprint" id="keybase_fingerprint" placeholder="fingerprint" value="<?=$this->escape($keybase_fingerprint)?>">
</div>
</div>
<h3>Signature</h3>
<textarea name="signature" id="signature"></textarea>