Add hash and signature verification on API read from leveldb
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 34s
Details
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 34s
Details
This commit is contained in:
parent
f0180a5c1f
commit
900b5aa4e5
|
@ -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);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue