|
| 1 | +import bcrypt from 'bcryptjs'; |
| 2 | + |
| 3 | +// How many times to scramble the password (10 seems to be the standard) |
| 4 | +// the password will be hashed 2^10 = 1024 times |
| 5 | +const SALT_ROUNDS = 10 |
| 6 | + |
| 7 | +// we use export so other files can import and use this func |
| 8 | +// hashing takes quite some time so we use the async keyword |
| 9 | +// the function will return a promise that resolves to a string (hash) |
| 10 | +export const hashPassword = async (password: string): Promise<string> => { |
| 11 | + try { |
| 12 | + // 1- generate a random salt (unique random data) |
| 13 | + // 'await' ensures that this assignment is complete before moving on |
| 14 | + const salt = await bcrypt.genSalt(SALT_ROUNDS) |
| 15 | + |
| 16 | + // 2- combine password with salt and hash it |
| 17 | + const hash = await bcrypt.hash(password, salt); |
| 18 | + |
| 19 | + // return the hash (this is what we store in database) |
| 20 | + return hash; |
| 21 | + } catch (error) { |
| 22 | + console.error('Error hashing password:', error); |
| 23 | + throw new Error('Failed to hash password'); |
| 24 | + } |
| 25 | +}; |
| 26 | + |
| 27 | +// takes the password user typed and stored hash |
| 28 | +// recall that bcrypt stores the salt inside the hash |
| 29 | +// the function internally extracts salt from hash |
| 30 | +// it then rehashes the typed password with same salt and compares |
| 31 | +export const comparePassword = async ( |
| 32 | + password: string, |
| 33 | + hash: string, |
| 34 | +): Promise<boolean> => { |
| 35 | + try { |
| 36 | + // bcrypt extracts the salt from the hash and compares |
| 37 | + const isMatch = await bcrypt.compare(password, hash); |
| 38 | + return isMatch; |
| 39 | + } catch (error) { |
| 40 | + console.error('Error comparing passwords:', error); |
| 41 | + throw new Error('Failed to compare passwords'); |
| 42 | + } |
| 43 | +}; |
| 44 | + |
| 45 | + |
0 commit comments