-
[Password hashing] Argon2, Bcrypt, Scrypt, PBKDF2 소개Node.js/nest.js 2023. 3. 6. 23:34
Springboot를 사용하면서 비밀번호 해싱은 늘 BcryptPasswordEncoder만 복사 붙여넣기 형태로 사용했다.
Nest.js는 반면에 bcrypt, bcrypt.js, Scrypt, Argon2 등 passwordHash로 검색하면 나오는 라이브러리가 많아서 직접 알아봐야하는 상황이 있었다.
Spring Security의 공식 문서를 살펴보니 bcrypt, Scrypt, Argon2, Pbkdf2 등.. 다양하게 제공하고 있었다.
이참에 자세히 알아보자.
https://docs.spring.io/spring-security/reference/features/authentication/password-storage.html
Bcrypt가 무엇이고, 어떤 것을 사용하는 것이 좋은지 정리해본다.
결론부터 말하자면 MD5, SHA1, SHA-256, SHA-512는 사용하면 안되고, 가능하면 Argon2를 사용하자.
(특수 분야가 아닌 이상 계속 bcrypt 사용해도 2023년 지금은 괜찮은 것 같다.)비밀번호 암호화 하는 이유
- 인터넷 통신은 보안성이 보장되지 않기 때문에 해커나 악의적인 사용자가 비밀번호를 가로챌 가능성이 크다.
- 따라서, 비밀번호를 암호화하여 보안성을 높이는 것이 중요하다.
해시(Hash)란?
- 해시란 원형문자(plaintext)가 해시함수(해시 엔진)를 통과하여 암호화되어 나온 결과물
- 해시함수(해시엔진)를 통과하는 과정을 **해싱(hashing)**이라고 한다.
- 13 곱하기 29 가 무엇인지 누가 물으면 377 이라는 것을 금방 알 수 있다. 하지만 반대로 몇과 몇을 곱하면 377이 나오냐라고 물어보면 무수히 많은 경우의 수 가 있다. 이것이 해싱의 기본원리 이다.
해싱(Hashing)의 단점
- 원형문자가 같으면 해시 값도 같다.
- ex) md5라는 해시 엔진을 통과한 12345라는 비밀번호의 hash는 무조건 ”*827ccb0eea8a706c4c34a16891f84e7b”*이다. (비밀번호 정책이 존재하는 이유 !!)
- 이러한 해싱의 단점을 보완하기 위하여 플레인 텍스트에 랜덤의 문자열을 더 해준 뒤(salting) 해싱을 한다. 그리고 반복해서 여러번 암호화 하는 것을 Bcrypt가 수행한다.
- Hashing된 값을 복호화할 수 없기 때문에, 개인정보 유출 시 해싱 된 비밀번호가 그대로 노출될 위험이 있다.
Bcrypt
- 1999년 등장한 해싱 알고리즘으로 24년간 안전하게 사용되고 있다.
- 위에 언급한 salting 해싱 반복하는 기술이 동작원리다.
Scrypt
- 2009년 등장 Bcrypt 보다 설계를 개선했다. (특히 메모리 hardness <- 비전공자에게 이해하기 힘든 워딩...)
- 공격자가 메모리를 더 사용하게 해서 공격시 Bcrypt 공격의 4000배 비용이 든다고 한다.
Argon2
- 2012~2015년 Password Hashing Competition 우승한 암호화 세계의 강자 argon2
- bcrypt와 PBKDF2와 같은 아직 해싱 대표주자를 사용하기에도 무리 없지만, Argon2 발전하는 비밀번호 크래킹 기술에 대응하기 위해 등장했다.
- 무어의 법칙에 따르면 10년이 지나면 CPU, GPU 성능 개선이 해싱을 decode하기 더 쉽게 만들 것이고, MD5, SHA1, SHA-256, SHA-512 같은 알고리즘은 1초면 크래킹 될 것이라고 한다.
- 미래를 위해 등장한 해싱 알고리즘이다.
사용법
- 설치하기
https://www.npmjs.com/package/argon2
npm i argon2
- passwordEncoder 구현
import * as argon from 'argon2'; export class PasswordEncoder { static encode(password: string): Promise<string> { return argon.hash(password); } static async compare( rawPassword: string, encodedPassword: string, ): Promise<boolean> { return await argon.verify(encodedPassword, rawPassword); } }
- 로그인 컨트롤러
async signup(request: UserSignUpRequestDTO) { const passwordHash = await PasswordEncoder.encode(request.password); return this.userRepository.save(request.toUser(request, passwordHash)); }
Java 에서도 Argon2를 사용할 수 있다.
Reference 자바 Argon2 참조Reference
반응형'Node.js > nest.js' 카테고리의 다른 글
[nestjs] env파일로 관리하던 환경변수를 yaml파일로 관리하기 (0) 2023.07.02 nest.js 학습에 사용한 공부 자료 (0) 2023.03.23 백앤드에게 Event Loop란 무엇인가.(브라우저, Nest js, SpringBoot) (0) 2023.03.08