SHA-256 이란?
SHA-256은 SHA(Secure Hash Algorithm) 단방향 알고리즘의 한 종류로, 해시 값을 이용한 암호화 방식 중 하나이다. 256비트로 구성되며 64자리 문자열을 반환한다.
여기서 단방향 알고리즘이란 암호화는 가능하지만 복호화는 불가능한 것을 의미하고, 사용자의 비밀번호와 같은 보안상 문제가 발생할 수 있는 경우에 사용하면 좋다.
( 암호화는 단방향 뿐만아니라 양방향도 있다. 양방향은 암호화와 복호화가 가능하다. )
SHA-256 해시 함수는 어떤 길이의 값을 입력하더라도 256비트의 고정된 결과값을 출력한다. 일반적으로 입력값이 조금만 변동하여도 출력값이 완전히 달라지기 때문에 출력값을 토대로 입력값을 유추하는 것은 거의 불가능하다. 아주 작은 확률로 입력값이 다름에도 불구하고 출력값이 같은 경우가 발생하는데 이것을 충돌이라고 한다. 이러한 충돌의 발생 확률이 낮을수록 좋은 함수라고 평가된다.
사용방법
1. 사용자가 입력한 비밀번호를 SHA-256 알고리즘을 적용하여 해시값을 얻는다.
2. 얻은 해시값을 DB에 넣는다.
3. 사용자가 로그인 시 해당 비밀번호를 SHA-256 알고리즘을 적용하여 얻은 해시값을 DB에 들어있는 해시값과 비교한다.
* 똑같은 문자열을 똑같은 해시값을 반환합니다.
문제점
동일한 문자열은 동일한 해시값을 반환하게 됩니다. 따라서 해시값을 저장해두는 레인보우 테이블이라는게 생기고, 해커가 암호화된 데이터를 유추할 수 있게 되었습니다.
레인보우테이블이란 ?
해시 함수의 모든 입력값에 대한 결과값을 표로 정리한 것 입니다.
사용방법
1. 해커는 정보를 탈취하기 위해, 해시 함수에 0 ~ 최대값을 전부 넣어 결과값을 구하고, 표(레인보우 테이블)에 정리한다.
2. 레인보우 테이블을 이용하여 입력값과 결과값을 비교해가면서 암호를 찾는다.
레인보우 테이블에 대비하는 방법
레인보우 테이블에 대비하는 방법은 의외로 간단하다. 개발자만 알고있는 정보( salt 라고 함 ) 를 입력값에 더해준 뒤
SHA-256 알고리즘을 적용하면 된다.
SALT 란?
암호학에서솔트(salt)는 데이터, 비밀번호, 통과암호를 해시 처리하는 단방향 함수의 추가 입력으로 사용되는 랜덤 데이터 이다.
ex) salt = "ABC", 비밀번호 = "ABCD"
salt + 비밀번호 = "ABCABCD", 이를 암호화하면 전혀다른 해시값이 얻어진다.
구현예시
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class Encrypt {
public static void main(String[] args) {
Encrypt en = new Encrypt();
String pwd = "tistory";
System.out.println("pwd : "+ pwd);
//Salt 생성
// 현재 랜덤으로 Salt값을 생성하였지만, 실제 구현시 고정시키거나 Salt값을 저장해 두어야합니다.
String salt = en.getSalt();
System.out.println("salt : "+salt);
//최종 비밀번호 생성
String res = en.getEncrypt(pwd, salt);
}
public String getSalt() {
//1. Random, byte 객체 생성
SecureRandom r = new SecureRandom ();
byte[] salt = new byte[20];
//2. 난수 생성
r.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 pwd, String salt) {
String result = "";
try {
//1. SHA256 알고리즘 객체 생성
MessageDigest md = MessageDigest.getInstance("SHA-256");
//2. 비밀번호와 salt 합친 문자열에 SHA 256 적용
System.out.println("비밀번호 + salt 적용 전 : " + pwd+salt);
md.update((pwd+salt).getBytes());
byte[] pwdsalt = md.digest();
//3. byte To String (10진수의 문자열로 변경)
StringBuffer sb = new StringBuffer();
for (byte b : pwdsalt) {
sb.append(String.format("%02x", b));
}
result=sb.toString();
System.out.println("비밀번호 + salt 적용 후 : " + result);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return result;
}
}
출력
비밀번호 : tistory
salt : 978b29efa6c46ac895df0a832a374286b6ce281a
비밀번호 + salt 적용 전 : tistory978b29efa6c46ac895df0a832a374286b6ce281a
비밀번호 + salt 적용 후 : 695e3661fb24dc6fc38d91eb61e1841c77cb515996338ed11be5c69654c17c92
출처
https://defineall.tistory.com/1011
http://wiki.hash.kr/index.php/SHA256
'Java' 카테고리의 다른 글
[Java] Reactive Streams 란? (1) | 2024.01.10 |
---|---|
Spring Webflux 간단하게 알아보기 (0) | 2023.12.25 |
[Java] ArrayList 정렬 / Collections, List, 사용자정의 (0) | 2023.05.07 |
[java] :: 더블콜론의 의미 (0) | 2023.03.28 |
[java] java버전 변경 ( java 8 -> java 17) (0) | 2023.03.27 |