diff --git a/packages/backend/migration/1709242519122-HttpSignImplLv.js b/packages/backend/migration/1709242519122-HttpSignImplLv.js
new file mode 100644
index 0000000000..7748bae006
--- /dev/null
+++ b/packages/backend/migration/1709242519122-HttpSignImplLv.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class HttpSignImplLv1709242519122 {
+    name = 'HttpSignImplLv1709242519122'
+
+    async up(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "instance" ADD "httpMessageSignaturesImplementationLevel" character varying(16) NOT NULL DEFAULT '00'`);
+    }
+
+    async down(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "httpMessageSignaturesImplementationLevel"`);
+    }
+}
diff --git a/packages/backend/src/core/FetchInstanceMetadataService.ts b/packages/backend/src/core/FetchInstanceMetadataService.ts
index bc270bd28f..63168afd7d 100644
--- a/packages/backend/src/core/FetchInstanceMetadataService.ts
+++ b/packages/backend/src/core/FetchInstanceMetadataService.ts
@@ -24,6 +24,7 @@ type NodeInfo = {
 		version?: unknown;
 	};
 	metadata?: {
+		httpMessageSignaturesImplementationLevel?: unknown,
 		name?: unknown;
 		nodeName?: unknown;
 		nodeDescription?: unknown;
@@ -70,7 +71,7 @@ export class FetchInstanceMetadataService {
 			if (!force) {
 				const _instance = await this.federatedInstanceService.fetch(host);
 				const now = Date.now();
-				if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < 1000 * 60 * 60 * 24)) {
+				if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < 1000 * 60 * 60 * 3)) {
 					// unlock at the finally caluse
 					return;
 				}
@@ -104,6 +105,9 @@ export class FetchInstanceMetadataService {
 				updates.openRegistrations = info.openRegistrations;
 				updates.maintainerName = info.metadata ? info.metadata.maintainer ? (info.metadata.maintainer.name ?? null) : null : null;
 				updates.maintainerEmail = info.metadata ? info.metadata.maintainer ? (info.metadata.maintainer.email ?? null) : null : null;
+				if (info.metadata && info.metadata.httpMessageSignaturesImplementationLevel) {
+					updates.httpMessageSignaturesImplementationLevel = info.metadata.httpMessageSignaturesImplementationLevel.toString() ?? '00';
+				}
 			}
 
 			if (name) updates.name = name;
diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts
index 93ac8ce9a7..717e47d4b4 100644
--- a/packages/backend/src/core/activitypub/ApRequestService.ts
+++ b/packages/backend/src/core/activitypub/ApRequestService.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import * as crypto from 'node:crypto';
 import { URL } from 'node:url';
 import { Inject, Injectable } from '@nestjs/common';
+import { genRFC3230DigestHeader, RequestLike, signAsDraftToRequest } from '@misskey-dev/node-http-message-signatures';
 import { DI } from '@/di-symbols.js';
 import type { Config } from '@/config.js';
 import type { MiUser } from '@/models/User.js';
@@ -16,12 +16,6 @@ import { bindThis } from '@/decorators.js';
 import type Logger from '@/logger.js';
 import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
 
-type Request = {
-	url: string;
-	method: string;
-	headers: Record<string, string>;
-};
-
 type Signed = {
 	request: Request;
 	signingString: string;
@@ -34,103 +28,51 @@ type PrivateKey = {
 	keyId: string;
 };
 
-export class ApRequestCreator {
-	static createSignedPost(args: { key: PrivateKey, url: string, body: string, digest?: string, additionalHeaders: Record<string, string> }): Signed {
-		const u = new URL(args.url);
-		const digestHeader = args.digest ?? this.createDigest(args.body);
+export function createSignedPost(args: { level: string; key: PrivateKey; url: string; body: string; digest?: string; additionalHeaders: Record<string, string> }) {
+	const u = new URL(args.url);
+	const request: RequestLike = {
+		url: u.href,
+		method: 'POST',
+		headers: {
+			'Date': new Date().toUTCString(),
+			'Host': u.host,
+			'Content-Type': 'application/activity+json',
+			...args.additionalHeaders,
+		},
+	};
 
-		const request: Request = {
-			url: u.href,
-			method: 'POST',
-			headers: this.#objectAssignWithLcKey({
-				'Date': new Date().toUTCString(),
-				'Host': u.host,
-				'Content-Type': 'application/activity+json',
-				'Digest': digestHeader,
-			}, args.additionalHeaders),
-		};
+	// TODO: levelによって処理を分ける
+	const digestHeader = args.digest ?? genRFC3230DigestHeader(args.body);
+	request.headers['Digest'] = digestHeader;
 
-		const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']);
+	const result = signAsDraftToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']);
 
-		return {
-			request,
-			signingString: result.signingString,
-			signature: result.signature,
-			signatureHeader: result.signatureHeader,
-		};
-	}
+	return {
+		request,
+		...result,
+	};
+}
 
