From 5641b0b3ade309539b2b4ec7fd7073e341e6126a Mon Sep 17 00:00:00 2001 From: Erin Shepherd Date: Mon, 16 Oct 2023 23:37:09 +0200 Subject: [PATCH] fix: Refetch user keys when HTTP Signature validation fails If a user has had a key rotation, and nobody on this server follows that user, we will not receive the Update activity with the new key Therefore, when we encounter key validation errors we should check for an up-to-date key. References (other implementations): * [Mastodon](https://github.com/mastodon/mastodon/blob/fc9ab61448af94513524f14f5fd287d2a26ceeab/app/controllers/concerns/signature_verification.rb#L96) * [Akkoma](https://akkoma.dev/AkkomaGang/http_signatures/src/branch/main/lib/http_signatures/http_signatures.ex#L46) --- .../src/core/activitypub/ApDbResolverService.ts | 13 +++++++++++++ .../src/queue/processors/InboxProcessorService.ts | 13 ++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index 995c5dcd5f..e902c046a6 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -164,6 +164,19 @@ export class ApDbResolverService implements OnApplicationShutdown { }; } + /** + * Miskey User -> Refetched Key + */ + @bindThis + public async refetchPublicKeyForApId(user: MiRemoteUser): Promise { + await this.apPersonService.updatePerson(user.uri!); + const key = this.userPublickeysRepository.findOneBy({ userId: user.id }); + if (key != null) { + await this.publicKeyByUserIdCache.set(user.id, key); + } + return key; + } + @bindThis public dispose(): void { this.publicKeyCache.dispose(); diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts index 99e823f9fa..07ebcb221c 100644 --- a/packages/backend/src/queue/processors/InboxProcessorService.ts +++ b/packages/backend/src/queue/processors/InboxProcessorService.ts @@ -104,7 +104,18 @@ export class InboxProcessorService { } // HTTP-Signatureの検証 - const httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem); + let httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem); + + // If signature validation failed, try refetching the actor + if (!httpSignatureValidated) { + authUser.key = await this.apDbResolverService.refetchPublicKeyForApId(authUser.user); + + if (authUser.key == null) { + throw new Bull.UnrecoverableError('skip: failed to re-resolve user publicKey'); + } + + httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem); + } // また、signatureのsignerは、activity.actorと一致する必要がある if (!httpSignatureValidated || authUser.user.uri !== activity.actor) {