forked from Mirrors/keyoxide-web
Fix support for signature profiles
This commit is contained in:
parent
f0a748542c
commit
01ba4a3a54
7 changed files with 118 additions and 50 deletions
|
@ -5,6 +5,7 @@
|
|||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"bent": "^7.3.12",
|
||||
"body-parser": "^1.19.0",
|
||||
"dialog-polyfill": "^0.5.6",
|
||||
"doipjs": "^0.12.4",
|
||||
"dotenv": "^8.2.0",
|
||||
|
|
|
@ -28,41 +28,35 @@ 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
const router = require('express').Router()
|
||||
const bodyParser = require('body-parser').urlencoded({ extended: false })
|
||||
const kx = require('../server')
|
||||
|
||||
router.get('/sig', (req, res) => {
|
||||
res.render('profile', { mode: 'sig' })
|
||||
res.render('profile', { isSignature: true, signature: null })
|
||||
})
|
||||
|
||||
router.post('/sig', bodyParser, async (req, res) => {
|
||||
const data = await kx.generateSignatureProfile(req.body.signature)
|
||||
res.render('profile', { data: data, isSignature: true, signature: req.body.signature })
|
||||
})
|
||||
|
||||
router.get('/wkd/:id', async (req, res) => {
|
||||
const data = await kx.generateWKDProfile(req.params.id)
|
||||
if (data.errors.length > 0) {
|
||||
return res.render('profile-failed', { data: data })
|
||||
}
|
||||
res.render('profile', { data: data })
|
||||
})
|
||||
|
||||
router.get('/hkp/:id', async (req, res) => {
|
||||
const data = await kx.generateHKPProfile(req.params.id)
|
||||
if (data.errors.length > 0) {
|
||||
return res.render('profile-failed', { data: data })
|
||||
}
|
||||
res.render('profile', { data: data })
|
||||
})
|
||||
|
||||
router.get('/hkp/:server/:id', async (req, res) => {
|
||||
const data = await kx.generateHKPProfile(req.params.id, req.params.server)
|
||||
if (data.errors.length > 0) {
|
||||
return res.render('profile-failed', { data: data })
|
||||
}
|
||||
res.render('profile', { data: data })
|
||||
})
|
||||
|
||||
router.get('/keybase/:username/:fingerprint', async (req, res) => {
|
||||
const data = await kx.generateKeybaseProfile(req.params.username, req.params.fingerprint)
|
||||
if (data.errors.length > 0) {
|
||||
return res.render('profile-failed', { data: data })
|
||||
}
|
||||
res.render('profile', { data: data })
|
||||
})
|
||||
|
||||
|
@ -73,9 +67,6 @@ router.get('/:id', async (req, res) => {
|
|||
} else {
|
||||
data = await kx.generateHKPProfile(req.params.id)
|
||||
}
|
||||
if (data.errors.length > 0) {
|
||||
return res.render('profile-failed', { data: data })
|
||||
}
|
||||
res.render('profile', { data: data })
|
||||
})
|
||||
|
||||
|
|
|
@ -81,6 +81,30 @@ const generateHKPProfile = async (id, keyserverDomain) => {
|
|||
})
|
||||
}
|
||||
|
||||
const generateSignatureProfile = async (signature) => {
|
||||
return keys.fetchSignature(signature)
|
||||
.then(async key => {
|
||||
let keyData = key.keyData
|
||||
delete key.keyData
|
||||
keyData = processKeyData(keyData)
|
||||
|
||||
return {
|
||||
key: key,
|
||||
keyData: keyData,
|
||||
extra: await computeExtraData(key, keyData),
|
||||
errors: []
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
return {
|
||||
key: null,
|
||||
keyData: null,
|
||||
extra: null,
|
||||
errors: [err.message]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const generateKeybaseProfile = async (username, fingerprint) => {
|
||||
return keys.fetchKeybase(id, keyserverDomain)
|
||||
.then(async key => {
|
||||
|
@ -146,3 +170,4 @@ const computeExtraData = async (key, keyData) => {
|
|||
exports.generateWKDProfile = generateWKDProfile
|
||||
exports.generateHKPProfile = generateHKPProfile
|
||||
exports.generateKeybaseProfile = generateKeybaseProfile
|
||||
exports.generateSignatureProfile = generateSignatureProfile
|
||||
|
|
|
@ -65,22 +65,22 @@ const fetchWKD = (id) => {
|
|||
}
|
||||
})
|
||||
} catch (error) {
|
||||
reject(new Error("No public keys could be fetched using WKD"))
|
||||
reject(new Error(`No public keys could be fetched using WKD`))
|
||||
}
|
||||
}
|
||||
|
||||
if (!plaintext) {
|
||||
reject(new Error("No public keys could be fetched using WKD"))
|
||||
reject(new Error(`No public keys could be fetched using WKD`))
|
||||
}
|
||||
|
||||
try {
|
||||
output.publicKey = (await openpgp.key.read(plaintext)).keys[0]
|
||||
} catch(error) {
|
||||
reject(new Error("No public keys could be read from the data fetched using WKD"))
|
||||
reject(new Error(`No public keys could be read from the data fetched using WKD`))
|
||||
}
|
||||
|
||||
if (!output.publicKey) {
|
||||
reject(new Error("No public keys could be read from the data fetched using WKD"))
|
||||
reject(new Error(`No public keys could be read from the data fetched using WKD`))
|
||||
}
|
||||
|
||||
resolve(output)
|
||||
|
@ -107,11 +107,56 @@ const fetchHKP = (id, keyserverDomain) => {
|
|||
output.publicKey = await doip.keys.fetchHKP(id, keyserverDomain)
|
||||
output.fetchURL = `https://${keyserverDomain}/pks/lookup?op=get&options=mr&search=${query}`
|
||||
} catch(error) {
|
||||
reject(new Error("No public keys could be fetched using HKP"))
|
||||
reject(new Error(`No public keys could be fetched using HKP`))
|
||||
}
|
||||
|
||||
if (!output.publicKey) {
|
||||
reject(new Error("No public keys could be fetched using HKP"))
|
||||
reject(new Error(`No public keys could be fetched using HKP`))
|
||||
}
|
||||
|
||||
resolve(output)
|
||||
})
|
||||
}
|
||||
|
||||
const fetchSignature = (signature) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let output = {
|
||||
publicKey: null,
|
||||
fetchURL: null,
|
||||
keyData: null
|
||||
}
|
||||
|
||||
// Check validity of signature
|
||||
let signatureData
|
||||
try {
|
||||
signatureData = await openpgp.cleartext.readArmored(signature)
|
||||
} catch (error) {
|
||||
reject(new Error(`Signature could not be properly read (${error.message})`))
|
||||
}
|
||||
|
||||
// Process the signature
|
||||
try {
|
||||
output.keyData = await doip.signatures.process(signature)
|
||||
output.publicKey = output.keyData.key.data
|
||||
// TODO Find the URL to the key
|
||||
output.fetchURL = null
|
||||
} catch(error) {
|
||||
reject(new Error(`Signature could not be properly read (${error.message})`))
|
||||
}
|
||||
|
||||
// Check if a key was fetched
|
||||
if (!output.publicKey) {
|
||||
reject(new Error(`No public keys could be fetched`))
|
||||
}
|
||||
|
||||
// Check validity of signature
|
||||
const verified = await openpgp.verify({
|
||||
message: signatureData,
|
||||
publicKeys: output.publicKey
|
||||
})
|
||||
const { valid } = verified.signatures[0]
|
||||
if (!valid) {
|
||||
reject(new Error('Signature was invalid'))
|
||||
}
|
||||
|
||||
resolve(output)
|
||||
|
@ -129,11 +174,11 @@ const fetchKeybase = (username, fingerprint) => {
|
|||
output.publicKey = await doip.keys.fetchKeybase(username, fingerprint)
|
||||
output.fetchURL = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}`
|
||||
} catch(error) {
|
||||
reject(new Error("No public keys could be fetched from Keybase"))
|
||||
reject(new Error(`No public keys could be fetched from Keybase`))
|
||||
}
|
||||
|
||||
if (!output.publicKey) {
|
||||
reject(new Error("No public keys could be fetched from Keybase"))
|
||||
reject(new Error(`No public keys could be fetched from Keybase`))
|
||||
}
|
||||
|
||||
resolve(output)
|
||||
|
@ -142,4 +187,5 @@ const fetchKeybase = (username, fingerprint) => {
|
|||
|
||||
exports.fetchWKD = fetchWKD
|
||||
exports.fetchHKP = fetchHKP
|
||||
exports.fetchSignature = fetchSignature
|
||||
exports.fetchKeybase = fetchKeybase
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
extends templates/base.pug
|
||||
|
||||
block content
|
||||
section.profile.narrow
|
||||
h2 Something went wrong when generating the profile
|
||||
|
||||
ul
|
||||
each error in data.errors
|
||||
li= error
|
|
@ -24,7 +24,7 @@ block content
|
|||
script.
|
||||
kx = {
|
||||
key: {
|
||||
url: "!{data.key.fetchURL}",
|
||||
url: "!{data && data.key && data.key.fetchURL ? data.key.fetchURL : null}",
|
||||
object: null
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,21 @@ block content
|
|||
p
|
||||
a#qr--altLink
|
||||
|
||||
if (isSignature)
|
||||
#profileSigInput.card.card--form
|
||||
form#formGenerateSignatureProfile(method='post')
|
||||
label(for="signature") Please enter the raw profile signature below and press "Generate profile".
|
||||
textarea#signature(name='signature')= signature
|
||||
input(type='submit', name='submit', value='Generate profile')
|
||||
|
||||
|
||||
if (data && 'errors' in data && data.errors.length > 0)
|
||||
h2 Something went wrong while generating the profile
|
||||
ul
|
||||
each error in data.errors
|
||||
li= error
|
||||
else
|
||||
unless (isSignature && !signature)
|
||||
#profileHeader.card.card--profileHeader
|
||||
a.avatar(href="#")
|
||||
img#profileAvatar(src=data.extra.avatarURL alt="avatar")
|
||||
|
@ -74,4 +89,3 @@ block content
|
|||
each user, index in data.keyData.users
|
||||
unless index == data.keyData.primaryUserIndex
|
||||
+generateUser(user, false)
|
||||
|
||||
|
|
|
@ -874,7 +874,7 @@ bn.js@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
|
||||
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
|
||||
|
||||
body-parser@1.19.0:
|
||||
body-parser@1.19.0, body-parser@^1.19.0:
|
||||
version "1.19.0"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
|
||||
|
|
Loading…
Reference in a new issue