...
암호화 모듈
암호화 종류
SHA-2(Secure Hash Algorithm 2)
- 미국 NSA에서 설계한 암호화 해시 함수.
- digest size는 224, 256, 512 bit로 해시함수로 구성되어졌음.
- GPU를 이용한 연산속도가 매우 빠르기 때문에 password 암호화에 권장되지 않음
- GPU 연산속도가 빠를수록 공격자의 하드웨어를 통한 오프라인 brute force에 더 취약하다.
- 빠른 해시를 사용하여 암호화를 진행시 공격자는 오프라인 공격으로 초당 수십억개의 해시를 계산할 수 있다.
PBKDF2
pbkdf2_hmac(해시함수(sha256..), password, salt, iteration, DLen)
- 해시함수의 컨테이너 역할을 한다.
- 검증된 해시함수만을 사용한다.
- 해시함수와 salt를 적용 후 해시 함수의 반복횟수를 지정하여 암호화할 수 있다.
- 가장 많이 사용되는 함수. ISO 표준에 적합하며 NIST에서 승인된 알고리즘이다.
Bcrypt
bcrypt.hashpw(password, bcrypt.gensalt())
- 1999년에 publish된 password-hashing function이다.
- Blowfish 암호를 기반으로 설계된 암호화 함수이며 현재까지 사용중인 가장 강력한 해시 메커니즘 중 하나이다.
- 보안에 집착하기로 유명한 OpenBSD에서 사용하고 있다.
- .NET 및 Java를 포함한 많은 플랫폼,언어에서 사용할 수 있다.
- 반복횟수를 늘려 연산속도를 늦출 수 있으므로 연산 능력이 증가하더라도 brute-forece 공격에 대비할 수 있다.
Scrypt
hashlib.scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64)
- 2009년에 publish된 key derivation function이다.
- 오프라인 brute forece 공격에 대해 더 강력하지만, 많은 메모리와 CPU를 사용한다.
- OpenSSL 1.1 이상을 제공하는 시스템에서만 작동한다.
- 여러 언어의 라이브러리로 제공된다.
- 다른 암호기반 KDF에 비해 많은 양의 메모리를 사용하도록 설계되었다.
- 하드웨어 구현을 하는데 크기와 비용이 훨씬 더 비싸기 때문에, 주어진 자원에서 공격자가 사용할 수 있는 병렬처리의 양이 한정적이다.
왜 Bcrypt가 추천되어질까?
bcrypt가 정답은 아니다. 또한 SHA 종류가 무조건 나쁘다고 하는 것은 아니다.
그러나 많은 보안관련 글들에서 SHA를 암호해싱에 사용하는 암호화 함수들은 GPU를 이용한 공격에 취약하며 (SHA family는 연산속도가 매우빠르기 떄문) 많은 메모리를 필요로 하지 않는 점을 문제로 지적하고있다.
SHA가 보안에 결함이 있어서 안전하지 않기 때문이 아니라,
SHA는 일반적으로 GPU연산에 유리한 32비트 논리 및 산술 연산만 사용하기 때문에, 공격자가 빠른연산으로 공격할 수 있기 때문이라는 것이다.
그로인해 Bcrypt 설계자들은 이런 문제로 SHA가 아닌 Blowfish를 이용하여 구현하였다.
이상적으로 봤을때 limit가 없는 연산 능력을 가진 공격자는 모든 종류의 암호화 알고리즘을 해독 할 수 있겠지만, 이는 어디까지나 이론적인 상황이지 실제로 공격자는 컴퓨터자원을 무제한으로 보유하지 않기 때문에, 공격자의 속도를 늦출 수록 암호화 해독이 어려워진다.
어떤 암호화 함수(bcrypt, pbkdf2, scrypt, ..)를 쓰던 강력하지만, 충분한 시도 횟수, work-factor가 존재한다고 가정할 때, 방어자는 좀 더 느리게 설계된 암호화 방식에 의존하는 것이 낫다고 생각된다.
암호화 사용 정리
- ISO-27001 보안 규정을 준수해야하는 상황이면 PBKDF2를 사용하자.
- 일반적으로 규정을 준수해야할 상황이 아니면 구현이 쉽고 비교적 강력한 Bcrypt를 사용하자.
- 보안 시스템을 구현하는데 많은 비용을 투자할 수 있다면, Scrpyt를 사용하자.
Bcrypt 모듈 사용법
> npm install bcrypt
비밀번호 암호화하기
- hash는 동기, hashSync는 비동기 방식
- 파라미터로 넣은 숫자 12은 암호화에 사용되는 Salt로, 값이 높을 수록 암호화 연산이 증가한다.
하지만 암호화하는데 속도가 느려진다.
const bcrypt = require('bcrypt');
const PW = 'abcd1234'
const salt = 12;
// hash 비동기콜백
bcrypt.hash(PW, salt, (err, encryptedPW) => {
})
// hashSync 동기
const hash = bcrypt.hashSync(PW, salt);
// async/await 사용
const hash = await bcrypt.hash(PW, salt)
비밀번호 검증하기
const PW = 'abcd1234';
const hash = bcrypt.hashSync(PW, 12);
// 비동기 콜백
bcrypt.compare(PW , hash, (err, same) => {
console.log(same); //=> true
})
// 동기
const match = bcrypt.compareSync(PW, hash);
if(match) {
//login
}
// async/await
const match = await bcrypt.compare(PW , hash)
if(match) {
//login
}
Crypto 모듈 사용법
bcrypt 외에 정통의 crypto 암호화 사용법도 알고 싶다면 다음 포스팅을 참고하길 바란다.
# 참고자료
https://velog.io/@kylexid/%EC%99%9C-bcrypt-%EC%95%94%ED%98%B8%ED%99%94-%EB%B0%A9%EC%8B%9D%EC%9D%B4-%EC%B6%94%EC%B2%9C%EB%90%98%EC%96%B4%EC%A7%88%EA%B9%8C
인용한 부분에 있어 만일 누락된 출처가 있다면 반드시 알려주시면 감사하겠습니다
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.