-	static createDigest(body: string) {
-		return `SHA-256=${crypto.createHash('sha256').update(body).digest('base64')}`;
-	}
+export function createSignedGet(args: { level: string; key: PrivateKey; url: string; additionalHeaders: Record<string, string> }) {
+	const u = new URL(args.url);
+	const request: RequestLike = {
+		url: u.href,
+		method: 'GET',
+		headers: {
+			'Accept': 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+			'Date': new Date().toUTCString(),
+			'Host': new URL(args.url).host,
+			...args.additionalHeaders,
+		},
+	};
 
-	static createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record<string, string> }): Signed {
-		const u = new URL(args.url);
+	// TODO: levelによって処理を分ける
+	const result = signAsDraftToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
 
-		const request: Request = {
-			url: u.href,
-			method: 'GET',
-			headers: this.#objectAssignWithLcKey({
-				'Accept': 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
-				'Date': new Date().toUTCString(),
-				'Host': new URL(args.url).host,
-			}, args.additionalHeaders),
-		};
-
-		const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
-
-		return {
-			request,
-			signingString: result.signingString,
-			signature: result.signature,
-			signatureHeader: result.signatureHeader,
-		};
-	}
-
-	static #signToRequest(request: Request, key: PrivateKey, includeHeaders: string[]): Signed {
-		const signingString = this.#genSigningString(request, includeHeaders);
-		const signature = crypto.sign('sha256', Buffer.from(signingString), key.privateKeyPem).toString('base64');
-		const signatureHeader = `keyId="${key.keyId}",algorithm="rsa-sha256",headers="${includeHeaders.join(' ')}",signature="${signature}"`;
-
-		request.headers = this.#objectAssignWithLcKey(request.headers, {
-			Signature: signatureHeader,
-		});
-		// node-fetch will generate this for us. if we keep 'Host', it won't change with redirects!
-		delete request.headers['host'];
-
-		return {
-			request,
-			signingString,
-			signature,
-			signatureHeader,
-		};
-	}
-
-	static #genSigningString(request: Request, includeHeaders: string[]): string {
-		request.headers = this.#lcObjectKey(request.headers);
-
-		const results: string[] = [];
-
-		for (const key of includeHeaders.map(x => x.toLowerCase())) {
-			if (key === '(request-target)') {
-				results.push(`(request-target): ${request.method.toLowerCase()} ${new URL(request.url).pathname}`);
-			} else {
-				results.push(`${key}: ${request.headers[key]}`);
-			}
-		}
-
-		return results.join('\n');
-	}
-
-	static #lcObjectKey(src: Record<string, string>): Record<string, string> {
-		const dst: Record<string, string> = {};
-		for (const key of Object.keys(src).filter(x => x !== '__proto__' && typeof src[x] === 'string')) dst[key.toLowerCase()] = src[key];
-		return dst;
-	}
-
-	static #objectAssignWithLcKey(a: Record<string, string>, b: Record<string, string>): Record<string, string> {
-		return Object.assign(this.#lcObjectKey(a), this.#lcObjectKey(b));
-	}
+	return {
+		request,
+		...result,
+	};
 }
 
 @Injectable()
@@ -150,16 +92,25 @@ export class ApRequestService {
 	}
 
 	@bindThis
