Skip to content

Commit

Permalink
Merge pull request #511
Browse files Browse the repository at this point in the history
enhance(backend): replace bcrypt with argon2
  • Loading branch information
noridev authored Oct 5, 2024
2 parents 301876c + 1da0023 commit 81920f1
Show file tree
Hide file tree
Showing 18 changed files with 95 additions and 38 deletions.
1 change: 1 addition & 0 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"accepts": "1.3.8",
"ajv": "8.17.1",
"archiver": "7.0.1",
"argon2": "^0.40.1",
"async-mutex": "0.5.0",
"bcryptjs": "2.4.3",
"blurhash": "2.0.5",
Expand Down
7 changes: 4 additions & 3 deletions packages/backend/src/core/CreateSystemUserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import { randomUUID } from 'node:crypto';
import { Inject, Injectable } from '@nestjs/common';
import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
//import bcrypt from 'bcryptjs';
import { IsNull, DataSource } from 'typeorm';
import { genRsaKeyPair } from '@/misc/gen-key-pair.js';
import { MiUser } from '@/models/User.js';
Expand All @@ -32,8 +33,8 @@ export class CreateSystemUserService {
const password = randomUUID();

// Generate hash of password
const salt = await bcrypt.genSalt(8);
const hash = await bcrypt.hash(password, salt);
//const salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(password);

// Generate secret
const secret = generateNativeUserToken();
Expand Down
7 changes: 4 additions & 3 deletions packages/backend/src/core/SignupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import { generateKeyPair } from 'node:crypto';
import { Inject, Injectable } from '@nestjs/common';
import bcrypt from 'bcryptjs';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { DataSource, IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { MiMeta, UsedUsernamesRepository, UsersRepository } from '@/models/_.js';
Expand Down Expand Up @@ -69,8 +70,8 @@ export class SignupService {
}

// Generate hash of password
const salt = await bcrypt.genSalt(8);
hash = await bcrypt.hash(password, salt);
//const salt = await bcrypt.genSalt(8);
hash = await argon2.hash(password);
}

// Generate secret
Expand Down
15 changes: 14 additions & 1 deletion packages/backend/src/server/api/SigninApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

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';
Expand Down Expand Up @@ -123,7 +124,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 = await argon2.verify(profile.password!, password) || bcrypt.compareSync(password, profile.password!);

const fail = async (status?: number, failure?: { id: string }) => {
// Append signin history
Expand All @@ -140,6 +141,12 @@ export class SigninApiService {

if (!profile.twoFactorEnabled) {
if (same) {
if (profile.password!.startsWith('$2')) {
const newHash = await argon2.hash(password);
this.userProfilesRepository.update(user.id, {
password: newHash
});
}
return this.signinService.signin(request, reply, user);
} else {
return await fail(403, {
Expand All @@ -156,6 +163,12 @@ export class SigninApiService {
}

try {
if (profile.password!.startsWith('$2')) {
const newHash = await argon2.hash(password);
this.userProfilesRepository.update(user.id, {
password: newHash
});
}
await this.userAuthService.twoFactorAuthenticate(profile, token);
} catch (e) {
return await fail(403, {
Expand Down
7 changes: 4 additions & 3 deletions packages/backend/src/server/api/SignupApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
*/

import { Inject, Injectable } from '@nestjs/common';
import bcrypt from 'bcryptjs';
//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, MiMeta } from '@/models/_.js';
Expand Down Expand Up @@ -179,8 +180,8 @@ 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 salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(password);

const pendingUser = await this.userPendingsRepository.insertOne({
id: this.idService.gen(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
*/

import { Inject, Injectable } from '@nestjs/common';
import bcrypt from 'bcryptjs';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { UsersRepository, UserProfilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
Expand Down Expand Up @@ -65,7 +66,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const passwd = secureRndstr(8);

// Generate hash of password
const hash = bcrypt.hashSync(passwd);
const hash = await argon2.hash(passwd);

await this.userProfilesRepository.update({
userId: user.id,
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//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';
Expand Down Expand Up @@ -85,7 +86,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}
}

const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? '');
const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//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/_.js';
Expand Down Expand Up @@ -216,7 +217,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}
}

const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? '');
const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/server/api/endpoints/i/2fa/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//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';
Expand Down Expand Up @@ -77,7 +78,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}

const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? '');
const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//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/_.js';
Expand Down Expand Up @@ -66,7 +67,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}

const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? '');
const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//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';
Expand Down Expand Up @@ -62,7 +63,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}

const passwordMatched = await bcrypt.compare(ps.password, profile.password ?? '');
const passwordMatched = await argon2.verify(profile.password ?? '', ps.password);
if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//import bcrypt from 'bcryptjs';
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { UserSecurityKeysRepository } from '@/models/_.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//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/_.js';
Expand Down Expand Up @@ -50,15 +51,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}

const passwordMatched = await bcrypt.compare(ps.currentPassword, profile.password!);
const passwordMatched = await argon2.verify(profile.password!, ps.currentPassword);

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 salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(ps.newPassword);

await this.userProfilesRepository.update(me.id, {
password: hash,
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/server/api/endpoints/i/delete-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import type { UsersRepository, UserProfilesRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
Expand Down Expand Up @@ -59,7 +60,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return;
}

const passwordMatched = await bcrypt.compare(ps.password, profile.password!);
const passwordMatched = await argon2.verify(profile.password!, ps.password);
if (!passwordMatched) {
throw new Error('incorrect password');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//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/_.js';
Expand Down Expand Up @@ -43,7 +44,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });

// Compare password
const same = await bcrypt.compare(ps.password, profile.password!);
const same = await argon2.verify(profile.password!, ps.password);

if (!same) {
throw new Error('incorrect password');
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/server/api/endpoints/i/update-email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import { Inject, Injectable } from '@nestjs/common';
import ms from 'ms';
import bcrypt from 'bcryptjs';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { MiMeta, UserProfilesRepository } from '@/models/_.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
Expand Down Expand Up @@ -96,7 +97,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}

const passwordMatched = await bcrypt.compare(ps.password, profile.password!);
const passwordMatched = await argon2.verify(profile.password!, ps.password);
if (!passwordMatched) {
throw new ApiError(meta.errors.incorrectPassword);
}
Expand Down
7 changes: 4 additions & 3 deletions packages/backend/src/server/api/endpoints/reset-password.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import bcrypt from 'bcryptjs';
//import bcrypt from 'bcryptjs';
import * as argon2 from 'argon2';
import { Inject, Injectable } from '@nestjs/common';
import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
Expand Down Expand Up @@ -53,8 +54,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}

// Generate hash of password
const salt = await bcrypt.genSalt(8);
const hash = await bcrypt.hash(ps.password, salt);
//const salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(ps.password);

await this.userProfilesRepository.update(req.userId, {
password: hash,
Expand Down
Loading

0 comments on commit 81920f1

Please sign in to comment.