diff --git a/README.md b/README.md index ab4388c2ebd2..63cfa9c6323d 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ **🌎 **[Misskey](https://misskey-hub.net/)** is an open source, decentralized social media platform that's free forever! 🚀** +**Note** This fork adds argon2 support, so it's possible to migrate from Foundkey and Firefish. + --- diff --git a/package.json b/package.json index 125a33f4063c..74656a24c588 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "lodash": "4.17.21" }, "dependencies": { + "argon2": "^0.30.2", "execa": "7.1.1", "gulp": "4.0.2", "gulp-cssnano": "2.1.3", diff --git a/packages/backend/src/core/CreateSystemUserService.ts b/packages/backend/src/core/CreateSystemUserService.ts index cef664bf0b42..1482bd99376c 100644 --- a/packages/backend/src/core/CreateSystemUserService.ts +++ b/packages/backend/src/core/CreateSystemUserService.ts @@ -1,6 +1,7 @@ import { randomUUID } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { IsNull, DataSource } from 'typeorm'; import { genRsaKeyPair } from '@/misc/gen-key-pair.js'; import { User } from '@/models/entities/User.js'; @@ -27,8 +28,7 @@ export class CreateSystemUserService { const password = randomUUID(); // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(password, salt); + const hash = argon2.hash(password); // Generate secret const secret = generateNativeUserToken(); diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts index 070a9a9e3e44..02f0ef1da440 100644 --- a/packages/backend/src/core/SignupService.ts +++ b/packages/backend/src/core/SignupService.ts @@ -1,6 +1,7 @@ import { generateKeyPair } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { DataSource, IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { UsedUsernamesRepository, UsersRepository } from '@/models/index.js'; @@ -63,8 +64,7 @@ export class SignupService { } // Generate hash of password - const salt = await bcrypt.genSalt(8); - hash = await bcrypt.hash(password, salt); + hash = argon2.hash(password); } // Generate secret diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts index bd3d8a28dab3..86cbe3d62530 100644 --- a/packages/backend/src/server/api/SigninApiService.ts +++ b/packages/backend/src/server/api/SigninApiService.ts @@ -1,6 +1,7 @@ import { randomBytes } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import * as OTPAuth from 'otpauth'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; @@ -122,7 +123,7 @@ export class SigninApiService { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(password, profile.password!); + const same = return argon2.verify(profile.password, password); const fail = async (status?: number, failure?: { id: string }) => { // Append signin history diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index 7b215cea79ca..f3d3cf9055ac 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -1,5 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, RegistrationTicket } from '@/models/index.js'; @@ -155,8 +156,7 @@ export class SignupApiService { const code = secureRndstr(16, { chars: L_CHARS }); // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(password, salt); + const hash = argon2.hash(password); const pendingUser = await this.userPendingsRepository.insert({ id: this.idService.genId(), diff --git a/packages/backend/src/server/api/endpoints/admin/reset-password.ts b/packages/backend/src/server/api/endpoints/admin/reset-password.ts index e9c3b0e69fd9..80c3acf3203a 100644 --- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts @@ -1,5 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository, UserProfilesRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; @@ -57,7 +58,7 @@ export default class extends Endpoint { const passwd = secureRndstr(8); // Generate hash of password - const hash = bcrypt.hashSync(passwd); + const hash = argon2.hash(passwd); await this.userProfilesRepository.update({ userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index a7e39fc0281f..5d1bbf80f8a7 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -1,5 +1,6 @@ import { promisify } from 'node:util'; import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import cbor from 'cbor'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; @@ -56,7 +57,7 @@ export default class extends Endpoint { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = argon2.verify(profile.password, ps.password); if (!same) { throw new Error('incorrect password'); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts index 19c77365c622..363015f0ccb0 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts @@ -1,6 +1,7 @@ import { promisify } from 'node:util'; import * as crypto from 'node:crypto'; import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository, AttestationChallengesRepository } from '@/models/index.js'; @@ -41,7 +42,7 @@ export default class extends Endpoint { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = argon2.verify(profile.password, ps.password); if (!same) { throw new Error('incorrect password'); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts index eb4d7f9c14b1..c2a4cd1e8514 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -1,4 +1,5 @@ import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import * as OTPAuth from 'otpauth'; import * as QRCode from 'qrcode'; import { Inject, Injectable } from '@nestjs/common'; diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts index 4b726aed80bf..59ccecc5259e 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts @@ -1,4 +1,5 @@ import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/index.js'; @@ -38,7 +39,7 @@ export default class extends Endpoint { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = argon2.verify(profile.password, ps.password); if (!same) { throw new Error('incorrect password'); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts index e0e7ba665831..4580cd1bfada 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -1,4 +1,5 @@ import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -34,7 +35,7 @@ export default class extends Endpoint { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = argon2.verify(profile.password, ps.password); if (!same) { throw new Error('incorrect password'); diff --git a/packages/backend/src/server/api/endpoints/i/change-password.ts b/packages/backend/src/server/api/endpoints/i/change-password.ts index 873835a36c9e..7816ce0dd06c 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -1,4 +1,5 @@ import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository } from '@/models/index.js'; @@ -30,15 +31,14 @@ export default class extends Endpoint { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.currentPassword, profile.password!); + const same = argon2.verify(profile.password, ps.currentPassword); if (!same) { throw new Error('incorrect password'); } // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(ps.newPassword, salt); + const hash = argon2.hash(ps.newPassword); await this.userProfilesRepository.update(me.id, { password: hash, diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts index 77a03d9811fa..6d3de36f2b40 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -1,4 +1,5 @@ import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Inject, Injectable } from '@nestjs/common'; import type { UsersRepository, UserProfilesRepository } from '@/models/index.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; @@ -39,7 +40,7 @@ export default class extends Endpoint { } // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = argon2.verify(profile.password, ps.password); if (!same) { throw new Error('incorrect password'); diff --git a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts index 23ff63f5e9f3..326e47b06790 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -1,4 +1,5 @@ import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository, UserProfilesRepository } from '@/models/index.js'; @@ -39,7 +40,7 @@ export default class extends Endpoint { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = argon2.verify(profile.password, ps.password); if (!same) { throw new Error('incorrect password'); diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index 58e056bd3786..b7d3562d44aa 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -66,7 +66,7 @@ export default class extends Endpoint { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = argon2.verify(profile.password, ps.password); if (!same) { throw new ApiError(meta.errors.incorrectPassword); diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts index e6f1af7b220f..b57ce2584222 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -1,4 +1,5 @@ import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; import { Inject, Injectable } from '@nestjs/common'; import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/index.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; @@ -46,8 +47,7 @@ export default class extends Endpoint { } // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(ps.password, salt); + const hash = argon2.hash(ps.password); await this.userProfilesRepository.update(req.userId, { password: hash,