Computer Science/보안 & 인공지능

해시함수와 암호화 비교하기(feat. 솔팅과 키스트레칭)

컴슈터 2023. 11. 25. 20:47

해시함수와 암호화 비교

해시(Hash)와 암호화(Encryption)의 가장 큰 차이는 '방향'이다. 

  • 해시 : 단방향 암호화이므로 복호화는 불가능하다. 데이터 보안에 중점을 둠.
  • 암호화 : 양방향 암호화이므로 복호화 가능하다. 통신에서 보안에 중점을 둠.

암호화의 목적은 반드시 복호화하는 것은 아니기 때문에, 각자 관점에 따라 둘 다 암호화라고 부르기도 한다. 예를 들어 암호화 해시 함수(cryptographic hash function)라는 개념이 있듯이 말이다. 그래서 해시를 암호화가 아니라고 할 필요는 없는 것 같다(?)

암호화

개인키 (Symmetric key)

다른 말로 대칭키, 비공개키, 비밀키라고 부른다. 암호화와 복호화할 때 같은 비밀키를 공유한다. 따라서 키가 유출되면 해킹 당할 수도 있다. 하나의 키를 사용하기 때문에 속도가 빠르지만, 어느 한 쪽이 생성한 키를 다른 한 쪽에게 안전하게 전달하는 것이 힘들다.

  • 개인키 종류 : DES, 3DES, AES, SEED 등

공개키 (ASymmetric key)

다른 말로 비대칭키라고 부른다. 암호화와 복호화할 때 두 개의 키를 사용한다. 암호화할 때는 공개키를 사용하고, 복호화할 때는 비밀키를 사용한다. 보내야 하는 데이터를 수신측의 공개키로 암호화를 걸어 놓고, 송신측이 자신의 비밀키로 복호화를 한다.

  • 공개키 종류 : DSA, RSA 등

 

해시함수(Hash Function)

해시함수는 체크섬(checksum)이라고 불린다. 해시함수는 메시지 인증과 무결성 체크를 위해 존재한다.

  • 해시함수 종류 : MD5, SHA 등

해시함수의 특징은 입력 값의 길이에 상관 없이 고정된 길이의 해시값(=다이제스트)이 출력된다. 입력 값의 일부만 변경되더라도 avalanche 효과로 전혀 다른 해시값이 출력되버린다. (>> 테스트 해보기)
앞서 말했듯이 해시함수는 단방향(one-way)이므로 복호화를 할 수 없다. 즉 암호화는 가능하지만 복호화는 불가능하기 때문에 원본을 알 수 없다. 그렇기 때문에 패스워드는 반드시 단방향 함수를 이용해야 한다.


해시함수의 문제점

1) 인식 가능성(recognizability)
메시지가 같으면 다이제스트도 같으므로, 다른 사용자랑 패스워드가 같으면 다이제스트도 같아서 한꺼번에 털릴 수 있다. 레인보우 공격(rainbow attack)을 당할 수 있다. 이는 rainbow table에 미리 해시해둔 패스워드를 잔뜩 가지고 있다가 훔쳐낸 패스워드와 비교하는 것이다.
2) 속도(speed)
해시 함수의 처리 속도가 빠르기 때문에 무차별 대입 공격(Brute force attack)을 당할 수 있다.


해시함수의 문제점 해결

1) 솔팅(Salting)
솔팅은 패스워드에다가 임의의 문자열인 salt를 추가하여 다이제스트를 생성하는 것이다. 솔팅의 목적은 salt를 이용해서 rainbow table을 무의미하게 만드는 것이며, salt는 최소 128bit 정도는 되어야 안전하다.

솔팅(salting)의 예시

이제 패스워드의 다이제스트를 알아버려도, salting된 다이제스트로는 해커가 패스워드 일치 여부를 알기가 매우 어렵다. 또한 사용자마다 각자 다른 salt를 사용한다면 패스워드가 같더라도 다이제스트가 다르게 생성된다.
2) Key Stretching(키 스트레칭)
키 스트레칭은 말 그대로 쭉 늘린다는 뜻이다. 해시를 여러번 반복하여 충~분히 시간을 늘림으로서 Brute force attack에 대비한다.

키 스트레칭(Key Stretching)의 예시

어떻게 시간을 늘리냐면, 패스워드의 다이제스트를 생성하고, 생성된 다이제스트를 입력 값으로 하여 다이제스트를 생성하고, 또 이를 반복(Iteration count)해서 다이제스트를 생성하는 식으로 늘린다. 보통 사용자가 작성한 패스워드가 짧거나 예측하기 쉬운 경우가 많은데 Key Stretching은 이를 더 어렵게 만들어 준다.

암호화 추천!

솔팅과 키 스트레칭으로 구성된 암호화 시스템을 구현하기 보다는 이미 잘 만들어지고 검증된 암호화 시스템을 사용하자. 암호화 시스템을 잘못 구현해서 발생하는 위험을 피할 수 있다.

  • PBKDF2 : 가장 많이 사용되며 Django에서 기본으로 사용 중이다. ISO-27001의 보안 규정을 준수하고 있다.
  • Bcrypt : 애초부터 패스워드 저장을 목적으로 설계되어 매우 강력한 패스워드 다이제스트를 생성하는 시스템을 쉽게 구현할 수 있다. 관련된 라이브러리도 언어별로 쉽게 찾을 수 있다.
  • Scrypt : 위 두 개보다 진보된 시스템이다. 만약 구현하려는 시스템이 매우 민감한 정보를 다루고, 보안 시스템을 구현하는 데 많은 비용을 투자할 수 있다면 사용한다.

References