Bcrypt & Jsonwebtoken
Bcrypt & Jsonwebtoken ๐
โ๋ณด์ ์์คํ ์ ๊ฐ์ฅ ์ฝํ ์ฐ๊ฒฐ ๊ณ ๋ฆฌ๋งํผ๋ง ๊ฐํ๋ค.โ
ํน์ ๋ถ๋ถ์ ๋ณด์์ด ์๋ฌด๋ฆฌ ๊ฐํ๋ค๊ณ ํ๋๋ผ๋ ๋ค๋ฅธ๋ถ๋ถ์์ ๋ณด์์ด ๋ซ๋ ค๋ฒ๋ฆฌ๋ฉด ์๋ฏธ๊ฐ ์๋ค.
๋ฐ๋ผ์ ๋ณด์ ์์คํ ์ ์์ ์ฑ์ โ๊ฐํ ๋ถ๋ถ์ด ์ผ๋ง๋ ๊ฐํ๊ฐโ๋ณด๋ค๋ โ์ฝํ ๋ถ๋ถ์ด ์ผ๋ง๋ ์ฝํ๊ฐโ์ ๋ฐ๋ผ์ ์ข์ฐ๋๋ค.
๋จ๋ฐฉํฅ ํด์ ํจ์
์๋ฅผ ๋ค๋ฉด โabcdโ๋ผ๋ ๋ฌธ์์ด์ ํด์์๊ณ ๋ฆฌ์ฆ์ ์ํด โadasfuaokfa32423823joegnsvd324refwdoiepoht23n34โ ๊ฐ์ ๋ฌธ์์ด๋ก ์ธ์ฝ๋ฉ๋ ์ ์๋ค.
์์ ๊ฐ์ ์ ์ฅํ๋ฉด ์ฌ์ฉ์์ ํจ์ค์๋๋ฅผ ์ง์ ์ ์ฅํ๋ ์ํ์ ํผํ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ๋ ํจ์ค์๋๋ฅผ ์ ๋ ฅํ๋ฉด, ์ด๋ฅผ ํด์ํ ๊ฐ์ ์ ์ฅ๋ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ์ผ์น ์ฌ๋ถ๋ฅผ ํ์ธํ ์ ์๋ค.
์ด ํน์ง์ avalanche ํจ๊ณผ๋ผ๊ณ ํ๋ฉฐ, ์ฌ์ฉ์์ ์๋ณธ ํจ์ค์๋๋ฅผ ์ถ๋ก ํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋๋ ์ค์ํ ์์์ด๋ค.
๋จ๋ฐฉํฅ ํด์ ํจ์์ ๋ฌธ์ ์
๋์ผํ ๋ฉ์์ง๊ฐ ์ธ์ ๋ ๋์ผํ ๋ค์ด์ ์คํธ๋ฅผ ๊ฐ๋๋ค๋ฉด, ๊ณต๊ฒฉ์๊ฐ ์ ์ฒ๋ฆฌ(pre-computing)๋ ๋ค์ด์ ์คํธ๋ฅผ ๊ฐ๋ฅํ ํ ๋ง์ด ํ๋ณดํ ๋ค์ ์ด๋ฅผ ํ์ทจํ ๋ค์ด์ ์คํธ์ ๋น๊ตํด ์๋ณธ ๋ฉ์์ง๋ฅผ ์ฐพ์๋ด๊ฑฐ๋ ๋์ผํ ํจ๊ณผ์ ๋ฉ์์ง๋ฅผ ์ฐพ์ ์ ์๋ค.
์ด์ ๊ฐ์ ๋ค์ด์ ์คํธ ๋ชฉ๋ก์ ๋ ์ธ๋ณด์ฐ ํ ์ด๋ธ(rainbow table)์ด๋ผ ํ๊ณ , ์ด์ ๊ฐ์ ๊ณต๊ฒฉ ๋ฐฉ์์ ๋ ์ธ๋ณด์ฐ ๊ณต๊ฒฉ(rainbow attack)์ด๋ผ ํ๋ค. ๊ฒ๋ค๊ฐ ๋ค๋ฅธ ์ฌ์ฉ์์ ํจ์ค์๋๊ฐ ๊ฐ์ผ๋ฉด ๋ค์ด์ ์คํธ๋ ๊ฐ์ผ๋ฏ๋ก ํ๊บผ๋ฒ์ ๋ชจ๋ ์ ๋ณด๊ฐ ํ์ทจ๋ ์ ์๋ค.
๋จ๋ฐฉํฅ ํด์ ํจ์ ๋ณด์ํ๊ธฐ
์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด, ๊ณต๊ฒฉ์๊ฐ โredfl0werโ์ ๋ค์ด์ ์คํธ๋ฅผ ์์๋ด๋๋ผ๋ ์ํ ๋ ๋ค์ด์ ์คํธ๋ฅผ ๋์์ผ๋ก ํจ์ค์๋ ์ผ์น ์ฌ๋ถ๋ฅผ ํ์ธํ๊ธฐ ์ด๋ ต๋ค. ๋ํ ์ฌ์ฉ์๋ณ๋ก ๋ค๋ฅธ ์ํธ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋์ผํ ํจ์ค์๋๋ฅผ ์ฌ์ฉํ๋ ์ฌ์ฉ์์ ๋ค์ด์ ์คํธ๊ฐ ๋ค๋ฅด๊ฒ ์์ฑ๋์ด ์ธ์ ๊ฐ๋ฅ์ฑ ๋ฌธ์ ๊ฐ ํฌ๊ฒ ๊ฐ์ ๋๋ค.
์ํธ์ ํจ์ค์๋์ ๋ค์ด์ ์คํธ๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๊ณ , ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ๋ ์ ๋ ฅํ ํจ์ค์๋๋ฅผ ํด์ํ์ฌ ์ผ์น ์ฌ๋ถ๋ฅผ ํ์ธํ ์ ์๋ค. ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ๋์๋ ๋ชจ๋ ํจ์ค์๋๊ฐ ๊ณ ์ ์ ์ํธ๋ฅผ ๊ฐ๊ณ ์ํธ์ ๊ธธ์ด๋ 32๋ฐ์ดํธ ์ด์์ด์ด์ผ ์ํธ์ ๋ค์ด์ ์คํธ๋ฅผ ์ถ์ธกํ๊ธฐ ์ด๋ ต๋ค.
bcrypt
# terminal
$ npm install bcrypt
import bcrypt from 'bcrypt';
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(password, salt);
๊ฐ์ ํจ์ค์๋๋ผํด๋ ์ํธ๋ถ๋ถ์ด ๋งค๋ฒ ๋ฐ๋๋๊ฒ์ ๋ณผ ์ ์๋ค.
bcrypt์ hashing์ ๊ฒฝ์ฐ์ CPU์ ์ํฅ์ ๋ง์ด ๋ฐ๋๋ฐ, sync๋ก ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ด๋ฒคํธ ๋ฃจํ์์ block ๋นํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ๊ฐ๋จํ๊ฒ ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ฉํด์ ์ฌ์ฉํ ๋๋ ๊ด์ฐฎ์ง๋ง, ์๋ฒ์์ ์ฌ์ฉํ ๋ async ๋ชจ๋๋ฅผ ๊ถ์ฅํ๊ณ ์๋ค.
const signIn = async (password) => {
const comparePw = await bcrypt.compare(password, users.password)
if(!coparePw) throw new Error('id , pw๊ฐ ๋ง์ง ์์ต๋๋ค.');
}
JWT
JWT๋ฅผ ์ฌ์ฉํ๋ ๊ฐ์ฅ ํํ ์๋๋ฆฌ์ค.
์ ์ ๊ฐ ๋ก๊ทธ์ธ์ ํ๋ฉด, ์๋ฒ๋ ์ ์ ์ ์ ๋ณด์ ๊ธฐ๋ฐํ ํ ํฐ์ ๋ฐ๊ธํ์ฌ ์ ์ ์๊ฒ ์ ๋ฌ.
๊ทธ ํ, ์ ์ ๊ฐ ์๋ฒ์ ์์ฒญ์ ํ ๋๋ง๋ค JWT๋ฅผ ํฌํจํ์ฌ ์ ๋ฌ.
์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ์ ์์ฒญ์ ๋ฐ์ ๋๋ง๋ค, ํด๋น ํ ํฐ์ด ์ ํจํ๊ณ ์ธ์ฆ๋๋์ง ๊ฒ์ฆ์ ํ๊ณ , ์ ์ ๊ฐ ์์ฒญํ ์์ ์ ๊ถํ์ด ์๋์ง ํ์ธํ์ฌ ์์ ์ ์ฒ๋ฆฌ.
์ฆ, ์๋ฒ ์ธก์์๋ ์ ์ ์ ์ธ์ ์ ์ ์งํ ํ์๊ฐ ์์.
์ ์ ๊ฐ ๋ก๊ทธ์ธ๋์ด์๋์ง ์๋์ด์๋์ง ์ ๊ฒฝ ์ธ ํ์๊ฐ ์๊ณ , ์ ์ ๊ฐ ์์ฒญ์ ํ์ ๋ ํ ํฐ๋ง ํ์ธํ๋ฉด ๋๋, ์ธ์ ๊ด๋ฆฌ๊ฐ ํ์ ์์ด์ ์๋ฒ ์์์ ๋ง์ด ์๋ ์ ์์.
JMT ๊ตฌ์กฐ
Header : ํ์ (JWT)๊ณผ ์๊ณ ๋ฆฌ์ฆ(BASE64 ๊ฐ์)์ ๋ด๋๋ค.
Payload : ๋ณดํต ์ ์ ์ ๋ณด(id๊ฐ์)์ ๋ง๋ฃ๊ธฐ๊ฐ์ด ๊ฐ์ฒดํ์ผ๋ก ๋ด๊ธด๋ค.
Signature : header, payload๋ฅผ ์ธ์ฝ๋ฉ ํ ๊ฐ์ ํฉ์น๋ค SECRET_KEY๋ก ํด์ฌํ๋ค.( ํ๊ฒฝ๋ณ์๋ก ์ค์ )
์ฌ์ฉ๋ฒ
# npm install jsonwebtoken
JWT_SECRET=JwTsEcReTkEyOrHaShInG
.evn์์ ํ๊ฒฝ๋ณ์๋ก ์ํฌ๋ฆฟํค ์ค์
const jwt = require('jsonwebtoken');
const token = jwt.sign(
{
id: users.id,
},
process.env.JWT_SECRET,
{
expiresIn: '60m', // ์ ํจ ์๊ฐ์ 60๋ถ
}
);
sign()
1๋ฒ์งธ ์ธ์ : payload ์ฆ, ๋ณด๋ผ๋ด์ฉ. (์ค์ํ ์ ๋ณด๋ ๋ด์ง์๋๋ก ํ ๊ฒ)
2๋ฒ์งธ ์ธ์ : ๋น๋ฐํค ( gitignore์ ์จ๊ธธ๊ฒ์ ๊ถ์ฅ )
3๋ฒ์งธ ์ธ์ : ํ ํฐ์ ๋ณด ( ์ฃผ๋ก ์ ํจ๊ธฐ๊ฐ )
4๋ฒ์งธ ์ธ์ : ์ฝ๋ฐฑํจ์ ( ์ฌ์ฉํ์ง์์ผ๋ฉด ๋๊ธฐ์์ผ๋ก ์ฒ๋ฆฌ๋๋ค. )
const verifyToken = (token) => {
try {
return jwt.verify(token, process.env.JWT_SECRET);
} catch (err) {
return null;
}
};
const Authentication = (req, res, next) => {
const token = req.cookies.user; // token๊ฐ์ ธ์ค๊ธฐ
const vaildToken = verifyToken(token);
if (vaildToken) {
req.userId = vaildToken.id;
next();
} else {
res.status(400).send('ํ ํฐ์ด ์ ํจํ์ง ์์ต๋๋ค.');
return;
}
};
์ฃผ๋ก ์ธ์ฆ์ ์ฌ์ฉ๋๋ค.