본문 바로가기
알고리즘

[암호화] SHA-256 해시 함수

by 코린이 프로도 2022. 12. 28.
반응형

  오늘은 SHA-256 해시 알고리즘을 다뤄보려고 한다. 

 

암호화에 대한 기본 개념은 이전 글을 참고 바랍니다. 

2022.11.28 - [알고리즘] - 암호화

 

암호화

서비스를 제작할 때 암호화 알고리즘을 사용하는 경우는 많이 있다. 누구나 접근 가능한 서버와 통신을 하는 경우 통신 과정에서 데이터를 노출하지 않도록 암호화를 한다. 또 로그 파일이나 DB

corinprodo.tistory.com

아래 사이트를 참고했다.

http://wiki.hash.kr/index.php/SHA256

 

SHA256 - 해시넷

SHA-256은 SHA(Secure Hash Algorithm) 알고리즘의 한 종류로서 256비트로 구성되며 64자리 문자열을 반환한다. SHA-256은 미국의 국립표준기술연구소(NIST; National Institute of Standards and Technology)에 의해 공표된

wiki.hash.kr

 

SHA-256

 Secure Hash Algorithm의 약자로 256비트로 구성되어 이 알고리즘을 통해 암호화를 하면 총 2의 256승 만큼의 경우의수를 표현할 수 있다. 문자열로는 64자리 문자열을 나타낸다. 미국 국립표준기술연구소(NIST; National Institute of Standards and Technology)에 의해 공표된 표준 해시 알고리즘인 SHA-2 계열 중 하나이며, 최근에는 블록체인 기술에서도 심심찮게 접할 수 있는 알고리즘이다.

이제 중요한 특성을 간략하게 정리해 보겠다.

특성

  • 단방향 알고리즘이다. (복호화가 되지 않는다.)
    • 위와 같은 특성 때문에 서비스에서는 복호화할 필요가 없는 개인정보에 주로 사용한다.
  • 같은 입력값에 대해 같은 출력값을 제공한다.
    • 다른 입력값에 대해 출력값이 같은 경우를 충돌이라고 하는데, 이는 발생할 확률이 지극히 낮고, 현재까지 안전성 문제에서도 큰 단점이 발견되지 않았다. 
    • 따라서, 데이터의 변경 여부를 파악하는데 사용한다. 
  • 연산 속도가 빠르다
    • 암호화된 값을 찾는데도 연산이 빠르기 때문에 검증 횟수를 제한하는 등의 조치가 필요하다.
  • 안전성이 높다.
    • 구글 클라우드 서버 기반으로 연구한 사례로 900경의 해시 연산을 통해 충돌이 발견된 경험이 있다고 한다.
    • 양자 컴퓨터가 출시되지 않는 한 최소 10년은 안전하다고 판단할 수 있다고 한다.

 

Java 예제

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHATest{
	public static void main(String[] args) throws Exception {
		
        public static String encrypt(String plainText) throws NoSuchAlgorithmException {
        	MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(plainText.getBytes(StandardCharsets.UTF-8));
            
            StringBuilder sb = new StringBuilder();
            
            byte[] bytes = md.digest();
            for(byte b : bytes) {
            	builder.append(String.format("%02x", b));
            }
            
            return sb.toString();
        }
	}
}

 

java.security 패키지의 MessageDigest 클래스를 이용해 SHA-256 암호화를 할 수 있다.

String.format 함수를 이용해서 byte를 hex 문자열로 표현하는 것이다. 이 때 x를 대문자 X로 쓰면 hex도 대문자로 출력된다. 

 다만 위 예시에서 문제될 수 있는 점은 평문의 길이가 짧거나 예상 가능한 경우 이미 원본에 대한 해시값이 1:1로 매핑된 데이터베이스가 있다면 위험할 수 있다는 것이다. 이를 레인보우 테이블이라고 한다. 

 

 이를 보완하는 방법이 평문에 salt를 합친 문자열을 암호화 하는 것이 있다. 

salt는 해시 함수에서 digest를 생성할 때 추가되는 임의의 문자열이다. 원본에 추가해서 암호화하기 때문에 위에서 말한 레인보우 테이블에 포함될 가능성이 줄어들고 안전해진다.

 예를 들어 비밀번호를 평문이라고 한다면, 랜덤한 문자열 salt를 만들고 합하여 암호화한 뒤 DB에 저장하는 것이다. 이때 생성한 salt도 다른 곳에 저장해야 다시 비밀번호 일치여부를 확인할 때 암호화하여 DB에 저장된 것과 일치하는지 확인할 수 있다. 

 아래는 salt를 적용한 예시이다.

Salt 포함 예제

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHATest{
	public static void main(String[] args) throws Exception {
		
        public static String encrypt(String plainText) throws NoSuchAlgorithmException {
        
        	SecureRandom random = new SecureRandom();
            byte[] saltBytes = new byte[16]
            random.nextBytes(saltBytes);
            
        	StringBuilder saltSb = new StringBuilder();
            for(byte b : saltBytes) {
            	saltSb.append(String.format("%02x", b));
            }
            
            
        	MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(saltSb.append(plainText).toString().getBytes(StandardCharsets.UTF-8));
            
            StringBuilder sb = new StringBuilder();
            
            byte[] bytes = md.digest();
            for(byte b : bytes) {
            	builder.append(String.format("%02x", b));
            }
            
            return sb.toString();
        }
	}
}

 

 

오늘은 이만 끝!

반응형

'알고리즘' 카테고리의 다른 글

[암호화] SEED 암호화  (0) 2022.12.11
암호화  (0) 2022.11.28