From b1a43d41c88dbcf1b057019de33e2dc5e31f352a Mon Sep 17 00:00:00 2001 From: Esurio Date: Sun, 14 Jul 2024 05:24:14 +0000 Subject: [PATCH 1/4] wip: argon2 --- packages/backend/package.json | 1 + .../src/core/CreateSystemUserService.ts | 4 +- packages/backend/src/core/SignupService.ts | 4 +- packages/backend/src/misc/password.ts | 20 ++++ .../src/server/api/SigninApiService.ts | 9 +- .../src/server/api/SignupApiService.ts | 5 +- .../api/endpoints/admin/reset-password.ts | 5 +- .../server/api/endpoints/i/change-password.ts | 6 +- .../server/api/endpoints/i/delete-account.ts | 1 + .../server/api/endpoints/reset-password.ts | 4 +- pnpm-lock.yaml | 108 +++++++++++------- 11 files changed, 111 insertions(+), 56 deletions(-) create mode 100644 packages/backend/src/misc/password.ts diff --git a/packages/backend/package.json b/packages/backend/package.json index dc823a9f5a..7b51a210c2 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -104,6 +104,7 @@ "accepts": "1.3.8", "ajv": "8.13.0", "archiver": "7.0.1", + "argon2": "^0.40.3", "async-mutex": "0.5.0", "bcryptjs": "2.4.3", "blurhash": "2.0.5", diff --git a/packages/backend/src/core/CreateSystemUserService.ts b/packages/backend/src/core/CreateSystemUserService.ts index 6c5b0f6a36..0cea8c5170 100644 --- a/packages/backend/src/core/CreateSystemUserService.ts +++ b/packages/backend/src/core/CreateSystemUserService.ts @@ -6,6 +6,7 @@ import { randomUUID } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import { hashPassword } from '@/misc/password.js'; import { IsNull, DataSource } from 'typeorm'; import { genRsaKeyPair } from '@/misc/gen-key-pair.js'; import { MiUser } from '@/models/User.js'; @@ -32,8 +33,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 = await hashPassword(password); // Generate secret const secret = generateNativeUserToken(); diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts index 5522ecd6cc..365a6b75c5 100644 --- a/packages/backend/src/core/SignupService.ts +++ b/packages/backend/src/core/SignupService.ts @@ -6,6 +6,7 @@ import { generateKeyPair } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import { hashPassword } from '@/misc/password.js'; import { DataSource, IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; import type { UsedUsernamesRepository, UsersRepository } from '@/models/_.js'; @@ -66,8 +67,7 @@ export class SignupService { } // Generate hash of password - const salt = await bcrypt.genSalt(8); - hash = await bcrypt.hash(password, salt); + hash = await hashPassword(password); } // Generate secret diff --git a/packages/backend/src/misc/password.ts b/packages/backend/src/misc/password.ts new file mode 100644 index 0000000000..a1a3327267 --- /dev/null +++ b/packages/backend/src/misc/password.ts @@ -0,0 +1,20 @@ +import bcrypt from 'bcryptjs'; +import * as argon2 from 'argon2'; +import { randomBytes } from 'crypto'; + +export async function hashPassword(password: string): Promise { + const salt = randomBytes(32); + return argon2.hash(password, { salt: salt, type: argon2.argon2id }); +} + +export async function comparePassword(password: string, hash: string): Promise { + if (isOldAlgorithm(hash)) { + return bcrypt.compare(password, hash); + } + + return argon2.verify(hash, password); +} + +export function isOldAlgorithm(hash: string): boolean { + return hash.startsWith('$2'); +} diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts index edac9b3beb..95120ce8e0 100644 --- a/packages/backend/src/server/api/SigninApiService.ts +++ b/packages/backend/src/server/api/SigninApiService.ts @@ -5,6 +5,8 @@ import { Inject, Injectable } from '@nestjs/common'; import bcrypt from 'bcryptjs'; +import * as argon from 'argon2'; +import { comparePassword, hashPassword, isOldAlgorithm } from '@/misc/password.js'; import * as OTPAuth from 'otpauth'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; @@ -123,7 +125,12 @@ export class SigninApiService { const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(password, profile.password!); + const same = await comparePassword(password, profile.password!); + + if (same && isOldAlgorithm(profile.password!)) { + profile.password = await hashPassword(password); + await this.userProfilesRepository.save(profile); + } 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 632b0c62bc..39bbfd5c19 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -5,6 +5,7 @@ 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, MiRegistrationTicket } from '@/models/_.js'; @@ -21,6 +22,7 @@ import { bindThis } from '@/decorators.js'; import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js'; import { SigninService } from './SigninService.js'; import type { FastifyRequest, FastifyReply } from 'fastify'; +import { hashPassword } from '@/misc/password.js'; @Injectable() export class SignupApiService { @@ -180,8 +182,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 = await hashPassword(password); const pendingUser = await this.userPendingsRepository.insertOne({ id: this.idService.gen(), 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 53db096c1d..30d827eab0 100644 --- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts @@ -10,6 +10,7 @@ import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { hashPassword } from '@/misc/password.js'; export const meta = { tags: ['admin'], @@ -62,10 +63,10 @@ export default class extends Endpoint { // eslint- throw new Error('cannot reset password of root'); } - const passwd = secureRndstr(8); + const passwd = secureRndstr(16); // Generate hash of password - const hash = bcrypt.hashSync(passwd); + const hash = await hashPassword(passwd); await this.userProfilesRepository.update({ userId: user.id, 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 bb78d47149..0cad5b5a0e 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -4,6 +4,7 @@ */ import bcrypt from 'bcryptjs'; +import { hashPassword, comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository } from '@/models/_.js'; @@ -50,15 +51,14 @@ export default class extends Endpoint { // eslint- } } - const passwordMatched = await bcrypt.compare(ps.currentPassword, profile.password!); + const passwordMatched = await comparePassword(ps.currentPassword, profile.password!); if (!passwordMatched) { 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 = await hashPassword(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 bfa0b4605d..82578ea2fc 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -4,6 +4,7 @@ */ import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts index 9693892637..44afddf0e9 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -4,6 +4,7 @@ */ import bcrypt from 'bcryptjs'; +import { hashPassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; @@ -53,8 +54,7 @@ export default class extends Endpoint { // eslint- } // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(ps.password, salt); + const hash = await hashPassword(ps.password); await this.userProfilesRepository.update(req.userId, { password: hash, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 146a43ccfa..9960db61dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -188,6 +188,9 @@ importers: archiver: specifier: 7.0.1 version: 7.0.1 + argon2: + specifier: ^0.40.3 + version: 0.40.3 async-mutex: specifier: 0.5.0 version: 0.5.0 @@ -3549,6 +3552,10 @@ packages: resolution: {integrity: sha512-aGQIwo6/sWtyyqhVK4e1MtxYz4N1X8CNt6SOtCc+Wnczs5S5ONaLHDDR8LYaGn0MgOwvGgXyuZ5sJIfd7iyoUw==} engines: {node: '>=0.10'} + '@phc/format@1.0.0': + resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==} + engines: {node: '>=10'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -5494,6 +5501,10 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argon2@0.40.3: + resolution: {integrity: sha512-FrSmz4VeM91jwFvvjsQv9GYp6o/kARWoYKjbjDB2U5io1H3e5X67PYGclFDeQff6UXIhUd4aHR3mxCdBbMMuQw==} + engines: {node: '>=16.17.0'} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -9068,6 +9079,10 @@ packages: node-addon-api@3.2.1: resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} + node-addon-api@8.1.0: + resolution: {integrity: sha512-yBY+qqWSv3dWKGODD6OGE6GnTX7Q2r+4+DfpqxHSHh8x0B4EKP9+wVGLS6U/AM1vxSNNmUEuIV5EGhYwPpfOwQ==} + engines: {node: ^18 || ^20 || >= 21} + node-bitmap@0.0.1: resolution: {integrity: sha512-Jx5lPaaLdIaOsj2mVLWMWulXF6GQVdyLvNSxmiYCvZ8Ma2hfKX0POoR2kgKOqz+oFsRreq0yYZjQ2wjE9VNzCA==} engines: {node: '>=v0.6.5'} @@ -12456,7 +12471,7 @@ snapshots: '@babel/traverse': 7.24.7 '@babel/types': 7.24.7 convert-source-map: 2.0.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -12516,7 +12531,7 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-compilation-targets': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -13266,7 +13281,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.24.7 '@babel/types': 7.24.7 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -13661,7 +13676,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -13891,7 +13906,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -14541,7 +14556,7 @@ snapshots: '@opensearch-project/opensearch@2.10.0': dependencies: aws4: 1.13.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) hpagent: 1.2.0 json11: 1.1.2 ms: 2.1.3 @@ -14834,6 +14849,8 @@ snapshots: jsprim: 1.4.2 sshpk: 1.18.0 + '@phc/format@1.0.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -16835,7 +16852,7 @@ snapshots: '@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.3.3) '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.11.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.53.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -16855,7 +16872,7 @@ snapshots: '@typescript-eslint/type-utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -16875,7 +16892,7 @@ snapshots: '@typescript-eslint/type-utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -16893,7 +16910,7 @@ snapshots: '@typescript-eslint/types': 6.11.0 '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.11.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.53.0 optionalDependencies: typescript: 5.3.3 @@ -16906,7 +16923,7 @@ snapshots: '@typescript-eslint/types': 7.1.0 '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 optionalDependencies: typescript: 5.3.3 @@ -16919,7 +16936,7 @@ snapshots: '@typescript-eslint/types': 7.7.1 '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 optionalDependencies: typescript: 5.4.5 @@ -16950,7 +16967,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.3.3) - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.53.0 ts-api-utils: 1.3.0(typescript@5.3.3) optionalDependencies: @@ -16962,7 +16979,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.3.3) optionalDependencies: @@ -16974,7 +16991,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: @@ -16994,7 +17011,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.2 @@ -17008,7 +17025,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.11.0 '@typescript-eslint/visitor-keys': 6.11.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.2 @@ -17022,7 +17039,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.1.0 '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17037,7 +17054,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.7.1 '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 @@ -17452,13 +17469,13 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color agent-base@7.1.1: dependencies: - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -17571,6 +17588,12 @@ snapshots: arg@5.0.2: {} + argon2@0.40.3: + dependencies: + '@phc/format': 1.0.0 + node-addon-api: 8.1.0 + node-gyp-build: 4.8.1 + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -18833,7 +18856,7 @@ snapshots: detect-port@1.6.1: dependencies: address: 1.2.2 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -19080,7 +19103,7 @@ snapshots: esbuild-register@3.5.0(esbuild@0.20.2): dependencies: - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) esbuild: 0.20.2 transitivePeerDependencies: - supports-color @@ -19377,7 +19400,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -19420,7 +19443,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -20400,14 +20423,14 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -20446,14 +20469,14 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.4: dependencies: agent-base: 7.1.1 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -20561,7 +20584,7 @@ snapshots: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -20826,7 +20849,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -21963,7 +21986,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -22259,6 +22282,8 @@ snapshots: node-addon-api@3.2.1: optional: true + node-addon-api@8.1.0: {} + node-bitmap@0.0.1: {} node-dir@0.1.17: @@ -22294,8 +22319,7 @@ snapshots: detect-libc: 2.0.3 optional: true - node-gyp-build@4.8.1: - optional: true + node-gyp-build@4.8.1: {} node-gyp@10.1.0: dependencies: @@ -23596,7 +23620,7 @@ snapshots: require-in-the-middle@7.3.0: dependencies: - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -23654,7 +23678,7 @@ snapshots: retry-request@5.0.2: dependencies: - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) extend: 3.0.2 transitivePeerDependencies: - supports-color @@ -23906,7 +23930,7 @@ snapshots: dependencies: '@hapi/hoek': 10.0.1 '@hapi/wreck': 18.1.0 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) joi: 17.13.3 transitivePeerDependencies: - supports-color @@ -24004,7 +24028,7 @@ snapshots: socks-proxy-agent@8.0.3: dependencies: agent-base: 7.1.1 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -24655,7 +24679,7 @@ snapshots: chalk: 4.1.2 cli-highlight: 2.1.11 dayjs: 1.11.11 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) dotenv: 16.4.5 glob: 10.3.12 mkdirp: 2.1.6 @@ -24862,7 +24886,7 @@ snapshots: vite-node@0.34.6(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3): dependencies: cac: 6.7.14 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) mlly: 1.7.1 pathe: 1.1.2 picocolors: 1.0.1 @@ -24911,7 +24935,7 @@ snapshots: acorn-walk: 8.3.3 cac: 6.7.14 chai: 4.4.1 - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) local-pkg: 0.4.3 magic-string: 0.30.10 pathe: 1.1.2 @@ -24997,7 +25021,7 @@ snapshots: vue-eslint-parser@9.4.2(eslint@8.57.0): dependencies: - debug: 4.3.5(supports-color@5.5.0) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 From 715f05d8591d0d7acb27705df9a92e02ccefbbff Mon Sep 17 00:00:00 2001 From: Esurio Date: Sun, 14 Jul 2024 10:36:16 +0000 Subject: [PATCH 2/4] feat: argon2 support --- packages/backend/src/core/CreateSystemUserService.ts | 1 - packages/backend/src/core/SignupService.ts | 1 - packages/backend/src/server/api/SigninApiService.ts | 2 -- packages/backend/src/server/api/SignupApiService.ts | 2 -- .../backend/src/server/api/endpoints/admin/reset-password.ts | 1 - packages/backend/src/server/api/endpoints/i/2fa/key-done.ts | 4 ++-- .../backend/src/server/api/endpoints/i/2fa/register-key.ts | 4 ++-- packages/backend/src/server/api/endpoints/i/2fa/register.ts | 4 ++-- packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts | 4 ++-- packages/backend/src/server/api/endpoints/i/2fa/unregister.ts | 4 ++-- .../backend/src/server/api/endpoints/i/change-password.ts | 1 - packages/backend/src/server/api/endpoints/i/delete-account.ts | 3 +-- .../backend/src/server/api/endpoints/i/regenerate-token.ts | 3 ++- packages/backend/src/server/api/endpoints/i/update-email.ts | 4 ++-- packages/backend/src/server/api/endpoints/reset-password.ts | 1 - 15 files changed, 15 insertions(+), 24 deletions(-) diff --git a/packages/backend/src/core/CreateSystemUserService.ts b/packages/backend/src/core/CreateSystemUserService.ts index 0cea8c5170..e38c7b39cb 100644 --- a/packages/backend/src/core/CreateSystemUserService.ts +++ b/packages/backend/src/core/CreateSystemUserService.ts @@ -5,7 +5,6 @@ import { randomUUID } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; -import bcrypt from 'bcryptjs'; import { hashPassword } from '@/misc/password.js'; import { IsNull, DataSource } from 'typeorm'; import { genRsaKeyPair } from '@/misc/gen-key-pair.js'; diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts index 365a6b75c5..79d2543928 100644 --- a/packages/backend/src/core/SignupService.ts +++ b/packages/backend/src/core/SignupService.ts @@ -5,7 +5,6 @@ import { generateKeyPair } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; -import bcrypt from 'bcryptjs'; import { hashPassword } from '@/misc/password.js'; import { DataSource, IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts index 95120ce8e0..7c1bd942b1 100644 --- a/packages/backend/src/server/api/SigninApiService.ts +++ b/packages/backend/src/server/api/SigninApiService.ts @@ -4,8 +4,6 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import bcrypt from 'bcryptjs'; -import * as argon from 'argon2'; import { comparePassword, hashPassword, isOldAlgorithm } from '@/misc/password.js'; import * as OTPAuth from 'otpauth'; import { IsNull } from 'typeorm'; diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index 39bbfd5c19..e5fa1fea3f 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -4,8 +4,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, MiRegistrationTicket } from '@/models/_.js'; 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 30d827eab0..9d24302557 100644 --- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts @@ -4,7 +4,6 @@ */ import { Inject, Injectable } from '@nestjs/common'; -import bcrypt from 'bcryptjs'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; 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 65eece5b97..b03a3d0d54 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 @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -86,7 +86,7 @@ export default class extends Endpoint { } } - const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + const passwordMatched = await comparePassword(ps.password, profile.password ?? ''); if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } 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 9391aee5e0..ad3f3351e4 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 @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository } from '@/models/_.js'; @@ -217,7 +217,7 @@ export default class extends Endpoint { } } - const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + const passwordMatched = await comparePassword(ps.password, profile.password ?? ''); if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } 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 a54c598213..1d71cc7434 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import * as OTPAuth from 'otpauth'; import * as QRCode from 'qrcode'; import { Inject, Injectable } from '@nestjs/common'; @@ -77,7 +77,7 @@ export default class extends Endpoint { // eslint- } } - const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + const passwordMatched = await comparePassword(ps.password, profile.password ?? ''); if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } 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 c350136eae..e830fffa94 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 @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; @@ -66,7 +66,7 @@ export default class extends Endpoint { // eslint- } } - const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + const passwordMatched = await comparePassword(ps.password, profile.password ?? ''); if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } 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 b5a53cc889..900aeb55bc 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -62,7 +62,7 @@ export default class extends Endpoint { // eslint- } } - const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? ''); + const passwordMatched = await comparePassword(ps.password, profile.password ?? ''); if (!passwordMatched) { throw new ApiError(meta.errors.incorrectPassword); } 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 0cad5b5a0e..4dca633610 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; import { hashPassword, comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; 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 82578ea2fc..4da8920a66 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; @@ -60,7 +59,7 @@ export default class extends Endpoint { // eslint- return; } - const passwordMatched = await bcrypt.compare(ps.password, profile.password!); + const passwordMatched = await comparePassword(ps.password, profile.password!); if (!passwordMatched) { 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 78f3cce9ad..ea005e56d4 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -4,6 +4,7 @@ */ import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository, UserProfilesRepository } from '@/models/_.js'; @@ -43,7 +44,7 @@ export default class extends Endpoint { // eslint- const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.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 eea657ebbd..98b73b44c5 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; -import bcrypt from 'bcryptjs'; +import { comparePassword } from '@/misc/password.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -95,7 +95,7 @@ export default class extends Endpoint { // eslint- } } - const passwordMatched = await bcrypt.compare(ps.password, profile.password!); + const passwordMatched = await comparePassword(ps.password, profile.password!); if (!passwordMatched) { 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 44afddf0e9..4f2cfbc958 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; import { hashPassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/_.js'; From 70545473c349d546eeb6143d822b91074706ae26 Mon Sep 17 00:00:00 2001 From: Esurio Date: Sun, 14 Jul 2024 10:36:30 +0000 Subject: [PATCH 3/4] remove unused import --- packages/backend/src/server/api/endpoints/i/regenerate-token.ts | 1 - 1 file changed, 1 deletion(-) 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 ea005e56d4..938aa98a95 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import bcrypt from 'bcryptjs'; import { comparePassword } from '@/misc/password.js'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; From 12ad1f329e370cd72ba5c4c7ac3642d27c605d9d Mon Sep 17 00:00:00 2001 From: Esurio Date: Sun, 14 Jul 2024 10:38:40 +0000 Subject: [PATCH 4/4] Update CHANGELOG --- CHANGELOG_engawa.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG_engawa.md b/CHANGELOG_engawa.md index 70a8a5e386..0a9c1bb27e 100644 --- a/CHANGELOG_engawa.md +++ b/CHANGELOG_engawa.md @@ -16,6 +16,22 @@ --> +## 0.4.3 (unreleased) + +### Release Date + +### General +- パスワードのハッシュでArgon2idをサポート + - bcryptによるハッシュは再ログイン時にArgon2idに置き換えられます + +### Client +- + +### Server +- + +### Misc + ## 0.4.2 ### Release Date