diff --git a/packages/backend/package.json b/packages/backend/package.json index 1d3f2fcd2a..82675fafc2 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -79,7 +79,7 @@ "@fastify/multipart": "8.1.0", "@fastify/static": "6.12.0", "@fastify/view": "8.2.0", - "@misskey-dev/node-http-message-signatures": "0.0.0-alpha.11", + "@misskey-dev/node-http-message-signatures": "0.0.1", "@misskey-dev/sharp-read-bmp": "1.2.0", "@misskey-dev/summaly": "5.0.3", "@nestjs/common": "10.3.3", diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts index 36a4b34de1..9dda59543e 100644 --- a/packages/backend/src/core/activitypub/ApRequestService.ts +++ b/packages/backend/src/core/activitypub/ApRequestService.ts @@ -28,7 +28,7 @@ type PrivateKey = { keyId: string; }; -export function createSignedPost(args: { level: string; key: PrivateKey; url: string; body: string; additionalHeaders: Record }) { +export async function createSignedPost(args: { level: string; key: PrivateKey; url: string; body: string; additionalHeaders: Record }) { const u = new URL(args.url); const request: RequestLike = { url: u.href, @@ -42,10 +42,10 @@ export function createSignedPost(args: { level: string; key: PrivateKey; url: st }; // TODO: levelによって処理を分ける - const digestHeader = genRFC3230DigestHeader(args.body); + const digestHeader = await genRFC3230DigestHeader(args.body, 'SHA-256'); request.headers['Digest'] = digestHeader; - const result = signAsDraftToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']); + const result = await signAsDraftToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']); return { request, @@ -53,7 +53,7 @@ export function createSignedPost(args: { level: string; key: PrivateKey; url: st }; } -export function createSignedGet(args: { level: string; key: PrivateKey; url: string; additionalHeaders: Record }) { +export async function createSignedGet(args: { level: string; key: PrivateKey; url: string; additionalHeaders: Record }) { const u = new URL(args.url); const request: RequestLike = { url: u.href, @@ -67,7 +67,7 @@ export function createSignedGet(args: { level: string; key: PrivateKey; url: str }; // TODO: levelによって処理を分ける - const result = signAsDraftToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']); + const result = await signAsDraftToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']); return { request, @@ -108,7 +108,7 @@ export class ApRequestService { public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown, level: string): Promise { const body = typeof object === 'string' ? object : JSON.stringify(object); const key = await this.getPrivateKey(user.id, level); - const req = createSignedPost({ + const req = await createSignedPost({ level, key, url, @@ -140,7 +140,7 @@ export class ApRequestService { @bindThis public async signedGet(url: string, user: { id: MiUser['id'] }, level: string): Promise { const key = await this.getPrivateKey(user.id, level); - const req = createSignedGet({ + const req = await createSignedGet({ level, key, url, diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts index 3f10a128ed..94163a2495 100644 --- a/packages/backend/src/queue/processors/InboxProcessorService.ts +++ b/packages/backend/src/queue/processors/InboxProcessorService.ts @@ -104,7 +104,7 @@ export class InboxProcessorService { // HTTP-Signatureの検証 const errorLogger = (ms: any) => this.logger.error(ms); - const httpSignatureValidated = verifyDraftSignature(signature, authUser.key.keyPem, errorLogger); + const httpSignatureValidated = await verifyDraftSignature(signature, authUser.key.keyPem, errorLogger); this.logger.debug('Inbox message validation: ', { userId: authUser.user.id, userAcct: Acct.toString(authUser.user), diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts index ba0adac03b..1dbb94a2c2 100644 --- a/packages/backend/src/server/ActivityPubServerService.ts +++ b/packages/backend/src/server/ActivityPubServerService.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import * as crypto from 'node:crypto'; import { IncomingMessage } from 'node:http'; import { Inject, Injectable } from '@nestjs/common'; import fastifyAccepts from '@fastify/accepts'; @@ -100,10 +99,10 @@ export class ActivityPubServerService { } @bindThis - private inbox(request: FastifyRequest, reply: FastifyReply) { + private async inbox(request: FastifyRequest, reply: FastifyReply) { let signature: ReturnType; - const verifyDigest = verifyDigestHeader(request.raw, request.rawBody || '', true); + const verifyDigest = await verifyDigestHeader(request.raw, request.rawBody || '', true); if (!verifyDigest) { reply.code(401); return; @@ -120,13 +119,6 @@ export class ActivityPubServerService { return; } - if (signature.value.params.headers.indexOf('host') === -1 - || request.headers.host !== this.config.host) { - // Host not specified or not match. - reply.code(401); - return; - } - this.queueService.inbox(request.body as IActivity, signature); reply.code(202); diff --git a/packages/backend/test/unit/ap-request.ts b/packages/backend/test/unit/ap-request.ts index fc3855534d..797ef73e62 100644 --- a/packages/backend/test/unit/ap-request.ts +++ b/packages/backend/test/unit/ap-request.ts @@ -43,12 +43,12 @@ describe('ap-request', () => { 'User-Agent': 'UA', }; - const req = createSignedPost({ level, key, url, body, additionalHeaders: headers }); + const req = await createSignedPost({ level, key, url, body, additionalHeaders: headers }); const parsed = parseRequestSignature(req.request); expect(parsed?.version).toBe('draft'); if (!parsed) return; - const verify = verifyDraftSignature(parsed.value, keypair.publicKey); + const verify = await verifyDraftSignature(parsed.value, keypair.publicKey); assert.deepStrictEqual(verify, true); }); }); @@ -62,12 +62,12 @@ describe('ap-request', () => { 'User-Agent': 'UA', }; - const req = createSignedGet({ level, key, url, additionalHeaders: headers }); + const req = await createSignedGet({ level, key, url, additionalHeaders: headers }); const parsed = parseRequestSignature(req.request); expect(parsed?.version).toBe('draft'); if (!parsed) return; - const verify = verifyDraftSignature(parsed.value, keypair.publicKey); + const verify = await verifyDraftSignature(parsed.value, keypair.publicKey); assert.deepStrictEqual(verify, true); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52efc4c217..5853c00bb7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,8 +111,8 @@ importers: specifier: 8.2.0 version: 8.2.0 '@misskey-dev/node-http-message-signatures': - specifier: 0.0.0-alpha.11 - version: 0.0.0-alpha.11 + specifier: 0.0.1 + version: 0.0.1 '@misskey-dev/sharp-read-bmp': specifier: 1.2.0 version: 1.2.0 @@ -4621,6 +4621,10 @@ packages: resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==} dev: false + /@lapo/asn1js@1.2.4: + resolution: {integrity: sha512-mdInpQZaYUWu5QbKIB2+Vd+j6Y7cc6xQYNwYBPC9jri2rwy3tbxom0IhhT4G5WOKWO7Iht10SxYpKq+AfuH6dw==} + dev: false + /@levischuck/tiny-cbor@0.2.2: resolution: {integrity: sha512-f5CnPw997Y2GQ8FAvtuVVC19FX8mwNNC+1XJcIi16n/LTJifKO6QBgGLgN3YEmqtGMk17SKSuoWES3imJVxAVw==} dev: false @@ -4750,8 +4754,10 @@ packages: eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.0)(eslint@8.57.0) dev: true - /@misskey-dev/node-http-message-signatures@0.0.0-alpha.11: - resolution: {integrity: sha512-DeLzSIquddDQp+hqD9/zS/IkpJg8Zs1h/4viavCFe37CW2W4ABFumXhYJPB07n775QEihZNuvdipoMNXl83jzw==} + /@misskey-dev/node-http-message-signatures@0.0.1: + resolution: {integrity: sha512-BaMYEOSBwBtDW0NJcljE4S39gFpgNigVzbVFlVsKzu4+k7snL72mXEaAoMCHWCw7XmdY3+fKADbQoqc4SFrpLw==} + dependencies: + '@lapo/asn1js': 1.2.4 dev: false /@misskey-dev/sharp-read-bmp@1.2.0: @@ -6641,7 +6647,7 @@ packages: ts-dedent: 2.2.0 type-fest: 2.19.0 vue: 3.4.21(typescript@5.3.3) - vue-component-type-helpers: 1.8.27 + vue-component-type-helpers: 2.0.3 transitivePeerDependencies: - encoding - supports-color @@ -19440,6 +19446,10 @@ packages: resolution: {integrity: sha512-6bnLkn8O0JJyiFSIF0EfCogzeqNXpnjJ0vW/SZzNHfe6sPx30lTtTXlE5TFs2qhJlAtDFybStVNpL73cPe3OMQ==} dev: true + /vue-component-type-helpers@2.0.3: + resolution: {integrity: sha512-dVPXmrwul+lLt2ErNqwfIGTWkZoPQjlarFx5pwXnCwdJ80ZaJ2nmqtt3KcUgVaKBwBQBpJqOlJPaMxICBay+Cg==} + dev: true + /vue-demi@0.14.7(vue@3.4.21): resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} engines: {node: '>=12'}