웹 개발/Java

[JAVA] 비밀번호 암호화 SHA-256 알고리즘 / 레인보우 테이블 / Salt

개발 기록 2024. 2. 23. 18:02

 

SHA-256 (Secure Hash Algorithm -256)

: 해시값을 이용한 암호화 방식 중 하나로 단방향 알고리즘이다.

: 원본 데이터를 복구할 수 없는 형태로 변환하기 때문에 패스워드같은 민감한 정보의 보안에 적합하다.

 

단방향이란?

: 암호화는 가능하지만 복호화(해석)가 불가능한 것을 뜻한다.

 

일반적으로 abc라는 값을 SHA256 알고리즘을 적용하면' 2cskk32ke33j...' 와 같은 64자(256비트 길이)의 문자열로 반환된다.

abc가 암호화된 값과 abcc가 암호화된 값은 한글자라도 매우차이나므로 암호화된 값으로 원래의 값을 유추할 수 없어서

비밀번호(패스워드)를 암호화할 때 널리 사용되었으며 암호화된 값을 DB에 넣고 로그인 할 때 사용자가 입력한 비밀번호를 암호화하여 DB에 들어가있는 값을 비교하여 로그인 성공 여부를 결정했다.

 

그러나 레인보우 테이블이라는 것이 생기고 나서 암호화된 문자열로 원래의 문자열이 무엇인지 알 수 있게 되었다.

 


 

레인보우 테이블이란?

: 원본 문자열과 암호화된 해시값을 Key - Value 한 쌍의 형태로 저장해놓은 테이블

 

레인보우 테이블에 수많은 데이터들이 쌓여서 암호화된 값으로 원본 값을 알아낼 수 있게 된것이다.

이러한 일이 생기자 해킹을 방지하기 위해 Salt 라는 방법이 등장했다.

 


 

Salt란?

: 레인보우 테이블은 쌓인 데이터를 이용해서 원래의 값을 알아내는 방법이다. 

즉 내 비밀번호등의 원본 문자열이 길고 복잡하다면 레인보우 테이블에 존재할 가능성이 현저히 낮아진다.

 

이러한 점을 이용하여 원본 문자열에 랜덤 문자열(Salt)을 합치고 SHA256 알고리즘에 적용시킨다.

즉 Salt는 랜덤 문자열이다. 

일반적으로 아이디를 이용하여 Salt값을 정한다고 한다.

=> User 테이블에 Salt 컬럼이 필요하다.

 


 

예제 ( Salt + SHA256 암호화)

 

// 암호화
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
// log 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Encrypt {

	private static final Logger logger = LoggerFactory.getLogger(Encrypt.class);
    
	public static void main(String[] args) {
		
		Encrypt en = new Encrypt();
		
		// pw
		String pw = "password";
		logger.debug("pw : " + pw);
		
		// Salt 생성
		String salt = en.getSalt();
		logger.debug("salt : " + salt);

		// 최종 us_pw 생성
		String us_pw = en.getEncrypt(pw, salt);
	}
	
	public String getSalt() {
		
		// 1. Random, byte 객체 생성
		SecureRandom random = new SecureRandom();
		byte[] salt = new byte[20];
		
		// 2. 난수 생성
		random.nextBytes(salt);
		
		// 3. byte To String (10진수의 문자열로 변경)
		StringBuffer sb = new StringBuffer();
		for(byte b : salt) {
			sb.append(String.format("%02x", b));
		};
		
		return sb.toString();
	}
	
	public String getEncrypt(String pw, String salt) {
		
		String result = "";
		try {
			// 1. SHA256 알고리즘 객체 생성
			MessageDigest md = MessageDigest.getInstance("SHA-256");
			
			// 2. pw와 salt가 합쳐진 문자열에 SHA256 적용
			logger.debug("pw + salt 적용 전 : " + pw + salt);
			md.update((pw+salt).getBytes());
			byte[] pwSalt = md.digest();
			
			// 3. byte To String (10진수의 문자열로 변경)
			StringBuffer sb = new StringBuffer();
			for(byte b : pwSalt) {
				sb.append(String.format("%02x", b));
			}
			
			result = sb.toString();
			logger.debug("pw + salt 적용 후 : " + result);
			
		}catch(NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return result;
	}
}

 

결과

 

 


 

SHA256 이 잘 적용되었는지 확인하고 싶다면

이 사이트를 이용하자!

 

SHA256 해시 - 온라인 SHA256 해시 생성기 (convertstring.com)

 

SHA256 해시 - 온라인 SHA256 해시 생성기

 

www.convertstring.com

 

사이트에서 검사도 해보았다

 

입력

 

출력

 

 

코드 결과랑 똑같이 나옴!!


 

참고한 글

 

[JAVA] 비밀번호 암호화 하기 SHA-256 알고리즘 + Salt 적용 예제 - 레인보우 테이블 :: 매운코딩 (tistory.com)

 

[JAVA] 비밀번호 암호화 하기 SHA-256 알고리즘 + Salt 적용 예제 - 레인보우 테이블

SHA 256 알고리즘? 해시값을 이용한 암호화 방식 중 하나로 단방향 알고리즘이다. 단방향이란 암호화는 가능하나 복호화가 불가능한 것을 의미한다. 일반적인 "ABC"라는 값을 SHA-256알고리즘을 적용

cceeun.tistory.com

 

[Java] SHA-256 패스워드 암호화 적용 예제( SHA-256 with Salt ) (tistory.com)

 

[Java] SHA-256 패스워드 암호화 적용 예제( SHA-256 with Salt )

데이터 보안은 현대 IT 환경에서 중요한 이슈 중 하나입니다. 특히 사용자의 패스워드는 민감한 정보로, 이를 안전하게 보호하는 것은 필수적입니다. SHA-256은 이러한 패스워드 보안을 위해 널리

aday7.tistory.com