Skip to content

Add ed25519 webhook payload signing support#195

Open
MishkaRogachev wants to merge 3 commits into
masterfrom
add-ed25519-webhook-payload-signing-support
Open

Add ed25519 webhook payload signing support#195
MishkaRogachev wants to merge 3 commits into
masterfrom
add-ed25519-webhook-payload-signing-support

Conversation

@MishkaRogachev

@MishkaRogachev MishkaRogachev commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Fixes NIT-4848

Add Ed25519 webhook payload signing to the filtering-report:

  • Add init-filtering-report-signer command to mint a self-signed Ed25519 certificate
  • write-filtering-report-config wires report-forwarder.signer.pem-file.
  • Serve-report-receiver now verifies each report, rejects unsigned/forged with 401.
  • Added @peculiar/x509 + reflect-metadata dependencies for cert generation

@MishkaRogachev MishkaRogachev changed the base branch from release to master June 4, 2026 13:23
@MishkaRogachev MishkaRogachev changed the base branch from master to release June 4, 2026 13:24
@MishkaRogachev MishkaRogachev force-pushed the add-ed25519-webhook-payload-signing-support branch from 31d03c7 to d0c9796 Compare June 4, 2026 13:42
@MishkaRogachev MishkaRogachev force-pushed the add-ed25519-webhook-payload-signing-support branch from d0c9796 to 46649dc Compare June 9, 2026 11:10
@MishkaRogachev MishkaRogachev changed the base branch from release to master June 9, 2026 11:37
@MishkaRogachev MishkaRogachev marked this pull request as ready for review June 9, 2026 11:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Ed25519-based signing for filtering-report webhook payloads in the testnode environment by generating a self-signed certificate, wiring it into filtering-report’s report-forwarder config, and enforcing signature verification in the report receiver.

Changes:

  • Add an init-filtering-report-signer script command to mint a self-signed Ed25519 cert/keypair into /config.
  • Update filtering-report config generation to include report-forwarder.signer.pem-file.
  • Update the report receiver to verify signed payloads and reject invalid/unsigned requests with 401; add required dependencies for cert generation.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test-node.bash Runs signer initialization when --filteringreport is enabled during init.
scripts/package.json Adds @peculiar/x509 and reflect-metadata dependencies for cert generation.
scripts/yarn.lock Locks new transitive dependencies for X.509 / DI support.
scripts/index.ts Registers the new init-filtering-report-signer command with yargs.
scripts/consts.ts Adds /config paths for signer private+cert PEM and pinned public cert PEM.
scripts/config.ts Writes signer config, generates Ed25519 certs, and verifies signatures in serve-report-receiver.
docker-compose.yaml Mounts the shared config volume into report-receiver to access pinned cert.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/config.ts
Comment on lines +1178 to +1194
function verifyReportSignature(req: any, rawBody: Buffer, signerKey: crypto.KeyObject) {
const sigHeader = req.headers['x-signature'] as string;
const tsHeader = req.headers['x-signature-timestamp'] as string;
if (!sigHeader || !tsHeader) {
throw new Error('missing signature headers');
}

const tsSeconds = Number(tsHeader);
if (!Number.isFinite(tsSeconds) || Math.abs(Date.now() - tsSeconds * 1000) > REPORT_SIGNATURE_SKEW_MS) {
throw new Error('timestamp outside tolerance');
}

const payload = Buffer.concat([Buffer.from(`${tsHeader}.`), rawBody] as Uint8Array[]);
if (!crypto.verify(null, payload as Uint8Array, signerKey, Buffer.from(sigHeader, 'base64') as Uint8Array)) {
throw new Error('signature verification failed');
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread scripts/config.ts
Comment on lines 1200 to +1201
const http = require('http');
const signerKey = new crypto.X509Certificate(fs.readFileSync(consts.filteringReportSignerPubPath) as Uint8Array).publicKey;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants