From 3f3d26167745a1cf94fd2c1257ba82bee83f44b9 Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Sat, 8 Aug 2020 21:39:04 +0200 Subject: [PATCH] Add server scripts --- index.js | 1 + routes/server.js | 59 +++++++++++++++++ server/proofVerification.js | 127 ++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 routes/server.js create mode 100644 server/proofVerification.js diff --git a/index.js b/index.js index a7013d0..b713e84 100644 --- a/index.js +++ b/index.js @@ -15,6 +15,7 @@ app.use('/favicon.svg', express.static('favicon.svg')); app.use('/', require('./routes/main')); app.use('/dep', require('./routes/dep')); +app.use('/server', require('./routes/server')); app.use('/encrypt', require('./routes/encrypt')); app.use('/verify', require('./routes/verify')); app.use('/proofs', require('./routes/proofs')); diff --git a/routes/server.js b/routes/server.js new file mode 100644 index 0000000..2269a6b --- /dev/null +++ b/routes/server.js @@ -0,0 +1,59 @@ +const router = require('express').Router(); +const { check, query, validationResult } = require('express-validator'); +const proofVerification = require('../server/proofVerification'); + +router.get('/verify/proxy', [ + query('url').isURL().exists(), + query('fingerprint').isHexadecimal().exists(), + query('checkClaim').escape(), + query('checkClaimFormat').escape(), + query('checkRelation').escape().exists(), + query('checkPath').escape().exists() +], async function(req, res) { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ success: false, errors: errors.array() }); + } + + let params = { + url: req.query.url, + fingerprint: req.query.fingerprint, + checkClaim: req.query.checkClaim ? req.query.checkClaim : null, + checkClaimFormat: req.query.checkClaimFormat ? req.query.checkClaimFormat : "uri", + checkRelation: req.query.checkRelation, + checkPath: req.query.checkPath.split(',') + } + + try { + const proofResult = await proofVerification.Proxy(params); + res.status(200).send(proofResult); + } catch (e) { + console.log(e); + res.status(400).send({ success: false, errors: e }); + } +}); + +router.get('/verify/twitter', [ + query('tweetId').isInt().exists(), + query('fingerprint').isHexadecimal().exists() +], async function(req, res) { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ success: false, errors: errors.array() }); + } + + let params = { + tweetId: req.query.tweetId, + fingerprint: req.query.fingerprint + } + + try { + const proofResult = await proofVerification.Twitter(params); + res.status(200).send(proofResult); + } catch (e) { + console.log(e); + res.status(400).send({ success: false, errors: e }); + } +}); + +module.exports = router; diff --git a/server/proofVerification.js b/server/proofVerification.js new file mode 100644 index 0000000..981aa5b --- /dev/null +++ b/server/proofVerification.js @@ -0,0 +1,127 @@ +const bent = require('bent'); +const getJSON = bent('json'); +require('dotenv').config(); + +const Proxy = async (params) => { + let res = { + success: false, + errors: [], + isVerified: false, + params: params + } + + if (!res.params.checkClaim) { + switch (res.params.checkClaimFormat) { + default: + case "uri": + res.params.checkClaim = `openpgp4fpr:${res.params.fingerprint}`; + break; + case "message": + res.params.checkClaim = `[Verifying my OpenPGP key: openpgp4fpr:${res.params.fingerprint}]`; + break; + case "fingerprint": + res.params.checkClaim = res.params.fingerprint; + break; + } + } + + const obj = await getJSON(res.params.url); + res.isVerified = VerifyJsonProof(obj, res.params.checkPath, res.params.checkClaim, res.params.checkRelation); + + return res; +}; + +const Twitter = async (params) => { + let res = { + success: false, + errors: [], + isVerified: false, + params: params + } + + let twitter_api_auth = process.env.TWITTER_API_AUTH; + if (!twitter_api_auth) { + res.errors.push("No Twitter API auth token provided"); + return res; + } + + let proofUrl = `https://api.twitter.com/labs/2/tweets/${res.params.tweetId}?tweet.fields=author_id,created_at,id,source,text`; + let re = new RegExp(`[Verifying my OpenPGP key: openpgp4fpr:${res.params.fingerprint}]`, "gi"); + + const get = bent('GET', 'json', {'Content-Type': 'application/json', 'Authorization': `Bearer ${twitter_api_auth}`}); + const obj = await get(proofUrl); + res.isVerified = re.test(obj.data.text); + + return res; +}; + +const VerifyJsonProof = (data, checkPath, checkClaim, checkRelation) => { + let isVerified = false; + + if (!data) { + return isVerified; + } + + if (checkPath.length == 0) { + switch (checkRelation) { + default: + case 'contains': + let re = new RegExp(checkClaim, "gi"); + return re.test(data); + break; + case 'eq': + return data == checkClaim; + break; + case 'oneOf': + return data.includes(checkClaim); + break; + } + } + + if (Array.isArray(data)) { + data.forEach((item, i) => { + isVerified = isVerified || VerifyJsonProof(item, checkPath, checkClaim, checkRelation); + }); + } else if (Array.isArray(data[checkPath[0]])) { + data[checkPath[0]].forEach((item, i) => { + isVerified = isVerified || VerifyJsonProof(item, checkPath.slice(1), checkClaim, checkRelation); + }); + } else { + isVerified = isVerified || VerifyJsonProof(data[checkPath[0]], checkPath.slice(1), checkClaim, checkRelation); + } + + return isVerified; +} + +exports.Proxy = Proxy; +exports.Twitter = Twitter; + +// include 'secrets.php'; +// +// $fingerprint = urlencode($_GET["fp"]); +// $tweetId = urlencode($_GET["id"]); +// +// $check = "\[Verifying my OpenPGP key: openpgp4fpr:$fingerprint\]"; +// +// $response = array(); +// $response["verified"] = false; +// $response["fingerprint"] = $fingerprint; +// $response["tweetId"] = $tweetId; +// $response["text"] = $data["data"]["text"]; +// +// if (!is_null($twitter_api_auth)) { +// $ch = curl_init(); +// curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', $twitter_api_auth)); +// curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); +// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +// curl_setopt($ch, CURLOPT_URL, "https://api.twitter.com/labs/2/tweets/$tweetId?tweet.fields=author_id,created_at,id,source,text"); +// $result = curl_exec($ch); +// curl_close($ch); +// $data = json_decode($result, true); +// +// if (preg_match("/{$check}/i", $data["data"]["text"])) { +// $response["verified"] = true; +// } +// } +// +// echo json_encode($response);