Add hash and signature verification on API read from leveldb
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 34s Details

This commit is contained in:
Ladd Hoffman 2024-03-23 15:26:27 -05:00
parent f0180a5c1f
commit 900b5aa4e5
1 changed files with 37 additions and 17 deletions

View File

@ -1,10 +1,7 @@
const express = require('express');
const { Level } = require('level');
const { recoverPersonalSignature } = require('@metamask/eth-sig-util');
// const { ecrecover, fromRpcSig, pubToAddress } = require('@ethereumjs/util');
// const { Keccak } = require('sha3');
const objectHash = require('object-hash');
// const { createHash } = require('node:crypto');
require('dotenv').config();
@ -14,39 +11,47 @@ const dataDir = process.env.DATA_DIR || 'data';
const db = new Level(`${dataDir}/forum`, { valueEncoding: 'json' });
// const keccak = Keccak(256);
const verifySignature = ({ author, content, signature }) => {
try {
const account = recoverPersonalSignature({ data: content, signature });
if (account !== author) {
console.log('error: author does not match signature');
return false;
}
} catch (e) {
console.log('error: failed to recover signature:', e.message);
return false;
}
return true;
};
app.use(express.json());
app.post('/write', async (req, res) => {
const { body: { author, content, signature } } = req;
// Check author signature
try {
const account = recoverPersonalSignature({ data: content, signature });
if (account !== author) {
console.log('error: author does not match signature');
res.status(403).end();
return;
}
} catch (e) {
console.log('error: failed to recover signature:', e.message);
res.status(400).end();
if (!verifySignature({ author, content, signature })) {
res.status(403).end();
return;
}
// Compute content hash
const data = { author, content, signature };
const hash = objectHash(data);
console.log('write', hash);
// Store content
db.put(hash, data);
// Return hash
res.send(hash);
});
app.get('/read/:hash', async (req, res) => {
// Fetch content
const { hash } = req.params;
console.log('read', hash);
// Fetch content
let data;
try {
data = await db.get(req.params.hash);
@ -55,7 +60,22 @@ app.get('/read/:hash', async (req, res) => {
res.status(e.status).end();
return;
}
console.log('read', hash);
// Verify hash
const derivedHash = objectHash(data);
if (derivedHash !== hash) {
console.log('error: hash mismatch');
res.status(500).end();
return;
}
// Verify signature
if (!verifySignature(data)) {
console.log('error: signature verificaition failed');
res.status(500).end();
return;
}
// Return content
res.json(data);
});