문서의 선택한 두 판 사이의 차이를 보여줍니다.
| 양쪽 이전 판이전 판다음 판 | 이전 판 | ||
| python:django:bcrypt [2024/02/02 13:18] – [Node.js에서 bcrypt 사용하기] taekgu | python:django:bcrypt [2025/04/15 10:05] (현재) – 바깥 편집 127.0.0.1 | ||
|---|---|---|---|
| 줄 1: | 줄 1: | ||
| + | ====== 비밀번호 암호화하자 ====== | ||
| + | ===== bcrypt를 이용한 비밀번호 암호화 ===== | ||
| + | 1. bcrypt설치 | ||
| + | 2. bcrypt 모듈 불러옴 import bcrypt | ||
| + | 3. 해시할 문자열 인코딩 | ||
| + | 4. password 해시 | ||
| + | <code python> | ||
| + | import bcrypt | ||
| + | maro_password = ' | ||
| + | print (maro_password) | ||
| + | |||
| + | enc_password = maro_password.encode(' | ||
| + | print (enc_password) | ||
| + | |||
| + | |||
| + | hashed_pw = bcrypt.hashpw(enc_password, | ||
| + | print(hashed_pw) | ||
| + | </ | ||
| + | |||
| + | 5. 해시된 password 디코딩 | ||
| + | 6. 해시되고 디코딩된 password를 보관 | ||
| + | <code python> | ||
| + | dec_password = hashed_pw.decode(' | ||
| + | print(f' | ||
| + | </ | ||
| + | |||
| + | 7. 비밀번호비교 | ||
| + | <code python> | ||
| + | a = ' | ||
| + | # hased_pw는 DB에 저장된 암호화된 패스워드 | ||
| + | isPass = bcrypt.checkpw(a.encode(' | ||
| + | print(f" | ||
| + | </ | ||
| + | |||
| + | ===== Salting & Key Stretching ===== | ||
| + | |||
| + | 단방향 암호화에 사용되는 해시 알고리즘은 동일한 평문에 대해 항상 동일 해시값을 갖는다. 따라서 특정 해시 알고리즘에 대하여 특정 평문이 어떤 해시값을 갖는지 알 수 있다. | ||
| + | |||
| + | 또한 해시 함수는 본래 신속히 데이터를 검색하기 위해 탄생됐다. 따라서 공격자는 매우 빠른 속도로 임의의 문자열의 해시값과 해킹할 대상의 해시값을 비교하여 대상자를 공격할 수 있다. | ||
| + | |||
| + | 이런한 문제를 보안하기 위해 단방향 암호화를 진행할 때 솔팅(Salting)과 키 스트레칭(Key Stretching)을 적용 시킨다. | ||
| + | |||
| + | ===== 솔팅(Salting) ===== | ||
| + | |||
| + | |||
| + | 솔팅은 단방향 해시 함수 암호화를 진행 할 때 본래 데이터에 추가적으로 랜덤한 데이터를 더하는 방식이다. 원래 데이터에 추가 데이터가 포함 되었기 때문에 이전의 해시값과 달라진다. | ||
| + | |||
| + | ===== 키 스트레칭(Key Stretching) ===== | ||
| + | |||
| + | |||
| + | 단방향 해쉬값을 계산 한 후, 그 해쉬값을 또 다시 해시하고 또 이를 반복하는 방식이다. 최근 일반적인 장비로도 1초에 50억 개 이상의 해시값을 비교할 수 있다. 하지만 키 스트레칭을 적용하면 동일 장비에서 1초에 5번 정도만 비교할 수 있다. GPU(Graphics Processing Unit)를 사용하더라도 수백에서 수천 번 정도만 비교할 수 있다. | ||
| + | |||
| + | ===== Bcrypt 란? ===== | ||
| + | |||
| + | Bcypt는 브루스 슈나이어가 설계한 키(key) 방식의 대칭형 블록 암호에 기반을 둔 암호화 해시 함수다. Niels Provos 와 David Mazières가 설계했다. Bcrypt는 레인보우 테이블 공격을 방지하기 위해 솔팅과 키 스트레칭을 적용한 대표적인 예다. | ||
| + | |||
| + | ==== 구조 ==== | ||
| + | |||
| + | < | ||
| + | $2b$12$76taFAFPE9ydE0ZsuWkIZexWVjLBbTTHWc509/ | ||
| + | \/ \/ \____________________/ | ||
| + | Alg Cost | ||
| + | </ | ||
| + | |||
| + | * 2b : 해시 알고리즘 식별자 | ||
| + | * 12 : Cost Factor로 Key Stretching의 수 (2의 12승번) | ||
| + | * 76taFAFPE9ydE0ZsuWkIZe : 16Byte 크기의 Salt, Base64로 인코딩된 22개의 문자 | ||
| + | * xWVjLBbTTHWc509/ | ||
| + | |||
| + | |||
| + | ==== 검증 ==== | ||
| + | |||
| + | |||
| + | Bcrypt는 단방향 해시 알고리즘이다. 따라서 복호화가 불가능하다. Bcrypt의 검증은 암호화된 값이 가지고 있는 알고리즘, | ||
| + | |||
| + | * 비교하고 싶은 평문을 | ||
| + | * 암호화된 값이 가지고 있는 알고리즘, | ||
| + | * 암호화된 값과의 비교를 통해 검증을 진행한다. | ||
| + | |||
| + | |||
| + | |||
| + | ====== Node.js에서 bcrypt 사용하기 ====== | ||
| + | |||
| + | ===== Bcrypt 설치 ===== | ||
| + | |||
| + | <code bash> | ||
| + | $ npm install bcrypt --save | ||
| + | </ | ||
| + | |||
| + | ==== Bcrypt로 비밀번호 암호화 (Async) ==== | ||
| + | <code javascritp> | ||
| + | const bcrypt = require(" | ||
| + | |||
| + | const password = ' | ||
| + | const saltRounds = 12; // (3) | ||
| + | |||
| + | const makeHash = async (password, saltRounds) => { | ||
| + | return await bcrypt.hash(password, | ||
| + | } | ||
| + | |||
| + | const main = async () => { | ||
| + | const hashedPassword = await makeHash(password, | ||
| + | console.log(hashedPassword); | ||
| + | } | ||
| + | |||
| + | main() | ||
| + | => b' | ||
| + | </ | ||
| + | |||
| + | * (1): bcrypt 모듈 import | ||
| + | * (2): 암호화 할 평문 | ||
| + | * (3): Cost Factor | ||
| + | * (4): hash() method로 암호화, 첫번째 인자로 암호화 하고 싶은 평문이 두번째 인자로 Cost Factor가 들어간다. | ||
| + | |||
| + | ==== Bcrypt 검증 ==== | ||
| + | |||
| + | <code javascript> | ||
| + | const checkHash = async (password, hashedPassword) => { | ||
| + | return await bcrypt.compare(password, | ||
| + | } | ||
| + | |||
| + | const main = async () => { | ||
| + | const hashedPassword = await makeHash(" | ||
| + | const result = await checkHash(" | ||
| + | console.log(result); | ||
| + | }; | ||
| + | |||
| + | main() | ||
| + | => true(or false) // (2) | ||
| + | </ | ||
| + | |||
| + | * (1): compare() method로 평문과 암호화된 값 비교, 첫번째 인자로 평문이 두번째 인자로 암호화된 값이 들어간다. | ||
| + | * (2): 비교 결과, 평문과 암호화된 값을 비교해서 같으면 true를 다르면 false가 return된다. | ||
| + | |||
| + | |||
| + | ====== 정리 ====== | ||
| + | |||
| + | * 단방향 암호화는 해시 알고리즘을 사용한 암호화는 가능, 그러나 복호화는 불가능한 암호화 방법이다. | ||
| + | * 단방향 암호화는 해시 알고리즘을 기반으로 만들어졌다. | ||
| + | * 솔팅(Salting)과 키 스트레칭(Key Stretching) 기법을 이용하여 단방향 암호화의 단점을 보안할 수 있다. | ||
| + | * Bcrypt는 레인보우 테이블 공격을 방지하기 위해 솔팅과 키 스트레칭을 적용한 대표적인 예다. | ||
| + | * Bcrypt는 단방향 해시 알고리즘이기 때문에 복호화가 불가능하다. 따라서 비교하고 싶은 평문을 암호화된 값이 가지고 있는 알고리즘, | ||
| + | * 양방향 암호화에는 대칭키 방식과 비대칭키 방식이 존재. 암호화와 복호화를 진행 할 때 Key를 이용한다. | ||
| + | * 대칭키 방식의 양방향 암호화는 암호화와 복호화에 동일한 Key를 사용하며, | ||
| + | * 비대칭키 방식의 양방향 암호화는 암호화와 복호화에 서로 다른 Key를 사용하며, | ||
| + | |||
| + | 참조) [[https:// | ||