일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- rx
- list
- mvvm
- Observable
- Koin
- node
- junit
- paging
- node.js
- 동영상
- MotionLayout
- Animation
- liveData
- Android 13
- Reactive
- SwiftUI Tutorial
- google play
- GCP
- RxKotlin
- 인앱결제
- Android
- Kotlin
- MediaPlayer
- databinding
- android13
- SWIFTUI
- PagingLib
- mysql
- MediaSession
- 테스트 자동화
- Today
- Total
봄날은 갔다. 이제 그 정신으로 공부하자
패스워드 암호화 본문
패스워드 암호화라…
음…
이걸 어떻게 설명해야 좋으려나…
고민 끝에 이렇게 시작해 봅니다.
패스워드 암호화 어떤 것이 좋을까요?
개발을 하다보면 어쩔수 없이 회원의 개인정보를 저장해야 할 상황이 생겨버립니다.
그렇다고 회원 가입을 막을 수도 없고, 개인 정보를 저장하지 않을 수도 없고…
개인정보를 저장하려면 암호화해서 저장해야 하는데 어떤 암호화 알고리즘을 사용해야 하지?
암호화 알고리즘도 완벽하지 않다고 하던데… 내가 사용한 알고리즘이 보안에 취약하면 어떻게하지?
개인정보를 암호화해서 사용하면 서비스가 느려지지 않을까?
모든 개인정보를 다 암호화해야 하나?
고민하다보면 정말 끝없는 의문속에 휩싸이게 됩니다.
그리고 암호화에 대해 공부좀 해볼까 하고 파고 들려고 알아보면 엄청나게 많은 암호화 알고리즘의 종류에 기가 질리게 됩니다.
저도 푸릇푸릇한 뉴비개발자 시절에 암호화의 매력에 빠져 이것 저것 공부했었던 기억이 나네요… ㅠ_ㅠ
아쉽게도 대칭키 암호 알고리즘이니 공개키 암호 알고리즘이니 하는 것은 이번 글의 주제가 아닙니다.
이번 글에서는 제목대로 개인정보 중 가장 중요한 패스워드 암호화에 대해 설명하겠습니다.
패스워드 암호화
회원이 자신의 패스워드를 까먹은 상황을 가정해보겠습니다.
오랜만에 로그인 시도를하던 회원은 자기가 패스워드를 까먹었다는 것을 인지하고 이를 해결하기 위해 서비스에서 지원하는 비밀번호 찾기 기능을 선택해 비밀번호 찾기를 시도합니다.
핸드폰번호를 이용해 자신임을 인증하고 비밀번호 찾기를 완료했더니…
왠걸!!! 예전에는 내가 까먹은 패스워드가 핸드폰으로 왔었는데…
요즘은 임시 패스워드가 옵니다. 왜 그럴까요?
예전 서비스들은 암호화된 비밀번호를 관리자가 복호화키를 알고 있어 이를 사용해 복호화 가능한 방식을 사용했기 때문 입니다. (모두 그런건 아닙니다.)
이 방식을 사용하면 사용자들이 패스워드를 까먹었을 때 이전 패스워드를 알려줄 수 있다는 장점이 있지만 관리자가 관리하는 복호화키가 해커에게 노출된다면 모든 회원의 정보가 Open되는 대참사가 발생할 우려가 있는 단점이 있는 방식이었습니다.
그에 비해 비밀번호 찾기 시 임시 패스워드를 발급하는 방식은…
서비스 관리자도 사용자의 패스워드를 모르기 때문에(정확히는 알 방법이 없기 때문에) 새로운 패스워드를 랜덤하게 생성해 사용자에게 알려주는 방식 입니다. (더욱 보안에 신경 쓰는 서비스는 임시 패스워드로 로그인 시 패스워드를 변경하도록 유도합니다.)
아무리 암호화 했다고 해도 관리자가 사용자의 비밀번호를 모른다니? 얼핏 들으면 잘 이해가 가지 않지만 해시 함수를 사용한 암호화 알고리즘을 사용하면 패스워드는 회원 본인만 알고 관리자도 시스템도 알 수가 없기 때문에 회원이 비밀번호 찾기 시 해당 회원이 맞는지 검증한 후 맞다면 새로운 패스워드를 회원 정보를 갱신하고 이를 회원에게 전달하는 방식을 사용하는 것 입니다.
해시함수를 사용한 방식은 관리자도 비밀번호를 모를 정도로 보안성이 높고 만에 하나 해커에게 회원 DB가 털리더라도 해커는 다시 회원의 정보를 하나하나 다시 찾아야 하는 번거로움을 감수해야만 하는 매우 보안성이 높은 방식입니다.
관리자도 모를 정도로 보안성이 높은 해시 함수를 사용한 암호화에 대해 설명하기 전에 우선 해시 함수를 사용한 암호화 알고리즘에 대해 설명해야 할 필요가 있습니다.
해시 함수란?
해시 함수는 값을 입력받아 고정된 길이의 해시값을 출력하는 함수로 같은 입력에 대해서는 항상 같은 출력이 나오지만 출력을 가지고 역으로 입력값을 도출할 수는 없습니다.
이러한 해시함수를 사용하는 목적은 메시지의 오류나 변조를 탐지할 수 있는 무결성을 제공하기 위해 사용됩니다.
해시함수는 아래와 같은 특징을 가지고 있습니다.
- 어떤 입력 값에도 항상 고정된 길이의 해시값을 출력한다.
- 입력 값의 아주 일부만 변경되어도 전혀 다른 결과 값을 출력한다.
- 출력된 결과 값을 토대로 입력값을 유추할 수 없다.
위의 특징들로 인해 해커는 해시값을 가지고 입력값의 길이 등과 같은 대략적인 특징을 유추 할 수 없다는 장점이 있습니다.
예를 들어 AAA라는 값과 programmerAndPRogramme 값을 해시 함수를 사용해 돌리면 각각은 아래와 같은 해시값을 도출합니다.
“$2a$10$AhsgPJZisNv1koLiEjac9eLkqqFq2YIW88bLTpo3RPcgn3zSeAeKO”
“$2a$10$XRgtKtAqwaiQ4Z87WV3ot.zJ94E.rtgcr46WNgOldlezi6rpUn2W6”
보는 것과 같이 어떤게 AAA로 부터 나온것이고 어떤게 programmerAndPRogrammer로부터 나온것인지 전혀 짐작할 수 없습니다.
한가지 확실한 것은 AAA를 해시함수에 넣으면 동일하게 “$2a$10$AhsgPJZisNv1koLiEjac9eLkqqFq2YIW88bLTpo3RPcgn3zSeAeKO”
값을 출력하므로 출력되는 해시값의 결과를 비교해 패스워드 일치여부를 판별할 수 있는 것 입니다.
해커가 고생 고생해서 고객 DB를 획득한다고 해도 고객 각각의 패스워드는 해시 알고리즘으로 암호화 되어 있기 때문에 동일한 해시키가 나올때까지 고객 각각에 대해 어마어마한 연산을 계속 반복해야 합니다.
해커 입장에서는 정말 비효율의 극치라고 할 수 있습니다.
자 그럼 이런 해시함수를 사용한 알고리즘에는 어떤 것들이 있을까요?
순서대로 알아보겠습니다.
우선 MD5부터
MD5는 Message-Digest algorithm 5의 약자로 128비트 암호화 해시 함수로 1991년 MD4를 대체하기 위해 로널드 라이베스트가 고안했습니다. 그런데 1996년 MD5의 설계상 결함이 발견되었습니다. 치명적인 결함은 아니었지만, 암호학자들은 해시 용도로 SHA-1과 같은 다른 안전한 알고리즘을 사용할 것을 권장하기 시작했고 이후 2004년에 더욱 심한 암호화 결함이 발견되었고. 2006년에는 노트북 컴퓨터 한 대의 계산 능력으로 1분 내에 해시 충돌을 찾을 정도로 빠른 알고리즘이 발표되기도 하였습니다.
이와 같다보니 현재 MD5 알고리즘을 보안 관련 용도로 쓰는 것은 권장하지 않으며, 사용하게 된다면 심각한 보안 문제를 야기할 수도 있습니다. MD5는 주로 프로그램이나 파일이 원본 그대로인지를 확인하는 무결성 검사 등에 사용됩니다.
위 설명한 것 처럼 MD5는 1996년 최초 설계상의 결함이 발견된 이후부터 빠르게 SHA 계열 암호화 알고리즘으로 전환되기 시작하였습니다.
그럼 SHA 알고리즘이란?
SHA는 Secure Hash Algorithm의 약자로 이걸 풀이하면 안전한 해시 알고리즘이라는 뜻 입니다.
SHA 함수들은 서로 관련된 암호학적 해시 함수들의 모음으로 이들 함수는 미국 국가 안보국이 1993년 처음 설계하였으며 이후 미국 국가 표준으로 지정될 정도로 보안성이 뛰어난 해시 알고리즘 입니다.
SHA 함수군에 속하는 최초의 함수는 공식적으로 SHA라고 불리지만, 나중에 설계된 함수들과 구별하기 위하여 SHA-0이라고도 불립니다.
2년 후 SHA-0의 변형인 SHA-1이 발표되었으며, 그 후에 4종류의 변형 SHA-2(SHA-224, SHA-256, SHA-384, SHA-512)가 더 발표되었습니다.
SHA-1은 SHA 함수들 중 가장 많이 쓰이며, TLS, SSL, PGP, SSH, IPSec 등 많은 보안 프로토콜과 프로그램에서 사용되고 있습니다.
위에 언급한대로 SHA-1은 이전에 널리 사용되던 MD5를 대신해서 쓰이기도 하지만 좀 더 보안을 요구하는 곳에는 SHA-2계열의 SHA-256이나 그 이상의 알고리즘을 사용할 것을 권장합니다.
그 이유는 SHA-0과 SHA-1에 대한 공격 취약점이 이미 발견되었기 때문 입니다.
SHA-2에 대한 공격 취약점은 아직 발견되지 않았으나, 전문가들은 SHA-2 함수들이 SHA-1과 비슷한 방법을 사용하기 때문에 공격 취약점이 발견될 가능성이 높다고 지적하고 있습니다.
또한 SHA 계열의 해시 함수는 빠른 연산이 가능하므로 GPU의 연산속도가 빠를수록 공격자의 하드웨어를 통한 오프라인 brute force에 더 취약하게 되는데 이는 빠른 해시를 사용하여 해커가 오프라인 공격으로 초당 수십억개의 해시를 계산할 수 있기 때문입니다.
앞서 해시 함수 알고리즘에서 해커가 고객 각각에 대해 반복적으로 해시 함수에 해당하는 값을 찾는 연산을 계속 반복해야 한다고 하였는데 CPU의 성능이 좋으면 연산 속도가 빨라져 금방 찾을 수 있는 문제점이 생길 수 있습니다.
그럼 해커가 오래 걸리게 연산 속도를 떨어뜨리면 되지 않을까요?
Bcrypt란?
Bcrypt는 Blowfish 암호에 기반을 둔 해시 함수로 1999년 USENIX에서 발표되었으며 Bcrypt 함수는 OpenBSD 및 수세 리눅스 등의 일부 리눅스 배포판을 포함한 기타 시스템용 기본 암호 해시 함수 입니다.
Bcypt 암호화 해시 알고리즘의 큰 특징은 SHA 계열에서 약점으로 지적된 빠른 연산으로 인한 brute force 공격에 대한 대비책으로 Blowfish의 특징 중 하나인 key setup phase 라는 일종의 막대한 전처리 요구(Salt)로 느리게 만들고 반복횟수(Key Stretching)를 변수로 지정가능하게 하여 작업량 (=해싱시간) 을 조절할 수 있게 하였습니다.
Bcrypt 암호화에 대해 조금 더 자세히 설명하도록 하겠습니다.
Bcrypt 해시 알고리즘에 대해 자세히
Bcyrpt 해시 알고리즘은 brute force 공격에 대비책으로 막대한 전처리 요구(Salt)와 반복 횟수를 변수로 지정하여 작업량을 조절한다고 하였는데 하나하나 풀어서 자세히 설명하면 다음과 같습니다.
설명을 용이하게 하기 위해 우선 해커가 Output(Digest) 값을 탈취한 상태라로 가정하도록 하겠습니다.
사용자의 패스워드 ”AAA”를 일반적인 해시 함수를 사용해 암호화 한다면 다음 그림과 같습니다.
해커는 이제 무작위로 값을 넣어 드디어 찾아내야 합니다.
만약 해커가 고성능의 CPU를 보유하고 있다면 조금 빨리 찾아낼 수 있습니다.
Bcrypt 해시 알고리즘은 여기에 아래와 같이 전처리 과정(Salt)와 반복횟수를 더합니다.
이렇게 하게 되면 이제 해커는 Output(Digest)만을 가지고 패스워드를 찾아낼 수 없습니다.
Bcrypt 해시 알고리즘이 반복횟수(Key Stretching)를 변수로 지정가능하게 하여 작업량 (=해싱시간) 을 조절했기 때문에
우리의 의지의 해커 DB 서버를 해킹해 사용자 비밀번호 정보들을 알아내기 위해 다시한번 노력해 봅니다.
우선 DIGEST값을 분석해보기로 합니다.
식별자를 포함하여 앞의 세자리 중 두자리(2a)는 해시 알고리즘 식별자라는 것을 파악했고 cost factor로 반복 횟수도 확인했고...
어라? 반복 횟수가 1백만번... 이거 엄청 오래 걸리겠는데...
어...
랜덤 솔트도 난감한데.... 반복 횟수까지...
Bcrypt 해시 알고리즘에는 반복횟수(Key Stretching)를 변수로 지정하여 작업량을 늘리기 때문에 해커가 가진 엄청난 성능의 CPU도 어마어마하게 오랜 시간이 걸린다는 것을 파악했습니다.
우리의 의지의 해커 이건 의지만으로는 안된다는걸 깨닭고 드디어 포기합니다…
Bcrypt는 이런식으로 패스워드를 지키는 알고리즘으로 다른 알고리즘에 비해 상대적으로 안전하다고 할 수 있습니다.
정리
해시 함수 알고리즘을 사용하여 패스워드를 암호화하면 사용자 외에는 아무도 패스워드를 알 수 없습니다.
Bcrypt 해시 함수 알고리즘을 사용한 패스워드 암호화는 단순히 해시 함수를 통함 암호화만을 지원하는 것은 아닙니다.
해커에게 모든 정보가 노출되었을 때에도 패스워드를 안전하게 지키기 위해 막대한 전처리 요구(salt)와 반복 횟수(count)를 변수로 지정하여 작업량 늘려 패스워드를 찾기 힘들도록 강제할 수 있습니다.
'보안' 카테고리의 다른 글
개인정보 보호법과 개인정보 암호화 방법 (0) | 2022.01.05 |
---|---|
패스워드 암호화에 적합한 해시 함수들 (0) | 2021.12.29 |
내가 만든 앱은 내가 지키자! (앱 위변조 방지) 3/3 (0) | 2021.12.01 |
내가 만든 앱은 내가 지키자! (루팅감지, 디버깅감지) 2/3 (1) | 2021.11.15 |
내가 만든 앱은 내가 지키자! (시큐어 코딩, 난독화) 1/3 (1) | 2021.11.10 |