-	public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown, digest?: string): Promise<void> {
+	private async getPrivateKey(userId: MiUser['id'], level: string): Promise<PrivateKey> {
+		const keypair = await this.userKeypairService.getUserKeypair(userId);
+
+		return (level !== '00' && keypair.ed25519PrivateKey) ? {
+			privateKeyPem: keypair.ed25519PrivateKey,
+			keyId: `${this.config.url}/users/${userId}#ed25519-key`,
+		} : {
+			privateKeyPem: keypair.privateKey,
+			keyId: `${this.config.url}/users/${userId}#main-key`,
+		};
+	}
+
+	@bindThis
+	public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown, level: string, digest?: string): Promise<void> {
 		const body = typeof object === 'string' ? object : JSON.stringify(object);
 
-		const keypair = await this.userKeypairService.getUserKeypair(user.id);
-
-		const req = ApRequestCreator.createSignedPost({
-			key: {
-				privateKeyPem: keypair.privateKey,
-				keyId: `${this.config.url}/users/${user.id}#main-key`,
-			},
+		const req = createSignedPost({
+			level,
+			key: await this.getPrivateKey(user.id, level),
 			url,
 			body,
 			digest,
@@ -180,14 +131,10 @@ export class ApRequestService {
 	 * @param url URL to fetch
 	 */
 	@bindThis
-	public async signedGet(url: string, user: { id: MiUser['id'] }): Promise<unknown> {
-		const keypair = await this.userKeypairService.getUserKeypair(user.id);
-
-		const req = ApRequestCreator.createSignedGet({
-			key: {
-				privateKeyPem: keypair.privateKey,
-				keyId: `${this.config.url}/users/${user.id}#main-key`,
-			},
+	public async signedGet(url: string, user: { id: MiUser['id'] }, level: string): Promise<unknown> {
+		const req = createSignedGet({
+			level,
+			key: await this.getPrivateKey(user.id, level),
 			url,
 			additionalHeaders: {
 			},
diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts
index bb3c40f093..727ff6f956 100644
--- a/packages/backend/src/core/activitypub/ApResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApResolverService.ts
@@ -16,6 +16,7 @@ import { UtilityService } from '@/core/UtilityService.js';
 import { bindThis } from '@/decorators.js';
 import { LoggerService } from '@/core/LoggerService.js';
 import type Logger from '@/logger.js';
+import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
 import { isCollectionOrOrderedCollection } from './type.js';
 import { ApDbResolverService } from './ApDbResolverService.js';
 import { ApRendererService } from './ApRendererService.js';
@@ -41,6 +42,7 @@ export class Resolver {
 		private httpRequestService: HttpRequestService,
 		private apRendererService: ApRendererService,
 		private apDbResolverService: ApDbResolverService,
+		private federatedInstanceService: FederatedInstanceService,
 		private loggerService: LoggerService,
 		private recursionLimit = 100,
 	) {
@@ -103,8 +105,10 @@ export class Resolver {
 			this.user = await this.instanceActorService.getInstanceActor();
 		}
 
+		const server = await this.federatedInstanceService.fetch(host);
+
 		const object = (this.user
-			? await this.apRequestService.signedGet(value, this.user) as IObject
+			? await this.apRequestService.signedGet(value, this.user, server.httpMessageSignaturesImplementationLevel) as IObject
 			: await this.httpRequestService.getActivityJson(value)) as IObject;
 
 		if (
@@ -200,6 +204,7 @@ export class ApResolverService {
 		private httpRequestService: HttpRequestService,
 		private apRendererService: ApRendererService,
 		private apDbResolverService: ApDbResolverService,
+		private federatedInstanceService: FederatedInstanceService,
 		private loggerService: LoggerService,
 	) {
 	}
@@ -220,6 +225,7 @@ export class ApResolverService {
 			this.httpRequestService,
 			this.apRendererService,
 			this.apDbResolverService,
+			this.federatedInstanceService,
 			this.loggerService,
 		);
 	}
diff --git a/packages/backend/src/models/Instance.ts b/packages/backend/src/models/Instance.ts
index 9863c9d75d..0c94f9b277 100644
--- a/packages/backend/src/models/Instance.ts
+++ b/packages/backend/src/models/Instance.ts
@@ -149,4 +149,9 @@ export class MiInstance {
 		length: 16384, default: '',
 	})
 	public moderationNote: string;
+
+	@Column('varchar', {
+		length: 16, default: '00', nullable: false,
+	})
+	public httpMessageSignaturesImplementationLevel: string;
 }
diff --git a/packages/backend/src/queue/processors/DeliverProcessorService.ts b/packages/backend/src/queue/processors/DeliverProcessorService.ts
index 5fed070929..8f3782a048 100644
--- a/packages/backend/src/queue/processors/DeliverProcessorService.ts
+++ b/packages/backend/src/queue/processors/DeliverProcessorService.ts
@@ -72,24 +72,25 @@ export class DeliverProcessorService {
 		}
 
 		try {
-			await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content, job.data.digest);
+			const _server = await this.federatedInstanceService.fetch(host);
+			await this.fetchInstanceMetadataService.fetchInstanceMetadata(_server).then(() => {});
+			const server = await this.federatedInstanceService.fetch(host);
+
+			await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content, server.httpMessageSignaturesImplementationLevel, job.data.digest);
 
 			// Update stats
-			this.federatedInstanceService.fetch(host).then(i => {
-				if (i.isNotResponding) {
-					this.federatedInstanceService.update(i.id, {
-						isNotResponding: false,
-					});
-				}
+			if (server.isNotResponding) {
+				this.federatedInstanceService.update(server.id, {
+					isNotResponding: false,
+				});
+			}
 
-				this.fetchInstanceMetadataService.fetchInstanceMetadata(i);
-				this.apRequestChart.deliverSucc();
-				this.federationChart.deliverd(i.host, true);
+			this.apRequestChart.deliverSucc();
+			this.federationChart.deliverd(server.host, true);
 
-				if (meta.enableChartsForFederatedInstances) {
-					this.instanceChart.requestSent(i.host, true);
-				}
-			});
+			if (meta.enableChartsForFederatedInstances) {
+				this.instanceChart.requestSent(server.host, true);
+			}
 
 			return 'Success';
 		} catch (res) {