From 4b48d525042e92bc926aee54644e3ec2f1ba03bf Mon Sep 17 00:00:00 2001 From: sup39 Date: Mon, 29 Jan 2024 03:18:55 +0900 Subject: [PATCH] refactor: move misc/password.ts to backend-rs --- neko/index.js | 5 +- packages/backend-rs/Cargo.lock | 112 +++++++++++++++--- packages/backend-rs/Cargo.toml | 2 + packages/backend-rs/src/lib.rs | 1 + packages/backend-rs/src/prelude.rs | 3 + packages/backend-rs/src/util/mod.rs | 1 + packages/backend-rs/src/util/password.rs | 37 ++++++ packages/backend/package.json | 3 - packages/backend/src/misc/password.ts | 20 ---- .../backend/src/server/api/common/signup.ts | 2 +- .../api/endpoints/admin/reset-password.ts | 4 +- .../server/api/endpoints/i/2fa/key-done.ts | 4 +- .../api/endpoints/i/2fa/register-key.ts | 4 +- .../server/api/endpoints/i/2fa/register.ts | 4 +- .../server/api/endpoints/i/2fa/remove-key.ts | 4 +- .../server/api/endpoints/i/2fa/unregister.ts | 4 +- .../server/api/endpoints/i/change-password.ts | 4 +- .../server/api/endpoints/i/delete-account.ts | 4 +- .../api/endpoints/i/regenerate-token.ts | 4 +- .../server/api/endpoints/i/update-email.ts | 4 +- .../server/api/endpoints/reset-password.ts | 2 +- .../backend/src/server/api/private/signin.ts | 10 +- .../backend/src/server/api/private/signup.ts | 2 +- .../src/services/create-system-user.ts | 2 +- pnpm-lock.yaml | 51 ++------ 25 files changed, 182 insertions(+), 111 deletions(-) create mode 100644 packages/backend-rs/src/prelude.rs create mode 100644 packages/backend-rs/src/util/password.rs delete mode 100644 packages/backend/src/misc/password.ts diff --git a/neko/index.js b/neko/index.js index b25acfb6..27e1e6cb 100644 --- a/neko/index.js +++ b/neko/index.js @@ -295,7 +295,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { EnvConfig, readEnvironmentConfig, readServerConfig, JsDbConn, connectToDatabase, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, stringToAcct, acctToString, getFullApAccount, isSelfHost, extractHost, toPuny, toPunyOptional, convertToHiddenPost, sqlLikeEscape, safeForSql, formatMilliseconds, nativeInitIdGenerator, nativeCreateId, nativeGetTimestamp, fetchMeta, metaToPugArgs, hasOtherRenoteOfThisNote, nyaify, genString, IdConvertType, convertId } = nativeBinding +const { EnvConfig, readEnvironmentConfig, readServerConfig, JsDbConn, connectToDatabase, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, stringToAcct, acctToString, getFullApAccount, isSelfHost, extractHost, toPuny, toPunyOptional, convertToHiddenPost, sqlLikeEscape, safeForSql, formatMilliseconds, nativeInitIdGenerator, nativeCreateId, nativeGetTimestamp, fetchMeta, metaToPugArgs, hasOtherRenoteOfThisNote, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, genString, IdConvertType, convertId } = nativeBinding module.exports.EnvConfig = EnvConfig module.exports.readEnvironmentConfig = readEnvironmentConfig @@ -330,6 +330,9 @@ module.exports.fetchMeta = fetchMeta module.exports.metaToPugArgs = metaToPugArgs module.exports.hasOtherRenoteOfThisNote = hasOtherRenoteOfThisNote module.exports.nyaify = nyaify +module.exports.hashPassword = hashPassword +module.exports.verifyPassword = verifyPassword +module.exports.isOldPasswordAlgorithm = isOldPasswordAlgorithm module.exports.genString = genString module.exports.IdConvertType = IdConvertType module.exports.convertId = convertId diff --git a/packages/backend-rs/Cargo.lock b/packages/backend-rs/Cargo.lock index 4e6fea19..40993fa8 100644 --- a/packages/backend-rs/Cargo.lock +++ b/packages/backend-rs/Cargo.lock @@ -132,6 +132,18 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash", +] + [[package]] name = "arrayvec" version = "0.7.4" @@ -200,8 +212,10 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" name = "backend-rs" version = "0.0.0" dependencies = [ + "argon2", "async-trait", "basen", + "bcrypt", "cfg-if", "chrono", "cuid2", @@ -259,6 +273,19 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dbe4bb73fd931c4d1aaf53b35d1286c8a948ad00ec92c8e3c856f15fd027f43" +[[package]] +name = "bcrypt" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d1c9c15093eb224f0baa400f38fcd713fc1391a6f1c389d886beef146d60a3" +dependencies = [ + "base64", + "blowfish", + "getrandom", + "subtle", + "zeroize", +] + [[package]] name = "bigdecimal" version = "0.3.1" @@ -312,6 +339,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -321,6 +357,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blowfish" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" +dependencies = [ + "byteorder", + "cipher", +] + [[package]] name = "borsh" version = "1.3.1" @@ -414,9 +460,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -427,6 +473,16 @@ dependencies = [ "windows-targets 0.52.0", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.4.18" @@ -1081,6 +1137,15 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1273,9 +1338,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.14.4" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "902495f6b80f53f8435aefbbd2241c9c675fa239cd7e5f8e28fb57f3b69ecd09" +checksum = "efbf98e1bcb85cc441bbf7cdfb11070d2537a100e2697d75397b2584c32492d1" dependencies = [ "bitflags 2.4.2", "chrono", @@ -1296,9 +1361,9 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.14.6" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61bec1ee990ae3e9a5f443484c65fb38e571a898437f0ad283ed69c82fc59c0" +checksum = "7622f0dbe0968af2dacdd64870eee6dee94f93c989c841f1ad8f300cf1abd514" dependencies = [ "cfg-if", "convert_case", @@ -1310,9 +1375,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2314f777bc9cde51705d991c44466cee4de4a3f41c6d3d019fcbbebb5cdd47c4" +checksum = "8ec514d65fce18a959be55e7f683ac89c6cb850fb59b09e25ab777fd5a4a8d9e" dependencies = [ "convert_case", "once_cell", @@ -1560,6 +1625,17 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + [[package]] name = "paste" version = "1.0.14" @@ -1772,9 +1848,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -2114,18 +2190,18 @@ checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -2145,9 +2221,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed" dependencies = [ "itoa", "ryu", @@ -3169,9 +3245,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.34" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index 1c2b5ef5..3e66beb2 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -35,6 +35,8 @@ napi = { version = "2.14.4", default-features = false, features = ["napi9", "tok napi-derive = { version = "2.14.6", optional = true } basen = "0.1.0" urlencoding = "2.1.3" +argon2 = "0.5.3" +bcrypt = "0.15.0" [dev-dependencies] pretty_assertions = "1.4.0" diff --git a/packages/backend-rs/src/lib.rs b/packages/backend-rs/src/lib.rs index 2c57743e..e6ec2545 100644 --- a/packages/backend-rs/src/lib.rs +++ b/packages/backend-rs/src/lib.rs @@ -2,6 +2,7 @@ pub mod config; pub mod database; pub mod macros; pub mod model; +pub mod prelude; pub mod util; // #[cfg(feature = "napi")] diff --git a/packages/backend-rs/src/prelude.rs b/packages/backend-rs/src/prelude.rs new file mode 100644 index 00000000..4ae9ae36 --- /dev/null +++ b/packages/backend-rs/src/prelude.rs @@ -0,0 +1,3 @@ +pub fn to_napi_error(err: E) -> napi::Error { + napi::Error::from_reason(err.to_string()) +} diff --git a/packages/backend-rs/src/util/mod.rs b/packages/backend-rs/src/util/mod.rs index 50fab5e0..01102afa 100644 --- a/packages/backend-rs/src/util/mod.rs +++ b/packages/backend-rs/src/util/mod.rs @@ -7,4 +7,5 @@ pub mod id; pub mod meta; pub mod note; pub mod nyaify; +pub mod password; pub mod random; diff --git a/packages/backend-rs/src/util/password.rs b/packages/backend-rs/src/util/password.rs new file mode 100644 index 00000000..34415bed --- /dev/null +++ b/packages/backend-rs/src/util/password.rs @@ -0,0 +1,37 @@ +use crate::prelude::to_napi_error; +use argon2::{ + password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, + Argon2, +}; + +#[napi_derive::napi] +pub async fn hash_password(password: String) -> napi::Result { + let salt = SaltString::generate(&mut OsRng); + Argon2::default() + .hash_password(password.as_bytes(), &salt) + .map(|s| s.to_string()) + .map_err(to_napi_error) +} + +#[napi_derive::napi] +pub async fn verify_password(password: String, hash: String) -> napi::Result { + if _is_old_password_algorithm(&hash) { + bcrypt::verify(&password, &hash).map_err(to_napi_error) + } else { + let parsed_hash = PasswordHash::new(&hash).map_err(to_napi_error)?; + Ok(Argon2::default() + .verify_password(password.as_bytes(), &parsed_hash) + .is_ok()) + } +} + +#[inline] +fn _is_old_password_algorithm(hash: &str) -> bool { + // bcrypt hashes start with $2[ab]$ + hash.starts_with("$2") +} + +#[napi_derive::napi] +pub fn is_old_password_algorithm(hash: String) -> bool { + _is_old_password_algorithm(&hash) +} diff --git a/packages/backend/package.json b/packages/backend/package.json index 29a7d0b8..4261ac8a 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -34,11 +34,9 @@ "adm-zip": "^0.5.10", "ajv": "8.12.0", "archiver": "6.0.1", - "argon2": "^0.31.2", "aws-sdk": "2.1542.0", "axios": "1.6.5", "backend-rs": "workspace:*", - "bcryptjs": "2.4.3", "blurhash": "2.0.5", "bull": "4.12.2", "cacheable-lookup": "TheEssem/cacheable-lookup", @@ -128,7 +126,6 @@ "@swc/cli": "0.1.65", "@swc/core": "1.3.105", "@types/adm-zip": "0.5.5", - "@types/bcryptjs": "2.4.6", "@types/escape-regexp": "0.0.3", "@types/fluent-ffmpeg": "2.1.24", "@types/js-yaml": "4.0.9", diff --git a/packages/backend/src/misc/password.ts b/packages/backend/src/misc/password.ts deleted file mode 100644 index c63f89f5..00000000 --- a/packages/backend/src/misc/password.ts +++ /dev/null @@ -1,20 +0,0 @@ -import bcrypt from "bcryptjs"; -import * as argon2 from "argon2"; - -export async function hashPassword(password: string): Promise { - return argon2.hash(password); -} - -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 { - // bcrypt hashes start with $2[ab]$ - return hash.startsWith("$2"); -} diff --git a/packages/backend/src/server/api/common/signup.ts b/packages/backend/src/server/api/common/signup.ts index 9a2e141f..5bec9d27 100644 --- a/packages/backend/src/server/api/common/signup.ts +++ b/packages/backend/src/server/api/common/signup.ts @@ -10,7 +10,7 @@ import { UserKeypair } from "@/models/entities/user-keypair.js"; import { UsedUsername } from "@/models/entities/used-username.js"; import { db } from "@/db/postgre.js"; import config from "@/config/index.js"; -import { hashPassword } from "@/misc/password.js"; +import { hashPassword } from "backend-rs"; export async function signup(opts: { username: User["username"]; 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 5fbed130..934e2dd3 100644 --- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts @@ -1,8 +1,7 @@ import define from "@/server/api/define.js"; -// import bcrypt from "bcryptjs"; import rndstr from "rndstr"; import { Users, UserProfiles } from "@/models/index.js"; -import { hashPassword } from "@/misc/password.js"; +import { hashPassword } from "backend-rs"; export const meta = { tags: ["admin"], @@ -48,7 +47,6 @@ export default define(meta, paramDef, async (ps) => { const passwd = rndstr("a-zA-Z0-9", 8); // Generate hash of password - // const hash = bcrypt.hashSync(passwd); const hash = await hashPassword(passwd); await UserProfiles.update( 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 b8104e31..5031a88e 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 @@ -9,7 +9,7 @@ import { import config from "@/config/index.js"; import { procedures, hash } from "@/server/api/2fa.js"; import { publishMainStream } from "@/services/stream.js"; -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; const rpIdHashReal = hash(Buffer.from(config.hostname, "utf-8")); @@ -41,7 +41,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(ps.password, profile.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 8080c939..b366c4ab 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 @@ -4,7 +4,7 @@ import { promisify } from "node:util"; import * as crypto from "node:crypto"; import { genId } from "@/misc/gen-id.js"; import { hash } from "@/server/api/2fa.js"; -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; const randomBytes = promisify(crypto.randomBytes); @@ -26,7 +26,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(ps.password, profile.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 52e1df39..1ac67837 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 @@ import * as QRCode from "qrcode"; import config from "@/config/index.js"; import { UserProfiles } from "@/models/index.js"; import define from "@/server/api/define.js"; -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; export const meta = { requireCredential: true, @@ -23,7 +23,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); 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 b3bc5bdf..582242b2 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,4 @@ -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; import define from "@/server/api/define.js"; import { UserProfiles, UserSecurityKeys, Users } from "@/models/index.js"; import { publishMainStream } from "@/services/stream.js"; @@ -22,7 +22,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(ps.password, profile.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 c4e78eec..4f5f0ae2 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -1,7 +1,7 @@ import { publishMainStream } from "@/services/stream.js"; import define from "@/server/api/define.js"; import { Users, UserProfiles } from "@/models/index.js"; -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; export const meta = { requireCredential: true, @@ -21,7 +21,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(ps.password, profile.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 b0dc8bba..a5e6d1b9 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -1,6 +1,6 @@ import define from "@/server/api/define.js"; import { UserProfiles } from "@/models/index.js"; -import { hashPassword, comparePassword } from "@/misc/password.js"; +import { hashPassword, verifyPassword } from "backend-rs"; export const meta = { requireCredential: true, @@ -21,7 +21,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.currentPassword, profile.password!); + const same = await verifyPassword(ps.currentPassword, profile.password!); if (!same) { throw new Error("incorrect password"); 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 606cde82..04aed49e 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -1,7 +1,7 @@ import { UserProfiles, Users } from "@/models/index.js"; import { deleteAccount } from "@/services/delete-account.js"; import define from "@/server/api/define.js"; -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; export const meta = { requireCredential: true, @@ -25,7 +25,7 @@ export default define(meta, paramDef, async (ps, user) => { } // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(ps.password, profile.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 c1b4325a..78cc3622 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -6,7 +6,7 @@ import { import generateUserToken from "@/server/api/common/generate-native-user-token.js"; import define from "@/server/api/define.js"; import { Users, UserProfiles } from "@/models/index.js"; -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; export const meta = { requireCredential: true, @@ -29,7 +29,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(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 a48252ed..9920d79c 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -7,7 +7,7 @@ import { sendEmail } from "@/services/send-email.js"; import { ApiError } from "@/server/api/error.js"; import { validateEmailForAccount } from "@/services/validate-email-for-account.js"; import { HOUR } from "@/const.js"; -import { comparePassword } from "@/misc/password.js"; +import { verifyPassword } from "backend-rs"; export const meta = { requireCredential: true, @@ -47,7 +47,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(ps.password, profile.password!); + const same = await verifyPassword(ps.password, profile.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 ff5c8d98..d2295cff 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -1,6 +1,6 @@ import { UserProfiles, PasswordResetRequests } from "@/models/index.js"; import define from "@/server/api/define.js"; -import { hashPassword } from "@/misc/password.js"; +import { hashPassword } from "backend-rs"; export const meta = { tags: ["reset password"], diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index 14d8b5b9..23ec32df 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -12,10 +12,10 @@ import { import type { ILocalUser } from "@/models/entities/user.js"; import { genId } from "@/misc/gen-id.js"; import { - comparePassword, + verifyPassword, hashPassword, - isOldAlgorithm, -} from "@/misc/password.js"; + isOldPasswordAlgorithm, +} from "backend-rs"; import { verifyLogin, hash } from "@/server/api/2fa.js"; import { randomBytes } from "node:crypto"; import { IsNull } from "typeorm"; @@ -92,9 +92,9 @@ export default async (ctx: Koa.Context) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await comparePassword(password, profile.password!); + const same = await verifyPassword(password, profile.password!); - if (same && isOldAlgorithm(profile.password!)) { + if (same && isOldPasswordAlgorithm(profile.password!)) { profile.password = await hashPassword(password); await UserProfiles.save(profile); } diff --git a/packages/backend/src/server/api/private/signup.ts b/packages/backend/src/server/api/private/signup.ts index ea80badc..a2df9468 100644 --- a/packages/backend/src/server/api/private/signup.ts +++ b/packages/backend/src/server/api/private/signup.ts @@ -8,7 +8,7 @@ import config from "@/config/index.js"; import { sendEmail } from "@/services/send-email.js"; import { genId } from "@/misc/gen-id.js"; import { validateEmailForAccount } from "@/services/validate-email-for-account.js"; -import { hashPassword } from "@/misc/password.js"; +import { hashPassword } from "backend-rs"; export default async (ctx: Koa.Context) => { const body = ctx.request.body; diff --git a/packages/backend/src/services/create-system-user.ts b/packages/backend/src/services/create-system-user.ts index 0ebd1142..e644c3e7 100644 --- a/packages/backend/src/services/create-system-user.ts +++ b/packages/backend/src/services/create-system-user.ts @@ -8,7 +8,7 @@ import { genId } from "@/misc/gen-id.js"; import { UserKeypair } from "@/models/entities/user-keypair.js"; import { UsedUsername } from "@/models/entities/used-username.js"; import { db } from "@/db/postgre.js"; -import { hashPassword } from "@/misc/password.js"; +import { hashPassword } from "backend-rs"; export async function createSystemUser(username: string) { const password = uuid(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e3be0de..96a61e53 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,9 +108,6 @@ importers: archiver: specifier: 6.0.1 version: 6.0.1 - argon2: - specifier: ^0.31.2 - version: 0.31.2 aws-sdk: specifier: 2.1542.0 version: 2.1542.0 @@ -120,9 +117,6 @@ importers: backend-rs: specifier: workspace:* version: link:../backend-rs - bcryptjs: - specifier: 2.4.3 - version: 2.4.3 blurhash: specifier: 2.0.5 version: 2.0.5 @@ -389,9 +383,6 @@ importers: '@types/adm-zip': specifier: 0.5.5 version: 0.5.5 - '@types/bcryptjs': - specifier: 2.4.6 - version: 2.4.6 '@types/escape-regexp': specifier: 0.0.3 version: 0.0.3 @@ -2917,6 +2908,7 @@ packages: transitivePeerDependencies: - encoding - supports-color + dev: true /@microsoft/tsdoc-config@0.16.2: resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} @@ -3058,11 +3050,6 @@ packages: sshpk: 1.18.0 dev: false - /@phc/format@1.0.0: - resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==} - engines: {node: '>=10'} - dev: false - /@phosphor-icons/web@2.0.3: resolution: {integrity: sha512-9oYmohi2fo87w3DbtfjBoJxrklVojgXq2wuGcqxKccj2TxMq7UIusKDrGUZYOQHM9pUKkh+kvfmutETMGDR6gg==} dev: true @@ -3537,10 +3524,6 @@ packages: '@babel/types': 7.23.3 dev: true - /@types/bcryptjs@2.4.6: - resolution: {integrity: sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==} - dev: true - /@types/body-parser@1.19.5: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: @@ -4700,6 +4683,7 @@ packages: /abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} requiresBuild: true + dev: true /abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} @@ -4920,6 +4904,7 @@ packages: /aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} requiresBuild: true + dev: true /arch@2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} @@ -4966,23 +4951,11 @@ packages: dependencies: delegates: 1.0.0 readable-stream: 3.6.2 + dev: true /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - /argon2@0.31.2: - resolution: {integrity: sha512-QSnJ8By5Mth60IEte45w9Y7v6bWcQw3YhRtJKKN8oNCxnTLDiv/AXXkDPf2srTMfxFVn3QJdVv2nhXESsUa+Yg==} - engines: {node: '>=14.0.0'} - requiresBuild: true - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - '@phc/format': 1.0.0 - node-addon-api: 7.0.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} dependencies: @@ -5466,10 +5439,6 @@ packages: tweetnacl: 0.14.5 dev: false - /bcryptjs@2.4.3: - resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} - dev: false - /bin-check@4.1.0: resolution: {integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==} engines: {node: '>=4'} @@ -6455,6 +6424,7 @@ packages: /console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} requiresBuild: true + dev: true /consolidate@0.16.0(ejs@3.1.9)(pug@3.0.2): resolution: {integrity: sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==} @@ -9167,6 +9137,7 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wide-align: 1.1.5 + dev: true /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} @@ -9649,6 +9620,7 @@ packages: /has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} requiresBuild: true + dev: true /has-value@0.3.1: resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} @@ -11831,6 +11803,7 @@ packages: engines: {node: '>=8'} dependencies: semver: 6.3.1 + dev: true /make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -12359,10 +12332,6 @@ packages: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: false - /node-addon-api@7.0.0: - resolution: {integrity: sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==} - dev: false - /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -12450,6 +12419,7 @@ packages: hasBin: true dependencies: abbrev: 1.1.1 + dev: true /nopt@7.2.0: resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} @@ -12547,6 +12517,7 @@ packages: console-control-strings: 1.1.0 gauge: 3.0.2 set-blocking: 2.0.0 + dev: true /nth-check@1.0.2: resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==} @@ -14672,6 +14643,7 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -16619,6 +16591,7 @@ packages: requiresBuild: true dependencies: string-width: 4.2.3 + dev: true /with@7.0.2: resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==}