Today
-
Yesterday
-
Total
-

ABOUT ME

-

  • JAVA | 비밀번호의 암호화 (SHA, SALT)
    ▼ Backend/자바 (JAVA) 2021. 8. 19. 14:56
    반응형

    ▶ SHA(Secure Hash Algorithm)

    비밀번호 암호화로 단방향 암호화 기법을 많이 사용하는데 그중에서도 SHA에 대해 알아본다.

     

    대분류 중분류
     MD 길이  블록 길이  최대 메시지 길이  대표 알고리즘 
     해쉬 알고리즘
     (Hash Algorithm)
    SHA-1  160bit  512bit  2^64-1bit  SHA-1
    SHA-2  224bit  512bit  2^64-1bit  SHA-224
    SHA-2  256bit  512bit  2^64-1bit  SHA-256
    SHA-2  384bit  1024bit  2^128-1bit  SHA-384
    SHA-2  512bit  1024bit  2^128-1bit  SHA-512

     

    ▶ 왜 단방향 암호화를 사용할까?

    단순한 이유는 시스템이 사용자의 비밀번호의 원본 데이터를 알아야 할 필요가 없고, (개인정보, 보안상의 이유도 양방향 암호화를 사용하여 비밀번호를 저장하여 사용중에 탈취되었을 때 복호화되어 다른 시스템에서 악용될 수 있는 2차 문제를 사전에 방지하기 위해서이다.

     

    ▶ 단방향 암호화의 사용

    SHA 계열의 해시함수를 통해 사용자의 비밀번호를 해싱하여 나온 해시값을 데이터베이스에 저장해두었다가, 사용자가 로그인 시도를 할 때 입력한 비밀번호를 해싱하여 나온 해시값과 비교하여 검증하게 된다.

     

    ▶ 문제의 발견

    이러한 과정에서 문제가 발생했다. 데이터에 따른 동일한 해시값이 나온다는 것을 이용하여 많은 비밀번호 조합에 대해 해시를 사전에 연산한 후 레인보우 테이블(rainbow table)이라는 곳에 미리 적재해 놓은 후 해시값을 발견하면 색인을 수행해 동일한 해시와 일치하는지 확인하는 것이다.

     

    ▶ 문제의 해결

    문제를 해결하기 위해서 나온 방법 중에 하나는 데이터를 해싱하기 전에 임의의 값(salt)을 붙여서

    해싱을 수행하는 것이다. 

     

    *임의의 값(salt)을 최소 16글자 길이로 하면 평문 문자열의 복잡성과 길이가 크게 증가한다고 한다.

     

    이러한 임의의 값은 파일 시스템 권한으로 보호되는 애플리케이션 구성 파일 또는 HSM(Hardware Security Module)등의 안전한 장소에 보관한다.

     

    ▶ 해시란?

    임의의 크기를 가진 데이터를 고정된 데이터의 크기로 변환시키는 것을 말한다.

     

    HashEncryptionUtil.java

     

    package com.melon.boot.util;
    
    import java.math.BigInteger;
    import java.security.MessageDigest;
    
    public class HashEncryptionUtil {
        public static String encryptSHA256(String password, String salt) throws Exception {
        	if (password != null && salt != null) {
        		// MD2, MD4, MD5, SHA-1, SHA-256, SHA-512
        		MessageDigest md = MessageDigest.getInstance("SHA-256");
        		
        		md.reset();
        		
        		// salt 바이트 데이터를 사용해 다이제스트를 갱신
        		md.update(salt.getBytes()); 
        		
        		// 바이트배열로 해쉬를 반환, 패딩 등의 최종 처리를 행해 해시 계산을 완료
        		byte[] digested = md.digest(password.getBytes()); 	
        		
        		return String.format("%064x", new BigInteger(1, digested));
        	} else {
        		return "";
        	}
        }
    }
    반응형

    댓글

Designed by Tistory.