본문으로 바로가기

[Secure Coding] 비밀번호 암호화 하기

category CS/Secure 2016. 4. 28. 17:49

SHA-256 와 SHA-512 와 RSA방식을 가장 많이 쓴다.

MDS는 나온지 너무 오래되서 취약하다. 뽐뿌가 이거쓰다가 털렸다.


SHA-256을 실습해보자


1. USERS 테이블에 SALT 컬럼을 추가해보자

2. 회원 비밀번호를 SALT를 사용한 SHA-256으로 암호화 하자

SHA-256은 64 자리 문자열이 출력된다.


sha256은 hash 함수의 일종이다

hash 함수라는게 뭐냐면 다 알고 있겠지만 간단히 설명해보겠다


y = x + 2 이런 함수는 y를 알면 x도 알 수 있다

하지만 y = hash(x) 이런 해쉬 함수는 y를 알아도 x를 알 수 없는게 특징이다

그리고 모든 x값에 대해 각기 다른 y값을 내뱉는 특징 때문에 x가 원본임을 증명하는 일종의 시그니쳐로도 사용할 수 있다

(정확하게 말하자면 hash 함수는 단사함수가 아니다. hash collision이 있어서 다른 x임에도 같은 y값이 나오는 경우도 있다.

 hash collision을 피하기 위해선 계산을 더 복잡하게 하면 된다. 적당한 기회 비용을 두고 밀당을 해야한다는 소리)


hash 결과값은 32bit 8개를 병렬로 늘어놓은 값 

32bit x 8 = 256bit 그래서 이름이 sha256이다


비밀번호에 랜덤 값을 주고 또 암호화를 시킨다.


1
2
3
4
5
6
7
8
9
// 회원가입시 비밀번호를 SHA-256 으로 SALT 이용해 암호화 하기
            
            String salt = SHA256Util.generateSalt();
            String newPassword = SHA256Util.getEncrypt(memberVO.getUserPassword(), salt);
            memberVO.setUserPassword(newPassword);
            memberVO.setSalt(salt);
            
            memberService.addMember(memberVO);
            SendMessage.send(response, "OK");
cs



로그인 할때 멤버별 salt로 input 값을 암호화를 시킨뒤 db에 저장된 값과 맞는지 비교하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public boolean login(HttpSession session, LoginVO loginVO) {
        String memberSalt = memberDAO.getSaltById( loginVO.getId());
        String inputPassword = loginVO.getPassword();
        String newPassword = SHA256Util.getEncrypt(inputPassword, memberSalt);
        
        MemberVO memberVO = memberDAO.login(loginVO);
        
        if(memberVO != null) {
            
            // 로그인 성공시..
            LoginStore loginStore = LoginStore.getInstance();
            if ( loginStore.get(loginVO.getId())!= null ){
                loginStore.logout(loginVO.getId());
            }
            session.setAttribute(Session.MEMBER, memberVO);
            loginStore.add(loginVO.getId(), session);
            
            session.setAttribute(Session.MEMBER, memberVO);
        }
        
        return memberVO != null;
    }
 
cs


그러면 회원 DB에 암호화 되서 저장된 data ↓







SHA256Util.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package kr.co.hucloud.utilities;
 
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
 
/**
 * SHA-256 암호화
 * 
 * @author Minchang Jang
 *
 */
public class SHA256Util {
 
    public static String getEncrypt(String source, String salt) {
        return getEncrypt(source, salt.getBytes());
    }
    
    public static String getEncrypt(String source, byte[] salt) {
        
        String result = "";
        
        byte[] a = source.getBytes();
        byte[] bytes = new byte[a.length + salt.length];
        
        System.arraycopy(a, 0, bytes, 0, a.length);
        System.arraycopy(salt, 0, bytes, a.length, salt.length);
        
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(bytes);
            
            byte[] byteData = md.digest();
            
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xFF+ 25616).substring(1));
            }
            
            result = sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        
        return result;
    }
    
    public static String generateSalt() {
        Random random = new Random();
        
        byte[] salt = new byte[8];
        random.nextBytes(salt);
        
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < salt.length; i++) {
            // byte 값을 Hex 값으로 바꾸기.
            sb.append(String.format("%02x",salt[i]));
        }
        
        return sb.toString();
    }
    
}
 
 
 
cs



참고 


레퍼런스 문서

http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf