refactor: move misc/password.ts to backend-rs

This commit is contained in:
sup39 2024-01-29 03:18:55 +09:00 committed by naskya
parent 7bf2652044
commit 4b48d52504
Signed by: naskya
GPG key ID: 712D413B3A9FED5C
25 changed files with 182 additions and 111 deletions

View file

@ -295,7 +295,7 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`) 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.EnvConfig = EnvConfig
module.exports.readEnvironmentConfig = readEnvironmentConfig module.exports.readEnvironmentConfig = readEnvironmentConfig
@ -330,6 +330,9 @@ module.exports.fetchMeta = fetchMeta
module.exports.metaToPugArgs = metaToPugArgs module.exports.metaToPugArgs = metaToPugArgs
module.exports.hasOtherRenoteOfThisNote = hasOtherRenoteOfThisNote module.exports.hasOtherRenoteOfThisNote = hasOtherRenoteOfThisNote
module.exports.nyaify = nyaify module.exports.nyaify = nyaify
module.exports.hashPassword = hashPassword
module.exports.verifyPassword = verifyPassword
module.exports.isOldPasswordAlgorithm = isOldPasswordAlgorithm
module.exports.genString = genString module.exports.genString = genString
module.exports.IdConvertType = IdConvertType module.exports.IdConvertType = IdConvertType
module.exports.convertId = convertId module.exports.convertId = convertId

View file

@ -132,6 +132,18 @@ version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" 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]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.7.4" version = "0.7.4"
@ -200,8 +212,10 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
name = "backend-rs" name = "backend-rs"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"argon2",
"async-trait", "async-trait",
"basen", "basen",
"bcrypt",
"cfg-if", "cfg-if",
"chrono", "chrono",
"cuid2", "cuid2",
@ -259,6 +273,19 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dbe4bb73fd931c4d1aaf53b35d1286c8a948ad00ec92c8e3c856f15fd027f43" 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]] [[package]]
name = "bigdecimal" name = "bigdecimal"
version = "0.3.1" version = "0.3.1"
@ -312,6 +339,15 @@ dependencies = [
"wyz", "wyz",
] ]
[[package]]
name = "blake2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
"digest",
]
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.4" version = "0.10.4"
@ -321,6 +357,16 @@ dependencies = [
"generic-array", "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]] [[package]]
name = "borsh" name = "borsh"
version = "1.3.1" version = "1.3.1"
@ -414,9 +460,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.32" version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
@ -427,6 +473,16 @@ dependencies = [
"windows-targets 0.52.0", "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]] [[package]]
name = "clap" name = "clap"
version = "4.4.18" version = "4.4.18"
@ -1081,6 +1137,15 @@ dependencies = [
"syn 2.0.48", "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]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.9.0" version = "2.9.0"
@ -1273,9 +1338,9 @@ dependencies = [
[[package]] [[package]]
name = "napi" name = "napi"
version = "2.14.4" version = "2.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "902495f6b80f53f8435aefbbd2241c9c675fa239cd7e5f8e28fb57f3b69ecd09" checksum = "efbf98e1bcb85cc441bbf7cdfb11070d2537a100e2697d75397b2584c32492d1"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.4.2",
"chrono", "chrono",
@ -1296,9 +1361,9 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df"
[[package]] [[package]]
name = "napi-derive" name = "napi-derive"
version = "2.14.6" version = "2.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e61bec1ee990ae3e9a5f443484c65fb38e571a898437f0ad283ed69c82fc59c0" checksum = "7622f0dbe0968af2dacdd64870eee6dee94f93c989c841f1ad8f300cf1abd514"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"convert_case", "convert_case",
@ -1310,9 +1375,9 @@ dependencies = [
[[package]] [[package]]
name = "napi-derive-backend" name = "napi-derive-backend"
version = "1.0.58" version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2314f777bc9cde51705d991c44466cee4de4a3f41c6d3d019fcbbebb5cdd47c4" checksum = "8ec514d65fce18a959be55e7f683ac89c6cb850fb59b09e25ab777fd5a4a8d9e"
dependencies = [ dependencies = [
"convert_case", "convert_case",
"once_cell", "once_cell",
@ -1560,6 +1625,17 @@ dependencies = [
"syn 2.0.48", "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]] [[package]]
name = "paste" name = "paste"
version = "1.0.14" version = "1.0.14"
@ -1772,9 +1848,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.4.4" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -2114,18 +2190,18 @@ checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.195" version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.195" version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2145,9 +2221,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.111" version = "1.0.112"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -3169,9 +3245,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.5.34" version = "0.5.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]

View file

@ -35,6 +35,8 @@ napi = { version = "2.14.4", default-features = false, features = ["napi9", "tok
napi-derive = { version = "2.14.6", optional = true } napi-derive = { version = "2.14.6", optional = true }
basen = "0.1.0" basen = "0.1.0"
urlencoding = "2.1.3" urlencoding = "2.1.3"
argon2 = "0.5.3"
bcrypt = "0.15.0"
[dev-dependencies] [dev-dependencies]
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"

View file

@ -2,6 +2,7 @@ pub mod config;
pub mod database; pub mod database;
pub mod macros; pub mod macros;
pub mod model; pub mod model;
pub mod prelude;
pub mod util; pub mod util;
// #[cfg(feature = "napi")] // #[cfg(feature = "napi")]

View file

@ -0,0 +1,3 @@
pub fn to_napi_error<E: ToString>(err: E) -> napi::Error {
napi::Error::from_reason(err.to_string())
}

View file

@ -7,4 +7,5 @@ pub mod id;
pub mod meta; pub mod meta;
pub mod note; pub mod note;
pub mod nyaify; pub mod nyaify;
pub mod password;
pub mod random; pub mod random;

View file

@ -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<String> {
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<bool> {
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)
}

View file

@ -34,11 +34,9 @@
"adm-zip": "^0.5.10", "adm-zip": "^0.5.10",
"ajv": "8.12.0", "ajv": "8.12.0",
"archiver": "6.0.1", "archiver": "6.0.1",
"argon2": "^0.31.2",
"aws-sdk": "2.1542.0", "aws-sdk": "2.1542.0",
"axios": "1.6.5", "axios": "1.6.5",
"backend-rs": "workspace:*", "backend-rs": "workspace:*",
"bcryptjs": "2.4.3",
"blurhash": "2.0.5", "blurhash": "2.0.5",
"bull": "4.12.2", "bull": "4.12.2",
"cacheable-lookup": "TheEssem/cacheable-lookup", "cacheable-lookup": "TheEssem/cacheable-lookup",
@ -128,7 +126,6 @@
"@swc/cli": "0.1.65", "@swc/cli": "0.1.65",
"@swc/core": "1.3.105", "@swc/core": "1.3.105",
"@types/adm-zip": "0.5.5", "@types/adm-zip": "0.5.5",
"@types/bcryptjs": "2.4.6",
"@types/escape-regexp": "0.0.3", "@types/escape-regexp": "0.0.3",
"@types/fluent-ffmpeg": "2.1.24", "@types/fluent-ffmpeg": "2.1.24",
"@types/js-yaml": "4.0.9", "@types/js-yaml": "4.0.9",

View file

@ -1,20 +0,0 @@
import bcrypt from "bcryptjs";
import * as argon2 from "argon2";
export async function hashPassword(password: string): Promise<string> {
return argon2.hash(password);
}
export async function comparePassword(
password: string,
hash: string,
): Promise<boolean> {
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");
}

View file

@ -10,7 +10,7 @@ import { UserKeypair } from "@/models/entities/user-keypair.js";
import { UsedUsername } from "@/models/entities/used-username.js"; import { UsedUsername } from "@/models/entities/used-username.js";
import { db } from "@/db/postgre.js"; import { db } from "@/db/postgre.js";
import config from "@/config/index.js"; import config from "@/config/index.js";
import { hashPassword } from "@/misc/password.js"; import { hashPassword } from "backend-rs";
export async function signup(opts: { export async function signup(opts: {
username: User["username"]; username: User["username"];

View file

@ -1,8 +1,7 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
// import bcrypt from "bcryptjs";
import rndstr from "rndstr"; import rndstr from "rndstr";
import { Users, UserProfiles } from "@/models/index.js"; import { Users, UserProfiles } from "@/models/index.js";
import { hashPassword } from "@/misc/password.js"; import { hashPassword } from "backend-rs";
export const meta = { export const meta = {
tags: ["admin"], tags: ["admin"],
@ -48,7 +47,6 @@ export default define(meta, paramDef, async (ps) => {
const passwd = rndstr("a-zA-Z0-9", 8); const passwd = rndstr("a-zA-Z0-9", 8);
// Generate hash of password // Generate hash of password
// const hash = bcrypt.hashSync(passwd);
const hash = await hashPassword(passwd); const hash = await hashPassword(passwd);
await UserProfiles.update( await UserProfiles.update(

View file

@ -9,7 +9,7 @@ import {
import config from "@/config/index.js"; import config from "@/config/index.js";
import { procedures, hash } from "@/server/api/2fa.js"; import { procedures, hash } from "@/server/api/2fa.js";
import { publishMainStream } from "@/services/stream.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")); 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 }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -4,7 +4,7 @@ import { promisify } from "node:util";
import * as crypto from "node:crypto"; import * as crypto from "node:crypto";
import { genId } from "@/misc/gen-id.js"; import { genId } from "@/misc/gen-id.js";
import { hash } from "@/server/api/2fa.js"; import { hash } from "@/server/api/2fa.js";
import { comparePassword } from "@/misc/password.js"; import { verifyPassword } from "backend-rs";
const randomBytes = promisify(crypto.randomBytes); 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 }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -3,7 +3,7 @@ import * as QRCode from "qrcode";
import config from "@/config/index.js"; import config from "@/config/index.js";
import { UserProfiles } from "@/models/index.js"; import { UserProfiles } from "@/models/index.js";
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { comparePassword } from "@/misc/password.js"; import { verifyPassword } from "backend-rs";
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -23,7 +23,7 @@ export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -1,4 +1,4 @@
import { comparePassword } from "@/misc/password.js"; import { verifyPassword } from "backend-rs";
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { UserProfiles, UserSecurityKeys, Users } from "@/models/index.js"; import { UserProfiles, UserSecurityKeys, Users } from "@/models/index.js";
import { publishMainStream } from "@/services/stream.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 }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -1,7 +1,7 @@
import { publishMainStream } from "@/services/stream.js"; import { publishMainStream } from "@/services/stream.js";
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { Users, UserProfiles } from "@/models/index.js"; import { Users, UserProfiles } from "@/models/index.js";
import { comparePassword } from "@/misc/password.js"; import { verifyPassword } from "backend-rs";
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -21,7 +21,7 @@ export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -1,6 +1,6 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { UserProfiles } from "@/models/index.js"; import { UserProfiles } from "@/models/index.js";
import { hashPassword, comparePassword } from "@/misc/password.js"; import { hashPassword, verifyPassword } from "backend-rs";
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -21,7 +21,7 @@ export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.currentPassword, profile.password!); const same = await verifyPassword(ps.currentPassword, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -1,7 +1,7 @@
import { UserProfiles, Users } from "@/models/index.js"; import { UserProfiles, Users } from "@/models/index.js";
import { deleteAccount } from "@/services/delete-account.js"; import { deleteAccount } from "@/services/delete-account.js";
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { comparePassword } from "@/misc/password.js"; import { verifyPassword } from "backend-rs";
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -25,7 +25,7 @@ export default define(meta, paramDef, async (ps, user) => {
} }
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -6,7 +6,7 @@ import {
import generateUserToken from "@/server/api/common/generate-native-user-token.js"; import generateUserToken from "@/server/api/common/generate-native-user-token.js";
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { Users, UserProfiles } from "@/models/index.js"; import { Users, UserProfiles } from "@/models/index.js";
import { comparePassword } from "@/misc/password.js"; import { verifyPassword } from "backend-rs";
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -29,7 +29,7 @@ export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new Error("incorrect password"); throw new Error("incorrect password");

View file

@ -7,7 +7,7 @@ import { sendEmail } from "@/services/send-email.js";
import { ApiError } from "@/server/api/error.js"; import { ApiError } from "@/server/api/error.js";
import { validateEmailForAccount } from "@/services/validate-email-for-account.js"; import { validateEmailForAccount } from "@/services/validate-email-for-account.js";
import { HOUR } from "@/const.js"; import { HOUR } from "@/const.js";
import { comparePassword } from "@/misc/password.js"; import { verifyPassword } from "backend-rs";
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -47,7 +47,7 @@ export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // Compare password
const same = await comparePassword(ps.password, profile.password!); const same = await verifyPassword(ps.password, profile.password!);
if (!same) { if (!same) {
throw new ApiError(meta.errors.incorrectPassword); throw new ApiError(meta.errors.incorrectPassword);

View file

@ -1,6 +1,6 @@
import { UserProfiles, PasswordResetRequests } from "@/models/index.js"; import { UserProfiles, PasswordResetRequests } from "@/models/index.js";
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { hashPassword } from "@/misc/password.js"; import { hashPassword } from "backend-rs";
export const meta = { export const meta = {
tags: ["reset password"], tags: ["reset password"],

View file

@ -12,10 +12,10 @@ import {
import type { ILocalUser } from "@/models/entities/user.js"; import type { ILocalUser } from "@/models/entities/user.js";
import { genId } from "@/misc/gen-id.js"; import { genId } from "@/misc/gen-id.js";
import { import {
comparePassword, verifyPassword,
hashPassword, hashPassword,
isOldAlgorithm, isOldPasswordAlgorithm,
} from "@/misc/password.js"; } from "backend-rs";
import { verifyLogin, hash } from "@/server/api/2fa.js"; import { verifyLogin, hash } from "@/server/api/2fa.js";
import { randomBytes } from "node:crypto"; import { randomBytes } from "node:crypto";
import { IsNull } from "typeorm"; import { IsNull } from "typeorm";
@ -92,9 +92,9 @@ export default async (ctx: Koa.Context) => {
const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
// Compare password // 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); profile.password = await hashPassword(password);
await UserProfiles.save(profile); await UserProfiles.save(profile);
} }

View file

@ -8,7 +8,7 @@ import config from "@/config/index.js";
import { sendEmail } from "@/services/send-email.js"; import { sendEmail } from "@/services/send-email.js";
import { genId } from "@/misc/gen-id.js"; import { genId } from "@/misc/gen-id.js";
import { validateEmailForAccount } from "@/services/validate-email-for-account.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) => { export default async (ctx: Koa.Context) => {
const body = ctx.request.body; const body = ctx.request.body;

View file

@ -8,7 +8,7 @@ import { genId } from "@/misc/gen-id.js";
import { UserKeypair } from "@/models/entities/user-keypair.js"; import { UserKeypair } from "@/models/entities/user-keypair.js";
import { UsedUsername } from "@/models/entities/used-username.js"; import { UsedUsername } from "@/models/entities/used-username.js";
import { db } from "@/db/postgre.js"; import { db } from "@/db/postgre.js";
import { hashPassword } from "@/misc/password.js"; import { hashPassword } from "backend-rs";
export async function createSystemUser(username: string) { export async function createSystemUser(username: string) {
const password = uuid(); const password = uuid();

View file

@ -108,9 +108,6 @@ importers:
archiver: archiver:
specifier: 6.0.1 specifier: 6.0.1
version: 6.0.1 version: 6.0.1
argon2:
specifier: ^0.31.2
version: 0.31.2
aws-sdk: aws-sdk:
specifier: 2.1542.0 specifier: 2.1542.0
version: 2.1542.0 version: 2.1542.0
@ -120,9 +117,6 @@ importers:
backend-rs: backend-rs:
specifier: workspace:* specifier: workspace:*
version: link:../backend-rs version: link:../backend-rs
bcryptjs:
specifier: 2.4.3
version: 2.4.3
blurhash: blurhash:
specifier: 2.0.5 specifier: 2.0.5
version: 2.0.5 version: 2.0.5
@ -389,9 +383,6 @@ importers:
'@types/adm-zip': '@types/adm-zip':
specifier: 0.5.5 specifier: 0.5.5
version: 0.5.5 version: 0.5.5
'@types/bcryptjs':
specifier: 2.4.6
version: 2.4.6
'@types/escape-regexp': '@types/escape-regexp':
specifier: 0.0.3 specifier: 0.0.3
version: 0.0.3 version: 0.0.3
@ -2917,6 +2908,7 @@ packages:
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
- supports-color - supports-color
dev: true
/@microsoft/tsdoc-config@0.16.2: /@microsoft/tsdoc-config@0.16.2:
resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==}
@ -3058,11 +3050,6 @@ packages:
sshpk: 1.18.0 sshpk: 1.18.0
dev: false 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: /@phosphor-icons/web@2.0.3:
resolution: {integrity: sha512-9oYmohi2fo87w3DbtfjBoJxrklVojgXq2wuGcqxKccj2TxMq7UIusKDrGUZYOQHM9pUKkh+kvfmutETMGDR6gg==} resolution: {integrity: sha512-9oYmohi2fo87w3DbtfjBoJxrklVojgXq2wuGcqxKccj2TxMq7UIusKDrGUZYOQHM9pUKkh+kvfmutETMGDR6gg==}
dev: true dev: true
@ -3537,10 +3524,6 @@ packages:
'@babel/types': 7.23.3 '@babel/types': 7.23.3
dev: true dev: true
/@types/bcryptjs@2.4.6:
resolution: {integrity: sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==}
dev: true
/@types/body-parser@1.19.5: /@types/body-parser@1.19.5:
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
dependencies: dependencies:
@ -4700,6 +4683,7 @@ packages:
/abbrev@1.1.1: /abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
requiresBuild: true requiresBuild: true
dev: true
/abbrev@2.0.0: /abbrev@2.0.0:
resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==}
@ -4920,6 +4904,7 @@ packages:
/aproba@2.0.0: /aproba@2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
requiresBuild: true requiresBuild: true
dev: true
/arch@2.2.0: /arch@2.2.0:
resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==}
@ -4966,23 +4951,11 @@ packages:
dependencies: dependencies:
delegates: 1.0.0 delegates: 1.0.0
readable-stream: 3.6.2 readable-stream: 3.6.2
dev: true
/arg@4.1.3: /arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} 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: /argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies: dependencies:
@ -5466,10 +5439,6 @@ packages:
tweetnacl: 0.14.5 tweetnacl: 0.14.5
dev: false 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: /bin-check@4.1.0:
resolution: {integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==} resolution: {integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -6455,6 +6424,7 @@ packages:
/console-control-strings@1.1.0: /console-control-strings@1.1.0:
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
requiresBuild: true requiresBuild: true
dev: true
/consolidate@0.16.0(ejs@3.1.9)(pug@3.0.2): /consolidate@0.16.0(ejs@3.1.9)(pug@3.0.2):
resolution: {integrity: sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==} resolution: {integrity: sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==}
@ -9167,6 +9137,7 @@ packages:
string-width: 4.2.3 string-width: 4.2.3
strip-ansi: 6.0.1 strip-ansi: 6.0.1
wide-align: 1.1.5 wide-align: 1.1.5
dev: true
/gensync@1.0.0-beta.2: /gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
@ -9649,6 +9620,7 @@ packages:
/has-unicode@2.0.1: /has-unicode@2.0.1:
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
requiresBuild: true requiresBuild: true
dev: true
/has-value@0.3.1: /has-value@0.3.1:
resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==}
@ -11831,6 +11803,7 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
semver: 6.3.1 semver: 6.3.1
dev: true
/make-dir@4.0.0: /make-dir@4.0.0:
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
@ -12359,10 +12332,6 @@ packages:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
dev: false dev: false
/node-addon-api@7.0.0:
resolution: {integrity: sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==}
dev: false
/node-domexception@1.0.0: /node-domexception@1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'} engines: {node: '>=10.5.0'}
@ -12450,6 +12419,7 @@ packages:
hasBin: true hasBin: true
dependencies: dependencies:
abbrev: 1.1.1 abbrev: 1.1.1
dev: true
/nopt@7.2.0: /nopt@7.2.0:
resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==}
@ -12547,6 +12517,7 @@ packages:
console-control-strings: 1.1.0 console-control-strings: 1.1.0
gauge: 3.0.2 gauge: 3.0.2
set-blocking: 2.0.0 set-blocking: 2.0.0
dev: true
/nth-check@1.0.2: /nth-check@1.0.2:
resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==} resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==}
@ -14672,6 +14643,7 @@ packages:
/signal-exit@3.0.7: /signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
dev: true
/signal-exit@4.1.0: /signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
@ -16619,6 +16591,7 @@ packages:
requiresBuild: true requiresBuild: true
dependencies: dependencies:
string-width: 4.2.3 string-width: 4.2.3
dev: true
/with@7.0.2: /with@7.0.2:
resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==}