Skip to content

Commit

Permalink
feat: accept more signature algorithms like ECDSA/Ed25519
Browse files Browse the repository at this point in the history
  • Loading branch information
atsu1125 committed Feb 19, 2024
1 parent 46af04d commit 15ac6c0
Showing 1 changed file with 75 additions and 4 deletions.
79 changes: 75 additions & 4 deletions src/server/activitypub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ import { In } from 'typeorm';
import { ensure } from '../prelude/ensure';
import { renderLike } from '../remote/activitypub/renderer/like';
import config from '../config';
import { verifyDigest } from '../remote/activitypub/check-fetch.js';
import * as Koa from 'koa';
import * as crypto from 'crypto';
import { inspect } from 'util';
import { IActivity } from '../remote/activitypub/type';
import { serverLogger } from '.';

// Init router
const router = new Router();
Expand All @@ -32,25 +35,93 @@ function inbox(ctx: Router.RouterContext) {
if (config.disableFederation) ctx.throw(404);

if (ctx.req.headers.host !== config.host) {
serverLogger.warn("inbox: Invalid Host");
ctx.status = 400;
ctx.message = "Invalid Host";
return;
}

let signature;
let signature: httpSignature.IParsedSignature;

try {
signature = httpSignature.parseRequest(ctx.req, { headers: ['(request-target)', 'digest', 'host', 'date'] });
} catch (e) {
serverLogger.warn(`inbox: signature parse error: ${inspect(e)}`);
ctx.status = 401;

if (e instanceof Error) {
if (e.name === "ExpiredRequestError")
ctx.message = "Expired Request Error";
if (e.name === "MissingHeaderError")
ctx.message = "Missing Required Header";
}

return;
}

// Validate signature algorithm
if (
!signature.algorithm
.toLowerCase()
.match(/^((dsa|rsa|ecdsa)-(sha256|sha384|sha512)|ed25519-sha512|hs2019)$/)
) {
serverLogger.warn(
`inbox: invalid signature algorithm ${signature.algorithm}`,
);
ctx.status = 401;
ctx.message = "Invalid Signature Algorithm";
return;

// hs2019
// keyType=ED25519 => ed25519-sha512
// keyType=other => (keyType)-sha256
}

// Validate digest header
const digest = ctx.req.headers.digest;

if (typeof digest !== "string") {
serverLogger.warn(
"inbox: zero or more than one digest header(s) are present",
);
ctx.status = 401;
ctx.message = "Invalid Digest Header";
return;
}

if (!verifyDigest(ctx.request.rawBody, ctx.headers.digest)) {
const match = digest.match(/^([0-9A-Za-z-]+)=(.+)$/);

if (match == null) {
serverLogger.warn("inbox: unrecognized digest header");
ctx.status = 401;
ctx.message = "Invalid Digest Header";
return;
}


const digestAlgo = match[1];
const expectedDigest = match[2];

if (digestAlgo.toUpperCase() !== "SHA-256") {
serverLogger.warn("inbox: unsupported digest algorithm");
ctx.status = 401;
ctx.message = "Unsupported Digest Algorithm";
return;
}

const actualDigest = crypto
.createHash("sha256")
.update(ctx.request.rawBody)
.digest("base64");

if (expectedDigest !== actualDigest) {
serverLogger.warn("inbox: Digest Mismatch");
ctx.status = 401;
ctx.message = "Digest Missmatch";
return;
}

processInbox(ctx.request.body, signature);
processInbox(ctx.request.body as IActivity, signature);

ctx.status = 202;
}
Expand Down

0 comments on commit 15ac6c0

Please sign in to comment.