dumorando / bapiv2

the bark backend API
https://api.bark.dumorando.com
0 stars 1 forks source link

[Security] Use hashing rather than encryption for passwords #2

Open Steve0Greatness opened 2 months ago

Steve0Greatness commented 2 months ago

Encryption isn't the best method of storing a password for one very large reason: the decryption key has to be stored somewhere. If the server ever were to be hacked, the decryption key would be need to be stored somewhere in the database, meaning the server is practically storing passwords in plaintext.

The far better way to store a password is to use a cryptographic hash function to store them. Hashing, unlike encryption, cannot be reversed, meaning the only way for an attacker to steal a password is to brute force it.

I'd specifically recommend you use a cryptographic hash function designed for passwords, like Argon2. There are prebuilt JavaScript implementations of Argon2, like argon2(FYI: this requires the usage of await).

Here's a little JavaScript pseudocode written with this library:

const argon2 = require("argon2");
const db = require("key-value-database")

async function UserSignup(login, password) {
    var hash = await argon2.hash(password);
    db.store(`users.${login}.hash`, hash);
}

async function UserLogin(login, password) {
    var hash = db.get(`users.${login}.hash`);
    return await argon2.verify(hash, password);
}

Here's a small usage example:

await UserSignup("mashedpotatoes96", "~.FWf&}O0|DA\XvD");

await UserLogin("mashedpotatoes96", "~.FWf&}O0|DA\XvD"); // true
await UserLogin("mashedpotatoes96", "password123"); // false
dumorando commented 2 months ago

this was the goal for this version of the bark api but my server cant run bcrypt for some reason. haven't heard of this library yet but ill implement it soon

Steve0Greatness commented 2 months ago

this was the goal for this version of the bark api but my server cant run bcrypt for some reason. haven't heard of this library yet but ill implement it soon

If you're self hosting: bcrypt has fairly strict memory requirements, Argon2 should be able to work since, at least from what I've heard, it can adapt to the amount of memory available.

If you're not self hosting: I have no clue.

dumorando commented 2 months ago

i use serv00 which has 512 mb of ram

Steve0Greatness commented 2 months ago

Actually, hold on, nevermind. I misunderstood the amount of memory bcrypt uses.

I'm actually not completely sure what the best of the password hash algorithms are best. Given the wording on Wikipedia's bcrypt page, it seems to be pointing towards Pufferfish2 being the best, but considering that Bcrypt won't run on serv00, it probably won't be able to run Pufferfish2 either. But Argon2 is a very different function, so it should work. Keyword is should, but it also might not.

dumorando commented 2 months ago

yea its just that argon2 and bcrypt use node plugins which my server doesnt support for some reason its not any issue with memory

dumorando commented 2 months ago

im not sure if this would be great for passwords but i could try something like sha256

Steve0Greatness commented 2 months ago

im not sure if this would be great for passwords but i could try something like sha256

Since that doesn't require a node plugin (at least to my knowledge) it should work.

Make sure to implement salts as well, so that it's not vulnerable to rainbow tables.

dumorando commented 2 months ago

good idea just not sure how i would implement salting

dumorando commented 2 months ago

nvm itd be easy

Steve0Greatness commented 2 months ago

good idea just not sure how i would implement salting

Salts are just a long number prepended (or appended) to the password before it is hashed, so try storing it alongside the password and then choosing which way you'll add it into the password.

dumorando commented 2 months ago

so like

let userpassword = req.body.password;
let salt = db.get(req.body.username).salt;

if (sha256(userpassword + salt) == db.get(req.body.username).password) {
//logged in
}
Steve0Greatness commented 2 months ago

so like

let userpassword = req.body.password;
let salt = db.get(req.body.username).salt;

if (sha256(userpassword + salt) == db.get(req.body.username).password) {
//logged in
}

Yeah, pretty much.

dumorando commented 2 months ago

alright yeah ill get started on that tomrorow


stop liking this it will proably take me a long time too get the courage to work with this shitty code agaein