refactor (backend): port password hashing/verification to backend-rs
Co-authored-by: naskya <m@naskya.net>
This commit is contained in:
parent
baa57d7c17
commit
70aa3704ef
25 changed files with 214 additions and 118 deletions
92
Cargo.lock
generated
92
Cargo.lock
generated
|
@ -132,6 +132,18 @@ version = "1.0.82"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
||||
|
||||
[[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"
|
||||
|
@ -190,8 +202,10 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
|||
name = "backend-rs"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"async-trait",
|
||||
"basen",
|
||||
"bcrypt",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"cuid2",
|
||||
|
@ -238,6 +252,12 @@ version = "0.21.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
|
@ -250,6 +270,19 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dbe4bb73fd931c4d1aaf53b35d1286c8a948ad00ec92c8e3c856f15fd027f43"
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7"
|
||||
dependencies = [
|
||||
"base64 0.22.0",
|
||||
"blowfish",
|
||||
"getrandom",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bigdecimal"
|
||||
version = "0.3.1"
|
||||
|
@ -303,6 +336,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"
|
||||
|
@ -312,6 +354,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.4.0"
|
||||
|
@ -415,6 +467,16 @@ dependencies = [
|
|||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[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.5.4"
|
||||
|
@ -1075,6 +1137,15 @@ dependencies = [
|
|||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[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"
|
||||
|
@ -1122,7 +1193,7 @@ checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978"
|
|||
dependencies = [
|
||||
"ahash 0.8.11",
|
||||
"anyhow",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytecount",
|
||||
"clap",
|
||||
"fancy-regex",
|
||||
|
@ -1559,6 +1630,17 @@ dependencies = [
|
|||
"syn 2.0.58",
|
||||
]
|
||||
|
||||
[[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"
|
||||
|
@ -1801,7 +1883,7 @@ version = "0.11.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
|
@ -1947,7 +2029,7 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2398,7 +2480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bigdecimal",
|
||||
"bitflags 2.5.0",
|
||||
"byteorder",
|
||||
|
@ -2445,7 +2527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bigdecimal",
|
||||
"bitflags 2.5.0",
|
||||
"byteorder",
|
||||
|
|
|
@ -9,8 +9,10 @@ napi = { version = "2.16.2", default-features = false }
|
|||
napi-derive = "2.16.2"
|
||||
napi-build = "2.1.2"
|
||||
|
||||
argon2 = "0.5.3"
|
||||
async-trait = "0.1.80"
|
||||
basen = "0.1.0"
|
||||
bcrypt = "0.15.1"
|
||||
cfg-if = "1.0.0"
|
||||
chrono = "0.4.37"
|
||||
convert_case = "0.6.0"
|
||||
|
|
|
@ -17,8 +17,10 @@ macro_rs = { workspace = true }
|
|||
napi = { workspace = true, optional = true, default-features = false, features = ["napi9", "tokio_rt", "chrono_date", "serde-json"] }
|
||||
napi-derive = { workspace = true, optional = true }
|
||||
|
||||
argon2 = { workspace = true, features = ["std"] }
|
||||
async-trait = { workspace = true }
|
||||
basen = { workspace = true }
|
||||
bcrypt = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
cuid2 = { workspace = true }
|
||||
|
|
3
packages/backend-rs/index.d.ts
vendored
3
packages/backend-rs/index.d.ts
vendored
|
@ -135,6 +135,9 @@ export function toPuny(host: string): string
|
|||
export function toMastodonId(firefishId: string): string | null
|
||||
export function fromMastodonId(mastodonId: string): string | null
|
||||
export function nyaify(text: string, lang?: string | undefined | null): string
|
||||
export function hashPassword(password: string): string
|
||||
export function verifyPassword(password: string, hash: string): boolean
|
||||
export function isOldPasswordAlgorithm(hash: string): boolean
|
||||
export interface AbuseUserReport {
|
||||
id: string
|
||||
createdAt: Date
|
||||
|
|
|
@ -310,7 +310,7 @@ if (!nativeBinding) {
|
|||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, toMastodonId, fromMastodonId, nyaify, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding
|
||||
const { readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, toMastodonId, fromMastodonId, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding
|
||||
|
||||
module.exports.readServerConfig = readServerConfig
|
||||
module.exports.stringToAcct = stringToAcct
|
||||
|
@ -324,6 +324,9 @@ module.exports.toPuny = toPuny
|
|||
module.exports.toMastodonId = toMastodonId
|
||||
module.exports.fromMastodonId = fromMastodonId
|
||||
module.exports.nyaify = nyaify
|
||||
module.exports.hashPassword = hashPassword
|
||||
module.exports.verifyPassword = verifyPassword
|
||||
module.exports.isOldPasswordAlgorithm = isOldPasswordAlgorithm
|
||||
module.exports.AntennaSrcEnum = AntennaSrcEnum
|
||||
module.exports.MutedNoteReasonEnum = MutedNoteReasonEnum
|
||||
module.exports.NoteVisibilityEnum = NoteVisibilityEnum
|
||||
|
|
|
@ -3,3 +3,4 @@ pub mod check_word_mute;
|
|||
pub mod convert_host;
|
||||
pub mod mastodon_id;
|
||||
pub mod nyaify;
|
||||
pub mod password;
|
||||
|
|
69
packages/backend-rs/src/misc/password.rs
Normal file
69
packages/backend-rs/src/misc/password.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
use argon2::{
|
||||
password_hash,
|
||||
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
||||
Argon2,
|
||||
};
|
||||
|
||||
#[crate::export]
|
||||
pub fn hash_password(password: &str) -> Result<String, password_hash::errors::Error> {
|
||||
let salt = SaltString::generate(&mut OsRng);
|
||||
Ok(Argon2::default()
|
||||
.hash_password(password.as_bytes(), &salt)?
|
||||
.to_string())
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum VerifyError {
|
||||
#[error("An error occured while bcrypt verification: {0}")]
|
||||
BcryptError(#[from] bcrypt::BcryptError),
|
||||
#[error("Invalid argon2 password hash: {0}")]
|
||||
InvalidArgon2Hash(#[from] password_hash::Error),
|
||||
#[error("An error occured while argon2 verification: {0}")]
|
||||
Argon2Error(#[from] argon2::Error),
|
||||
}
|
||||
|
||||
#[crate::export]
|
||||
pub fn verify_password(password: &str, hash: &str) -> Result<bool, VerifyError> {
|
||||
if is_old_password_algorithm(hash) {
|
||||
Ok(bcrypt::verify(password, hash)?)
|
||||
} else {
|
||||
let parsed_hash = PasswordHash::new(hash)?;
|
||||
Ok(Argon2::default()
|
||||
.verify_password(password.as_bytes(), &parsed_hash)
|
||||
.is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[crate::export]
|
||||
pub fn is_old_password_algorithm(hash: &str) -> bool {
|
||||
// bcrypt hashes start with $2[ab]$
|
||||
hash.starts_with("$2")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_test {
|
||||
use super::{hash_password, is_old_password_algorithm, verify_password};
|
||||
|
||||
#[test]
|
||||
fn verify_password_test() {
|
||||
let password = "omWc*%sD^fn7o2cXmc9e2QasBdrbRuhNB*gx!J5";
|
||||
|
||||
let hash = hash_password(password).unwrap();
|
||||
assert!(verify_password(password, hash.as_str()).unwrap());
|
||||
|
||||
let argon2_hash = "$argon2id$v=19$m=19456,t=2,p=1$jty3puDFd4ENv/lgHn3ROQ$kRHDdEoVv2rruvnF731E74NxnYlvj5FMgePdGIIq3Jk";
|
||||
let argon2_invalid_hash = "$argon2id$v=19$m=19456,t=2,p=1$jty3puDFd4ENv/lgHn3ROQ$kRHDdEoVv2rruvnF731E74NxnYlvj4FMgePdGIIq3Jk";
|
||||
let bcrypt_hash = "$2a$12$WzUc.20jgbHmQjUMqTr8vOhKqYbS1BUvubapv/GLjCK1IN.h4e4la";
|
||||
let bcrypt_invalid_hash = "$2a$12$WzUc.20jgbHmQjUMqTr7vOhKqYbS1BUvubapv/GLjCK1IN.h4e4la";
|
||||
|
||||
assert!(!is_old_password_algorithm(argon2_hash));
|
||||
assert!(is_old_password_algorithm(bcrypt_hash));
|
||||
|
||||
assert!(verify_password(password, argon2_hash).unwrap());
|
||||
assert!(verify_password(password, bcrypt_hash).unwrap());
|
||||
|
||||
assert!(!verify_password(password, argon2_invalid_hash).unwrap());
|
||||
assert!(!verify_password(password, bcrypt_invalid_hash).unwrap());
|
||||
}
|
||||
}
|
|
@ -37,11 +37,9 @@
|
|||
"adm-zip": "0.5.10",
|
||||
"ajv": "8.12.0",
|
||||
"archiver": "7.0.1",
|
||||
"argon2": "^0.40.1",
|
||||
"aws-sdk": "2.1597.0",
|
||||
"axios": "^1.6.8",
|
||||
"backend-rs": "workspace:*",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "2.0.5",
|
||||
"bull": "4.12.2",
|
||||
"cacheable-lookup": "TheEssem/cacheable-lookup",
|
||||
|
@ -130,7 +128,6 @@
|
|||
"@swc/cli": "0.3.12",
|
||||
"@swc/core": "1.4.13",
|
||||
"@types/adm-zip": "^0.5.5",
|
||||
"@types/bcryptjs": "2.4.6",
|
||||
"@types/color-convert": "^2.0.3",
|
||||
"@types/content-disposition": "^0.5.8",
|
||||
"@types/escape-regexp": "0.0.3",
|
||||
|
|
|
@ -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");
|
||||
}
|
|
@ -4,12 +4,11 @@ import { User } from "@/models/entities/user.js";
|
|||
import { Users, UsedUsernames } from "@/models/index.js";
|
||||
import { UserProfile } from "@/models/entities/user-profile.js";
|
||||
import { IsNull } from "typeorm";
|
||||
import { genId, toPuny } from "backend-rs";
|
||||
import { genId, hashPassword, toPuny } from "backend-rs";
|
||||
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";
|
||||
|
||||
export async function signup(opts: {
|
||||
username: User["username"];
|
||||
|
@ -40,7 +39,7 @@ export async function signup(opts: {
|
|||
}
|
||||
|
||||
// Generate hash of password
|
||||
hash = await hashPassword(password);
|
||||
hash = hashPassword(password);
|
||||
}
|
||||
|
||||
// Generate secret
|
||||
|
|
|
@ -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,8 +47,7 @@ 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);
|
||||
const hash = hashPassword(passwd);
|
||||
|
||||
await UserProfiles.update(
|
||||
{
|
||||
|
|
|
@ -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"));
|
||||
|
||||
|
@ -40,8 +40,8 @@ export const paramDef = {
|
|||
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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -2,9 +2,8 @@ import define from "@/server/api/define.js";
|
|||
import { UserProfiles, AttestationChallenges } from "@/models/index.js";
|
||||
import { promisify } from "node:util";
|
||||
import * as crypto from "node:crypto";
|
||||
import { genId } from "backend-rs";
|
||||
import { genId, verifyPassword } from "backend-rs";
|
||||
import { hash } from "@/server/api/2fa.js";
|
||||
import { comparePassword } from "@/misc/password.js";
|
||||
|
||||
const randomBytes = promisify(crypto.randomBytes);
|
||||
|
||||
|
@ -25,8 +24,8 @@ export const paramDef = {
|
|||
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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -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,
|
||||
|
@ -22,8 +22,8 @@ export const paramDef = {
|
|||
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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -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";
|
||||
|
@ -21,8 +21,8 @@ export const paramDef = {
|
|||
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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -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,
|
||||
|
@ -20,8 +20,8 @@ export const paramDef = {
|
|||
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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -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,
|
||||
|
@ -20,8 +20,8 @@ export const paramDef = {
|
|||
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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.currentPassword, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -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,
|
||||
|
@ -24,8 +24,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
return;
|
||||
}
|
||||
|
||||
// Compare password
|
||||
const same = await comparePassword(ps.password, profile.password!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -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,
|
||||
|
@ -28,8 +28,8 @@ 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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error("incorrect password");
|
||||
|
|
|
@ -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,
|
||||
|
@ -46,8 +46,8 @@ export const paramDef = {
|
|||
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!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new ApiError(meta.errors.incorrectPassword);
|
||||
|
|
|
@ -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"],
|
||||
|
@ -32,7 +32,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
}
|
||||
|
||||
// Generate hash of password
|
||||
const hash = await hashPassword(ps.password);
|
||||
const hash = hashPassword(ps.password);
|
||||
|
||||
await UserProfiles.update(req.userId, {
|
||||
password: hash,
|
||||
|
|
|
@ -10,12 +10,12 @@ import {
|
|||
AttestationChallenges,
|
||||
} from "@/models/index.js";
|
||||
import type { ILocalUser } from "@/models/entities/user.js";
|
||||
import { genId } from "backend-rs";
|
||||
import {
|
||||
comparePassword,
|
||||
genId,
|
||||
hashPassword,
|
||||
isOldAlgorithm,
|
||||
} from "@/misc/password.js";
|
||||
isOldPasswordAlgorithm,
|
||||
verifyPassword,
|
||||
} from "backend-rs";
|
||||
import { verifyLogin, hash } from "@/server/api/2fa.js";
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { IsNull } from "typeorm";
|
||||
|
@ -91,11 +91,11 @@ export default async (ctx: Koa.Context) => {
|
|||
|
||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||
|
||||
// Compare password
|
||||
const same = await comparePassword(password, profile.password!);
|
||||
// Compare passwords
|
||||
const same = verifyPassword(password, profile.password!);
|
||||
|
||||
if (same && isOldAlgorithm(profile.password!)) {
|
||||
profile.password = await hashPassword(password);
|
||||
if (same && isOldPasswordAlgorithm(profile.password!)) {
|
||||
profile.password = hashPassword(password);
|
||||
await UserProfiles.save(profile);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,8 @@ import { Users, RegistrationTickets, UserPendings } from "@/models/index.js";
|
|||
import { signup } from "@/server/api/common/signup.js";
|
||||
import config from "@/config/index.js";
|
||||
import { sendEmail } from "@/services/send-email.js";
|
||||
import { genId } from "backend-rs";
|
||||
import { genId, hashPassword } from "backend-rs";
|
||||
import { validateEmailForAccount } from "@/services/validate-email-for-account.js";
|
||||
import { hashPassword } from "@/misc/password.js";
|
||||
import { inspect } from "node:util";
|
||||
|
||||
export default async (ctx: Koa.Context) => {
|
||||
const body = ctx.request.body;
|
||||
|
@ -85,7 +83,7 @@ export default async (ctx: Koa.Context) => {
|
|||
const code = rndstr("a-z0-9", 16);
|
||||
|
||||
// Generate hash of password
|
||||
const hash = await hashPassword(password);
|
||||
const hash = hashPassword(password);
|
||||
|
||||
await UserPendings.insert({
|
||||
id: genId(),
|
||||
|
|
|
@ -4,17 +4,16 @@ import { genRsaKeyPair } from "@/misc/gen-key-pair.js";
|
|||
import { User } from "@/models/entities/user.js";
|
||||
import { UserProfile } from "@/models/entities/user-profile.js";
|
||||
import { IsNull } from "typeorm";
|
||||
import { genId } from "backend-rs";
|
||||
import { genId, hashPassword } from "backend-rs";
|
||||
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";
|
||||
|
||||
export async function createSystemUser(username: string) {
|
||||
const password = uuid();
|
||||
|
||||
// Generate hash of password
|
||||
const hash = await hashPassword(password);
|
||||
const hash = hashPassword(password);
|
||||
|
||||
// Generate secret
|
||||
const secret = generateNativeUserToken();
|
||||
|
|
|
@ -99,9 +99,6 @@ importers:
|
|||
archiver:
|
||||
specifier: 7.0.1
|
||||
version: 7.0.1
|
||||
argon2:
|
||||
specifier: ^0.40.1
|
||||
version: 0.40.1
|
||||
aws-sdk:
|
||||
specifier: 2.1597.0
|
||||
version: 2.1597.0
|
||||
|
@ -111,9 +108,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
|
||||
|
@ -377,9 +371,6 @@ importers:
|
|||
'@types/adm-zip':
|
||||
specifier: ^0.5.5
|
||||
version: 0.5.5
|
||||
'@types/bcryptjs':
|
||||
specifier: 2.4.6
|
||||
version: 2.4.6
|
||||
'@types/color-convert':
|
||||
specifier: ^2.0.3
|
||||
version: 2.0.3
|
||||
|
@ -3294,11 +3285,6 @@ packages:
|
|||
sshpk: 1.17.0
|
||||
dev: false
|
||||
|
||||
/@phc/format@1.0.0:
|
||||
resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/@phosphor-icons/web@2.1.1:
|
||||
resolution: {integrity: sha512-QjrfbItu5Rb2i37GzsKxmrRHfZPTVk3oXSPBnQ2+oACDbQRWGAeB0AsvZw263n1nFouQuff+khOCtRbrc6+k+A==}
|
||||
dev: true
|
||||
|
@ -3831,10 +3817,6 @@ packages:
|
|||
'@babel/types': 7.23.0
|
||||
dev: true
|
||||
|
||||
/@types/bcryptjs@2.4.6:
|
||||
resolution: {integrity: sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==}
|
||||
dev: true
|
||||
|
||||
/@types/body-parser@1.19.2:
|
||||
resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
|
||||
dependencies:
|
||||
|
@ -5358,16 +5340,6 @@ packages:
|
|||
/arg@4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
|
||||
/argon2@0.40.1:
|
||||
resolution: {integrity: sha512-DjtHDwd7pm12qeWyfihHoM8Bn5vGcgH6sKwgPqwNYroRmxlrzadHEvMyuvQxN/V8YSyRRKD5x6ito09q1e9OyA==}
|
||||
engines: {node: '>=16.17.0'}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@phc/format': 1.0.0
|
||||
node-addon-api: 7.1.0
|
||||
node-gyp-build: 4.8.0
|
||||
dev: false
|
||||
|
||||
/argparse@1.0.10:
|
||||
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
||||
dependencies:
|
||||
|
@ -5893,10 +5865,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'}
|
||||
|
@ -13029,11 +12997,6 @@ packages:
|
|||
dev: true
|
||||
optional: true
|
||||
|
||||
/node-addon-api@7.1.0:
|
||||
resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==}
|
||||
engines: {node: ^16 || ^18 || >= 20}
|
||||
dev: false
|
||||
|
||||
/node-domexception@1.0.0:
|
||||
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||
engines: {node: '>=10.5.0'}
|
||||
|
@ -13083,6 +13046,7 @@ packages:
|
|||
/node-gyp-build@4.8.0:
|
||||
resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/node-int64@0.4.0:
|
||||
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
||||
|
|
Loading…
Reference in a new issue