---
# System prepended metadata

title: "\U0001F3C5 Day 26 - bcrypt.js 密碼加解密"
tags: [node.js, Node.js 直播班-2024春季班]

---

# 🏅 Day 26 - bcrypt.js 密碼加解密


### 密碼加密
使用 bcrypt.js 的 `hash()` 以**非同步**的方式將密碼加密
```javascript
bcrypt.hash(password, 12);
// 第一個參數是要做雜湊加密的字串，第二個參數是要加鹽的字串長度
```
> 補充：
> [雜湊(Hash function)](https://zh.wikipedia.org/zh-tw/%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B8)為一種演算法，會將資料打亂建立雜湊值，雜湊值具有「不可逆」的性質（由此值回推原本的值非常困難），因此常用於密碼加密
> [鹽（Salt）](https://zh.wikipedia.org/zh-tw/%E7%9B%90_(%E5%AF%86%E7%A0%81%E5%AD%A6))在密碼學中，是指在雜湊之前將雜湊內容（例如：密碼）的任意固定位置插入特定的字串。這個在雜湊中加入字串的方式稱為「加鹽」

### 密碼解密
密碼加密後，未來需要驗證是否為該註冊帳號就需以 `compare()` 將密碼與加密後的字串進行比對

```javascript
bcrypt.compare(password, user.password);
// 第一個參數是接收到的密碼，第二個參數是由資料庫找出的該 user 的密碼，為雜湊加密的字串
```


### 參考資源

- [bcrypt.js - hash](https://github.com/dcodeIO/bcrypt.js#hashs-salt-callback-progresscallback)
- [bcryptjs - compare](https://github.com/dcodeIO/bcrypt.js#compares-hash-callback-progresscallback)


題目(回報作業)
---
延續前一天 Day25 解答，運用 bcrypt.js 將使用者註冊輸入的密碼加密後再新增至 User 內

```javascript=
router.post('/sign_up', handleErrorAsync(async (req, res, next) => {
  let { name, email, password } = req.body;

  // 加入驗證，確保使用者註冊資料符合格式
  // 三個欄位皆必填
  if (!name || !email || !password) {
    return next(appError(400, '請確保所有欄位皆填寫', next));
  }

  // 暱稱 name 長度需至少 2 個字元以上
  if (!validator.isLength(name, { min: 2 })) {
    return next(appError(400, '暱稱需至少 2 個字元以上', next));
  }
  
  // 信箱 email 格式正確
  if (!validator.isEmail(email)) {
    return next(appError(400, 'Email 格式錯誤', next));
  }
  
  // 密碼 password 長度至少 8 碼以上
  if (!validator.isLength(password, { min: 8 })) {
    return next(appError(400, '密碼需至少 8 碼以上', next));
  }
  
  // 將密碼 password 加密
  password = await bcrypt.hash(password, 12);
  
  const newUser = await User.create({
    email,
    password,
    name
  });

  res.status(200).json({
    status: 'success',
    data: newUser
  });

}));
```

