“비밀번호 해싱“은 보안을 강화하기 위해 사용되는 기술 중 하나로, 사용자의 비밀번호를 안전하게 저장하는 방법입니다. 기본 아이디어는 일방향 함수를 사용하여 비밀번호를 변환하고, 이 변환된 값(해시)을 저장하는 것입니다.
사용자가 웹사이트나 앱에서 새 계정을 만들 때마다 사용자 이름과 비밀번호는 일반 텍스트 형식으로 저장되지 않습니다. 예를 들어 사용자 이름 netflix_user1 및 iLoveWatch1ngCom3dy를 비밀번호로 사용하여 Netflix에서 계정을 생성하는 경우 비밀번호는 실제로 데이터베이스에 그대로 저장되지 않습니다. 개발자들은 보통 수학적 알고리즘을 통해 이 비밀번호를 원래의 형태와 전혀 다르게 보이는 것으로 변환하는 기능을 실행합니다.
이 프로세스를 해싱이라고 하며 수학적 알고리즘을 해싱 알고리즘이라고 합니다.
비밀번호 해싱 특징 : 일방향 함수
비밀번호 해싱은 일방향 함수를 사용합니다.
이는 한 번 해싱된 값에서 원래 데이터로 역으로 돌아갈 수 없다는 뜻 입니다.
같은 비밀번호를 입력하면 해시 함수를 통과한 결과는 항상 동일합니다.
비밀번호 해싱의 목적
사용자의 실제 비밀번호를 저장하지 않고, 해시 값만 저장하여 보안을 강화합니다.
데이터베이스가 침입 당해도 사용자의 실제 비밀번호를 획득하기 어렵습니다.
해커는 해시를 획득하더라도 이를 사용하여 로그인할 수는 없습니다.
암호화와의 차이
암호화는 양방향이며, 키를 사용하여 원래 데이터로 돌아갈 수 있습니다.
하지만 비밀번호 해싱은 일방향이므로 역으로 돌아가는 것이 불가능합니다.
비밀번호 해싱은 사용자 계정의 보안을 강화하고, 악의적인 공격으로부터 비밀번호를 보호하는 데 중요한 역할을 합니다.
해싱을 인증에 사용하는 방법
사용자가 계정을 생성하고 비밀번호를 입력하면 애플리케이션은 해당 비밀번호를 해시 함수를 통해 저장합니다.
사용자가 로그인할 때마다 입력된 비밀번호를 다시 해시하여 데이터베이스에 저장된 값과 비교하여 인증합니다.
대표적 해싱 알고리즘
알고리즘 | 역사 | 보안 강도 | 원리 |
---|---|---|---|
MD5 | 1991년에 발표 | 취약 (현재 권장되지 않음) | 블록 단위 처리, 중간 결과 계산, 단방향 알고리즘 |
SHA-1 | 1995년에 발표 | 취약 (현재 권장되지 않음) | 블록 단위 처리, 중간 해시 값을 갱신하여 최종 해시 값 생성 |
bcrypt | 1999년에 소개 | 안전 | Blowfish 암호 기반, 솔트와 고비용 함수 적용 |
SHA-256 | 2001년에 나온 SHA-2 계열 중 하나 | 안전 | 블록 단위 처리, 중간 해시 값을 갱신하여 최종 해시 값 생성 |
SHA-3 | 2015년에 나온 SHA-3 | 안전 | 스폰지(Sponge) 구조 사용, 입력 데이터를 흡수와 비밀 단계로 나눔 |
BLAKE2 | 2012년에 발표 | 안전 | Merkle–Damgård 구조 기반, 입력 데이터 블록 단위 처리, 최종 해시 값 생성 |
Argon2 | 2015년 Password Hashing Competition에서 우승 | 안전 | 비밀번호 해싱에 특화, 입력 데이터와 솔트 결합, 블록 단위 처리, 메모리 요구량과 시간을 조절하는 매개변수 사용 |
해시된 비밀번호의 한계 : 레인보우 테이블 공격
해커는 일치하는 항목을 찾을 때까지 해시 함수를 통해 무작위 비밀번호를 실행하여 무차별 공격을 시도할 수 있습니다.
이런 프로세스는 지루하고 길기 때문에 이는 다소 비효율적입니다. 그럼에도 불구하고 해커는 결국 충분한 시간을 들여 코드를 해독할 수 있습니다
이런 비효율성을 개선한 것이 레인보우 테이블 공격입니다.
미리 계산된 해시 값을 포함하는 테이블을 사용하여 해시 값을 빠르게 역으로 찾는 공격 방법입니다.
위에서 언급한 공격으로부터 사용자 비밀번호를 보호하기 위해서는 비밀번호 솔팅이라는 추가 단계가 수행됩니다.
비밀번호 해킹을 어렵게 하는 방법
솔트
솔트는 해싱을 진행하기 전에 비밀번호에 무작위로 생성된 32개 이상의 난수를 추가하는 것입니다.
이를 통해 동일한 비밀번호를 가진 사용자도 각자 고유한 해시 값을 갖게 됩니다.
Salt가 작동 하는 예
Michael과 Bob은 우연히 동일한 비밀번호 s@1t3dH@shBrown을 사용한다고 하면 $2a$12$xdWgQ5mhv8rSaUK3qdusTO4XdMFbQi6TD/1VvOZjvGm10RXnhZZa2라는 동일한 해시도 갖게 됩니다.
그러나 Michael의 비밀번호가 Iwx2ZE로 솔트 처리되고 Bob의 비밀번호가 0DoVej로 솔트 처리된 경우 완전히 다른 솔트 처리된 해시를 갖게 됩니다.
Michael 비밀번호: s@1t3dH@shBrown
Michael 솔트: Iwx2ZE
Michael 솔트 입력: Iwx2ZEs@1t3dH@shBrown
Michael 솔티드 해시 출력: $2a$12$TGRg8FCZvnDm.f4WPNtWQucwRv5zsi4D9Qy/gYgpfFfYx9XpXdE6a
Bob 비밀번호: s@1t3dH@shBrown
Bob 솔트: 0DoVej
Bob 솔티드 입력: 0DoVejs@1t3dH@shBrown
Bob 솔티드 해시 출력: $2a$12$VtpXTHf69x1db/71bGHl3eMiEDAkgQe/Gq6UeNOKuHvdg.WnIXEHa
동일한 비밀번호에 대해 동일한 해시 값이 생성되는 것을 방지하여 무차별 대입 공격을 어렵게 만듭니다.
그러나 데이터베이스 전체가 해킹되면 솔트 정보도 함께 노출될 수 있습니다.
솔트를 사용함으로써 해커는 각 사용자에 대해 개별적으로 무차별 대입 공격을 수행해야 하므로, 동일한 비밀번호를 가진 사용자들에 대한 패턴이 쉽게 발견되지 않습니다. 이는 보안을 더 강화하는 데 도움이 됩니다.
페퍼
페퍼는 모든 사용자에게 동일한 값을 가지며, 솔트와 달리 데이터베이스에 저장되지 않습니다.
일반적으로 안전한 장소(예: HSM 또는 애플리케이션의 설정 파일)에 저장됩니다.
페퍼는 데이터베이스를 획득한 공격자가 솔트를 알더라도 원본 비밀번호를 알기 어렵게 만듭니다. 페퍼를 알아내기 위해서는 물리적인 액세스가 필요하며, 데이터베이스만 획득한 상황에서는 페퍼를 알아내기 어렵습니다.
페퍼는 주로 애플리케이션의 코드나 설정 파일에 저장되어 있으며, 암호화된 연산에 사용됩니다. 페퍼가 공개되면 안되므로 안전한 장소에 보관되어야 합니다.
솔트와 페퍼의 협업
솔트와 페퍼를 함께 사용하면 해시된 비밀번호를 보다 강력하게 보호할 수 있습니다. 솔트는 사용자 간에 차이를 주어 무차별 대입 공격을 방지하고, 페퍼는 공격자가 데이터베이스를 획득해도 원본 비밀번호를 어렵게 만듭니다.
이런 협업으로 인해 비밀번호 보안이 강화되며, 사용자 데이터가 안전하게 저장됩니다.