비밀번호 암호화 -> 고객 데이터 소중
개인정보 보호 법령에 의거.
백엔드 개발자라고해서 고객의 비밀번호를 알 수 없음 .
단방향. 돌아갈 수 없음. -> 해쉬 함수
(한번 복호화 후에는 비밀번호를 볼 수 없음, 역함수 없음)
(우리는 복호화 하는데, 이거를 풀려고 하는 사람이 있다. --> 해커들. 그렇기에 복잡하게 비밀번호 암호화 하는 것)
1. 설치
npm install bcrypt --save -dev
package.json에서 확인
2. 쓸 수 있게 가져온다
const bycrypt = require("bcrypt") ;
3. 두개의 변수 선언
const bcrypt = require("bcrypt");
const password = 'password'; // 문자열
const saltRounds = 12; //솔팅
const makeHash = async (password, saltRounds) => { //인자에 문자열이 들어가야 하는데, password와 몇번 salting하는지
return await bcrypt.hash (password, saltRounds);
} // 아까 다운 받은 bcrypt 모듈 안에, hash를 꺼내서, 이 hash의 password, saltRounds 를 전달한다.
만약, 내부 개발자이라면, rainbow table로
비밀번호를 알 수 있음
const bcrypt = require("bcrypt"); ---- (1)
const password = 'password'; ---- (2)
const saltRounds = 12; ---- (3)
const makeHash = async (password, saltRounds) => {
return await bcrypt.hash(password, saltRounds); ---- (4)
}
const main = async () => {
const hashedPassword = await makeHash(password, saltRounds);
console.log(hashedPassword);
}
main()
=> b'$2b$12$76taFAFPE9ydE0ZsuWkIZexWVjLBbTTHWc509/OLI5nM9d5r3fkRG'
b 붙어서 나올텐데 -> binary로 붙여서 해야 한다.
'$2b라는 함수로
$12번 해쉬 돌려서
$뒤에 솔팅을 할거야'
원본 비밀번호 거꾸로 유추는 할 수 없지만
솔트와 횟수도 알려주는데 , 대신 진짜 비밀번호 너 맞아?
- (1): bcrypt 모듈 import
- (2): 암호화 할 평문
- (3): Cost Factor
- (4): hash() method로 암호화, 첫번째 인자로 암호화 하고 싶은 평문이 두번째 인자로 Cost Factor
뒤 문자열도 같아야 함.
개발자를 위해, 그 문자열도 비교해주는 함수도 있음
솔팅(Salting)
단방향 해시 함수를 통해 암호화를 진행 할 때
본래 데이터에 추가적으로 랜덤한 데이터를 더하여 암호화를 진행하는 방식
원래 데이터에 추가 데이터가 포함 되었기 때문에 원래 데이터의 해시값과 다르게 됩니다.
--> 우연찮게 같은 패스워드를 쳐도 다르게 나오도록
f(x) = 2x =y 이렇게
어떤 함수인지, 몇번 돌렸는지, 어떤 그거인지 데이터베이스에 다 올라와서 알 수 있음. 숨기지 않음. 다 뚫어놓음
데이터베이스 털려도 다 알 수.
키 스트레칭(Key Stretching)
단방향 해쉬값을 계산 한 후, 그 해쉬값을 또 다시 해시하고 또 이를 반복하는 방식
최근에는 일반적인 장비로 1초에 50억 개 이상의 해시값을 비교할 수 있지만,
키 스트레칭을 적용하여 동일한 장비에서 1초에 5번 정도만 비교할 수 있습니다.
GPU(Graphics Processing Unit)를 사용하더라도 수백에서 수천 번 정도만 비교할 수 있습니다.
--> 솔트를 또 붙여서 여러 번 하는게 키 스트레칭
라이브러리의 이름이 bcrypt (자바스크립트 이외 언어에도 다 쓰는 라이브러리)
단방향 암호화 vs 양방향 암호화 차이점 말해보라는 질문 -> 특징을 말하면 됨.
- 수업 듣고 추가할 것 (복잡한 함수를 쓴다 )
- 복호화 불가능
- 솔팅 키스트레칭
<가입 흐름>
client로부터 데이터 받고
비밀번호 조건 체크
비밀번호를 DB 저장 직전
{비밀번호 암호화} -- salt , hashing
<로그인 흐름>
client 데이터 가져오고
유저 유무 확인 -- 이메일로
비밀번호 일치 여부 확인
-- 이 시점에 사용
요청을 보낼 때,
백엔드 프론트 통신은 언제나 요청을 보낼 때니까 - http request의 headers에 담아
백엔드 서버는
클라이언트와 데이터베이스 서버를 연결.
[로그인]
데이터베이스에서 암호화된 비밀번호를 가져온 비밀번호 (select문) vs 외부 클라이언트가 보내준 req에 들어온 비밀번호
= 일치하면 로그인 성공 -> 토큰 발급
header에 convention인 Authorization 키에 토큰을 담아서 프론트에게 보내면,
다시 우리는, "내가 보낸 토큰 맞아" 하고 토큰을 헤짚는.
[회원가입]
request가 담고 있는 유저가 전달해준 비밀번호와, getEncryptedPassword 함수로,
bcrypt의 makehash 함수를 써서,
유저가 전달한 비밀번호를,
12번의 솔팅 거쳐서, hashing을 거쳐서 결과값을 어렵게 만든 다음,
그 암호화된 것을 데이터베이스에 저장,
백엔드는 늘 항상 중간에서.
request받아오고, 데이터베이스에서 받아오고 비교하고.
const password= 'password' 는 외부에서 받아오는 password
const hashedPassword = await makeHash (password, saltRounds); 는 데이터베이스에서 가져온 것
그래야 백엔드가 중간 개입자로서
왼쪽 (클라이언트 , 외부에서 들어온) vs 오른쪽 (데이터베이스에서 긁어온)
중간을 잡을 수 있으니.
유저네임의 패스워드 (닉네임 or 이메일 불러와서 그의 패스워드를 데이터베이스에서 가져오는)
password를 가져오는데, 난수화된 패스워드일 테니 hashedPassword를 붙이는 것.
토큰을 발행하면, payload안에 우리가 가지고 가야할 최소한의 유저 정보
userid, password 와 같은 정보를 담고 있을 것.
http header의 특정 객체 안에, Authorization header에 토큰 있음.
Authorization을 까볼 수 있는 jwt 안의 verify함수 이용
이상으로 bcrypt와
bcrypt 안에 있는 해쉬함수,
그 해쉬함수 모듈 안에 있는 makeHash, checkHash 에 대해 알아보았다.
'Wecode -Foundation 2 (부트캠프) > 인증, 인가- 개념' 카테고리의 다른 글
Foundation 2- [jwt, token] 토큰 개념, 토큰 코드 만들기, 토큰 발행 / 프론트와 연결하는 법 (엔드포인트, api) (0) | 2023.09.09 |
---|---|
Foundation 2 - 인증 : token, session, (0) | 2023.09.06 |
Foundation 2- 인증과 인가 (0) | 2023.09.06 |