remove sign additionalPublicKeys signature requirements
This commit is contained in:
		
							parent
							
								
									437e69cfc4
								
							
						
					
					
						commit
						9705ec4a47
					
				|  | @ -10,8 +10,6 @@ export class APMultipleKeys1708980134301 { | |||
|         await queryRunner.query(`DROP INDEX "public"."IDX_171e64971c780ebd23fae140bb"`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" ADD "ed25519PublicKey" character varying(128)`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" ADD "ed25519PrivateKey" character varying(128)`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" ADD "ed25519PublicKeySignature" character varying(720)`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" ADD "ed25519SignatureAlgorithm" character varying(32)`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "FK_10c146e4b39b443ede016f6736d"`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "PK_10c146e4b39b443ede016f6736d"`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "PK_0db6a5fdb992323449edc8ee421" PRIMARY KEY ("userId", "keyId")`); | ||||
|  | @ -34,8 +32,6 @@ export class APMultipleKeys1708980134301 { | |||
|         await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "followersVisibility" DROP DEFAULT`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "followersVisibility" TYPE "public"."user_profile_followersVisibility_enum_old" USING "followersVisibility"::"text"::"public"."user_profile_followersVisibility_enum_old"`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "followersVisibility" SET DEFAULT 'public'`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" DROP COLUMN "ed25519SignatureAlgorithm"`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" DROP COLUMN "ed25519PublicKeySignature"`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" DROP COLUMN "ed25519PrivateKey"`); | ||||
|         await queryRunner.query(`ALTER TABLE "user_keypair" DROP COLUMN "ed25519PublicKey"`); | ||||
|         await queryRunner.query(`CREATE UNIQUE INDEX "IDX_171e64971c780ebd23fae140bb" ON "user_publickey" ("keyId") `); | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ | |||
|  * SPDX-License-Identifier: AGPL-3.0-only | ||||
|  */ | ||||
| 
 | ||||
| import { sign } from 'node:crypto'; | ||||
| import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; | ||||
| import * as Redis from 'ioredis'; | ||||
| import type { MiUser } from '@/models/User.js'; | ||||
|  | @ -12,7 +11,7 @@ import { RedisKVCache } from '@/misc/cache.js'; | |||
| import type { MiUserKeypair } from '@/models/UserKeypair.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { ED25519_PUBLIC_KEY_SIGNATURE_ALGORITHM, genEd25519KeyPair } from '@/misc/gen-key-pair.js'; | ||||
| import { genEd25519KeyPair } from '@/misc/gen-key-pair.js'; | ||||
| import { GlobalEventService, GlobalEvents } from '@/core/GlobalEventService.js'; | ||||
| 
 | ||||
| @Injectable() | ||||
|  | @ -56,12 +55,9 @@ export class UserKeypairService implements OnApplicationShutdown { | |||
| 		const keypair = await this.cache.fetch(userId); | ||||
| 		if (keypair.ed25519PublicKey != null) return; | ||||
| 		const ed25519 = await genEd25519KeyPair(); | ||||
| 		const ed25519PublicKeySignature = sign(ED25519_PUBLIC_KEY_SIGNATURE_ALGORITHM, Buffer.from(ed25519.publicKey), keypair.privateKey).toString('base64'); | ||||
| 		await this.userKeypairsRepository.update({ userId }, { | ||||
| 			ed25519PublicKey: ed25519.publicKey, | ||||
| 			ed25519PrivateKey: ed25519.privateKey, | ||||
| 			ed25519PublicKeySignature, | ||||
| 			ed25519SignatureAlgorithm: `rsa-${ED25519_PUBLIC_KEY_SIGNATURE_ALGORITHM}`, | ||||
| 		}); | ||||
| 		this.globalEventService.publishInternalEvent('userKeypairUpdated', { userId }); | ||||
| 	} | ||||
|  |  | |||
|  | @ -250,7 +250,7 @@ export class ApRendererService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public renderKey(user: MiLocalUser, publicKey: string, postfix?: string, signature?: IKey['signature']): IKey { | ||||
| 	public renderKey(user: MiLocalUser, publicKey: string, postfix?: string): IKey { | ||||
| 		return { | ||||
| 			id: `${this.config.url}/users/${user.id}${postfix ?? '/publickey'}`, | ||||
| 			type: 'Key', | ||||
|  | @ -259,7 +259,6 @@ export class ApRendererService { | |||
| 				type: 'spki', | ||||
| 				format: 'pem', | ||||
| 			}) as string, | ||||
| 			signature, | ||||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -501,7 +500,7 @@ export class ApRendererService { | |||
| 			discoverable: user.isExplorable, | ||||
| 			publicKey: this.renderKey(user, keypair.publicKey, '#main-key'), | ||||
| 			additionalPublicKeys: [ | ||||
| 				...(keypair.ed25519PublicKey ? [this.renderKey(user, keypair.ed25519PublicKey, '#ed25519-key', { signatureAlgorithm: keypair.ed25519SignatureAlgorithm!, signatureValue: keypair.ed25519PublicKeySignature! })] : []), | ||||
| 				...(keypair.ed25519PublicKey ? [this.renderKey(user, keypair.ed25519PublicKey, '#ed25519-key')] : []), | ||||
| 			], | ||||
| 			isCat: user.isCat, | ||||
| 			attachment: attachment.length ? attachment : undefined, | ||||
|  |  | |||
|  | @ -212,16 +212,6 @@ export class ApPersonService implements OnModuleInit { | |||
| 				if (keyIdHost !== expectHost) { | ||||
| 					throw new Error('invalid Actor: additionalPublicKeys.id has different host'); | ||||
| 				} | ||||
| 
 | ||||
| 				if (!key.signature) { | ||||
| 					throw new Error('invalid Actor: additionalPublicKeys.signature is not set'); | ||||
| 				} | ||||
| 				if (typeof key.signature.signatureAlgorithm !== 'string') { | ||||
| 					throw new Error('invalid Actor: additionalPublicKeys.signature.signatureAlgorithm is not a string'); | ||||
| 				} | ||||
| 				if (typeof key.signature.signatureValue !== 'string') { | ||||
| 					throw new Error('invalid Actor: additionalPublicKeys.signature.signatureValue is not a string'); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | @ -396,16 +386,11 @@ export class ApPersonService implements OnModuleInit { | |||
| 
 | ||||
| 					if (person.additionalPublicKeys) { | ||||
| 						for (const key of person.additionalPublicKeys) { | ||||
| 							if ( | ||||
| 								key.signature && key.signature.signatureAlgorithm && key.signature.signatureValue && | ||||
| 								verify(key.signature.signatureAlgorithm, Buffer.from(key.publicKeyPem), person.publicKey.publicKeyPem, Buffer.from(key.signature.signatureValue, 'base64')) | ||||
| 							) { | ||||
| 								await transactionalEntityManager.save(new MiUserPublickey({ | ||||
| 									keyId: key.id, | ||||
| 									userId: user.id, | ||||
| 									keyPem: key.publicKeyPem, | ||||
| 								})); | ||||
| 							} | ||||
| 							await transactionalEntityManager.save(new MiUserPublickey({ | ||||
| 								keyId: key.id, | ||||
| 								userId: user.id, | ||||
| 								keyPem: key.publicKeyPem, | ||||
| 							})); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  | @ -563,16 +548,11 @@ export class ApPersonService implements OnModuleInit { | |||
| 
 | ||||
| 			if (person.additionalPublicKeys) { | ||||
| 				for (const key of person.additionalPublicKeys) { | ||||
| 					if ( | ||||
| 						key.signature && key.signature.signatureAlgorithm && key.signature.signatureValue && | ||||
| 						verify(key.signature.signatureAlgorithm, Buffer.from(key.publicKeyPem), person.publicKey.publicKeyPem, Buffer.from(key.signature.signatureValue, 'base64')) | ||||
| 					) { | ||||
| 						await this.userPublickeysRepository.update({ keyId: key.id }, { | ||||
| 							userId: exist.id, | ||||
| 							keyPem: key.publicKeyPem, | ||||
| 						}); | ||||
| 						availablePublicKeys.add(key.id); | ||||
| 					} | ||||
| 					await this.userPublickeysRepository.update({ keyId: key.id }, { | ||||
| 						userId: exist.id, | ||||
| 						keyPem: key.publicKeyPem, | ||||
| 					}); | ||||
| 					availablePublicKeys.add(key.id); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -236,14 +236,6 @@ export interface IKey extends IObject { | |||
| 	id: string; | ||||
| 	owner: string; | ||||
| 	publicKeyPem: string; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Signature of publicKeyPem, signed by root privateKey (for additionalPublicKey) | ||||
| 	 */ | ||||
| 	signature?: { | ||||
| 		signatureAlgorithm: string; | ||||
| 		signatureValue: string | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| export interface IApDocument extends IObject { | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import * as util from 'node:util'; | |||
| 
 | ||||
| const generateKeyPair = util.promisify(crypto.generateKeyPair); | ||||
| 
 | ||||
| export const ED25519_PUBLIC_KEY_SIGNATURE_ALGORITHM = 'sha256'; | ||||
| 
 | ||||
| export async function genRsaKeyPair(modulusLength = 4096) { | ||||
| 	return await generateKeyPair('rsa', { | ||||
| 		modulusLength, | ||||
|  | @ -44,13 +42,10 @@ export async function genEd25519KeyPair() { | |||
| export async function genRSAAndEd25519KeyPair(rsaModulusLength = 4096) { | ||||
| 	const rsa = await genRsaKeyPair(rsaModulusLength); | ||||
| 	const ed25519 = await genEd25519KeyPair(); | ||||
| 	const ed25519PublicKeySignature = crypto.sign(ED25519_PUBLIC_KEY_SIGNATURE_ALGORITHM, Buffer.from(ed25519.publicKey), rsa.privateKey).toString('base64'); | ||||
| 	return { | ||||
| 		publicKey: rsa.publicKey, | ||||
| 		privateKey: rsa.privateKey, | ||||
| 		ed25519PublicKey: ed25519.publicKey, | ||||
| 		ed25519PrivateKey: ed25519.privateKey, | ||||
| 		ed25519PublicKeySignature, | ||||
| 		ed25519SignatureAlgorithm: `rsa-${ED25519_PUBLIC_KEY_SIGNATURE_ALGORITHM}`, | ||||
| 	}; | ||||
| } | ||||
|  |  | |||
|  | @ -48,26 +48,6 @@ export class MiUserKeypair { | |||
| 	}) | ||||
| 	public ed25519PrivateKey: string | null; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Signature of ed25519PublicKey, signed by privateKey. (base64) | ||||
| 	 */ | ||||
| 	@Column('varchar', { | ||||
| 		length: 720, | ||||
| 		nullable: true, | ||||
| 		default: null, | ||||
| 	}) | ||||
| 	public ed25519PublicKeySignature: string | null; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Signature algorithm of ed25519PublicKeySignature. | ||||
| 	 */ | ||||
| 	@Column('varchar', { | ||||
| 		length: 32, | ||||
| 		nullable: true, | ||||
| 		default: null, | ||||
| 	}) | ||||
| 	public ed25519SignatureAlgorithm: string | null; | ||||
| 
 | ||||
| 	constructor(data: Partial<MiUserKeypair>) { | ||||
| 		if (data == null) return; | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,12 +29,6 @@ describe(genRSAAndEd25519KeyPair, () => { | |||
| 		expect(keyPair.ed25519PrivateKey).toMatch(/^-----BEGIN PRIVATE KEY-----/); | ||||
| 		expect(keyPair.ed25519PrivateKey).toMatch(/-----END PRIVATE KEY-----\n$/); | ||||
| 		expect(keyPair.ed25519PrivateKey).not.toBe(keyPair2.ed25519PrivateKey); | ||||
| 		expect(keyPair.ed25519PublicKeySignature).toBe( | ||||
| 			crypto.sign(keyPair.ed25519SignatureAlgorithm.split('-').pop(), Buffer.from(keyPair.ed25519PublicKey), keyPair.privateKey).toString('base64'), | ||||
| 		); | ||||
| 		expect(crypto.verify(keyPair.ed25519SignatureAlgorithm, Buffer.from(keyPair.ed25519PublicKey), keyPair.publicKey, Buffer.from(keyPair.ed25519PublicKeySignature, 'base64'))).toBe(true); | ||||
| 		expect(keyPair.ed25519PublicKeySignature).not.toBe(keyPair2.ed25519PublicKeySignature); | ||||
| 
 | ||||
| 		//const imported = await webCrypto.subtle.importKey('spki', Buffer.from(keyPair.publicKey).buffer, { name: 'rsa-pss', hash: 'sha-256' }, false, ['verify']);
 | ||||
| 	}); | ||||
| }); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue