비밀번호 단방향 암호화에 대하여

박상수
7 min readApr 18, 2020

일반적으로 비밀번호 암호화를 위해서 단방향 해시함수의 다이제스트(digest)를 저장 . KISA에서도 이렇게 가이드 하고 있다.

https://seed.kisa.or.kr/kisa/bbs/faq.do

현재 사용되고 있는 현황

KISA 개인정보의 암호화 조치 안내서(2017.01)
  • 공공기관과 민간기관의 사용 권고가 다르며, 공공기관의 경우 SHA224~512를 권고 하고 있으며, 국가정보원에서 권고 하고 있다.
  • 민간기관은 NIST(미국 국립표준기술연구소), KISA(한국인터넷진흥원), 유럽 ECRYPT, 일본 CRYPTREC 등 에서 SHA224~512, Whirlpool 을 권고 하고 있다.

단방향 암호화에 사용하는 해시함수

  • 수학적 연산을 통해 원본 값을 다른 값으로 변경
  • 원본 값에 유사한 값으로 해싱을 하여도 전혀 다른 값을 출력(avalanche)

해시함수 용도에 따른 분류

  • 메시지인증
    - 메시지 위변조 확인을 위한 난수생성
  • 키유도/난수생성용
    - 안전한 키와 랜덤한 난수를 생성
  • 메시지압축/전자서명용
    - 패스워드의 안전한 저장이나 효율적인 전자서명을 위해 난수생성

해시함수 문제점

  • 무차별 대입공격(brute-force attack)에 취약
    본래 해시함수란 해시값을 사용하는 자료구조로, 정렬을 하지 않고 빠른 검색, 삽입을 하려고 만듬.
  • 레인보우 공격(rainbow attack)
    - 항상 동일한 값을 갖는다면 탈취한 값을 기반으로 rainbow table을 만들어 이를 기반으로 공격
call hash('abcd');
-> 88d4266fd4e6338d13b845fcf289579d209c897823
call hash('abcd');
-> 88d4266fd4e6338d13b845fcf289579d209c897823
항상 같은 값일 경우 이를 테이블화 하여 공격 가능

해시함수 보완

  • salting
    - 임의의 문자열을 추가하여 암호화
    - 레인보우 공격(rainbow attack)을 기반으로 테이블을 만들어도 salting값을 알기 힘듬
call hash('abcd','saltingsalting');
->78D60DC052BDDB82F459FC6AAABE7F6B7E03D9B87773198586C10CCD63D72C52
  • key stretching
    - 생성된 다이제스트를 입력값으로 다이제스트를 생성 이를 반복, 키를 탈취하여도 동일 횟수만큼 반복하여 다이제스트를 해야 값이 일치 됨.
//첫번째 호출
String pwd = hash('abcd');
print pwd;
->78D60DC052BDDB82F459FC6AAABE7F6B7E03D9B87773198586C10CCD63D72C52
call isCheck(pwd);
-> true
//두번째 호출
String pwd = hash('abcd');
print pwd;
->E03D9B87773198586C10CCD63D72C5278D60DC052BDDB82F459FC6AAABE7F6B7
call isCheck(pwd);
-> true

일반적인 알고리즘

SHA256 / 512

SHA(Secure Hash Algorithm) 함수는 미국 국가안보국(NSA)이 1993년에 처음으로 설계, 미국 국가 표준으로 지정 SHA-224, SHA-256, SHA-384, SHA-512가 존재, SHA-0과 SHA-1이 있으나 폐기. 최근 SHA-2 함수군에도 SHA-1과 동일한 문제가 있다고 알려져 있다.(http://www.itworld.co.kr/news/108321)

PBKDF2(Password-Based Key Derivation Function)

PBKDF2는 NIST(National Institute of Standards and Technology, 미국표준기술연구소)에 의해서 승인된 알고리즘이고, 미국 정부 시스템에서도 사용자 패스워드의 암호화된 다이제스트를 생성할 때 사용한다.

  • 해쉬 컨테이너 알고리즘
  • 사람이 기억할 수 있는 암호 기반으로 랜덤키 생성
  • 입력한 암호 기반으로 salt를 추가 정해진 횟수 만큼 hash 수행

BCrypt

bcrypt는 Blowfish 암호에 따라 Niels Provos 및 DavidMazières에 의해 디자인 된 암호 해시 함수로 1999 년에 USENIX에서 발표되었습니다. 레인보우 테이블 공격으로부터 보호하기 위해 salt를 이용할 뿐만 아니라, 시간이 지남에 따라 반복 횟수를 늘려 늦출 수 있기 때문에 계산 능력이 증가해도 공격에 대한 내성을 유지할 수 있습니다.

bcrypt 함수는 OpenBSD 및 SUSE Linux 등의 일부 Linux 배포판을 포함하여 다른 시스템의 기본 암호 해시 알고리즘.

C, C ++, C #,Elixir, Go, Java, JavaScript, Perl, PHP, Python, Ruby 및 기타 언어에 대한 bcrypt 구현 수 있습니다.

SCrypt

PBKDF2와 유사한 Adaptive Key Derivation Function이며 Colin Percival이 2012년 9월 17일에 설계했다. 2016 년에 scrypt 알고리즘은 IETF에 의해 RFC 7914로 공개되었습니다.

구체적으로는 알고리즘은 다른 암호 기반 KDF(RSA Laboratories의 인기있는 PBKDF2 등)에 비해 많은 양의 메모리를 사용하도록 설계되어 있으며, 하드웨어 구현의 크기와 비용이 훨씬 높아지기 때문에 공격자가 사용할 수있는 병렬 처리의 양이 제한됩니다.

따라서 PBKDF2보다 안전하다고 평가되며 미래에 BCrypt에 비해 더 경쟁력있다고 여겨진다.

그래서..

공인된 기준 ISO-27001 준수하려면 PBKDF2, HMAC, SHA-256, SHA-512를 사용하면 된다.

더 강력한 패스워드 다이제스트를 구현하고 싶다면 BCrypt를 사용하면 된다.

구현하는 시스템이 매우 민감하고 비용 투자에 문제가 없으면 SCrypt를 사용하면 된다.

참고

--

--