<< MySQL에서 무중단으로 스키마 변경하기(Alter) | Home | 이벤트 설정 시에 jQuery의 .on()을 사용하자. >>

SHA1 + salt로 패스워드 보안 이슈 회피가 가능한가?

최근 들어서 개인 정보 유출 등으로 인해 개인 정보 암호화 방법에 대해서 많이들 고민할 것입니다.
그 중에서 가장 중요하게 생각하는 것 중에 하나가 사용자의 패스워드인데, 과거에는 대부분 해시 MD5, SHA1 또는 SHA-256을 사용하고 있고, 좀 더 안다는 고급 개발자들이 있는 기업들만이 패스워드에 salt를 넣어 사용하고 있는 것으로 파악됩니다.(제가 잘못 알고 있을수도 있습니다.) 물론 최근들어 KISA의 제재로 salt + SHA1로 가는 추세이긴 합니다.
그러나 SHA1 + salt가 안전하다고 생각하는 분들은 아마 없을 듯 합니다. 그저 정부의 제재 수단을 회피하고자 적용하는 기업들이 많을 겁니다.

SHA1 + salt로 패스워드 보안 이슈 회피가 가능한가?

MD5, SHA1 또는 SHA-256 알고리즘은 보안이 우수하지 않다는 것은 다음 사이트에서 테스트해 보면 알 수 있습니다.
"http://google.com"을 MD5 인코딩한 값(c7b920f57e553df2bb68272f61570210)을 md5.rednoize.com 사이트에 넣고 검색 버튼을 클릭하면 바로 복호화되어 나옵니다.
md5.rednoize.com은 원본 데이터와 해시값의 데이터베이스를 참조해, 등록된 것은 즉시 해시값에서 데이터로 변환되어 출력하게 되는 구조입니다. 딕셔너리가 많이 확보되면 쉽게 패스워드를 풀 수 있게 된다는 소리도 됩니다.
이처럼 Rainbow Table("해시값이 이것이면, 암호는 이것"라는 테이블)을 사용해 일방향 암호화 기술을 무력화하게 됩니다. 이것만으로 보아도 일방향 암호화 알고리즘으로 MD5, SHA1 또는 SHA-256은 이제 한물간 일방향 암호화 알고리즘이라는 것을 쉽게 알 수 있죠.

그래서 보완책으로 나온 것이 SHA1 + salt입니다. salt를 붙이는 것으로, Rainbow Table 사용 접근 방식을 실질적으로 사용할 수 없게 하는 것으로 생각해 왔습니다.
SHA1 + salt의 처리방식은 아래와 같습니다.
$salt = "this is a salt";
$password = 'this is an password';
$hash = sha1($salt.$password);

자! 이 방법 또한 여기를 보듯이 GPU가 장착된 디바이스로 병렬처리하면 초당 수억건의 처리가 가능해 무력화 기술에 의해 무너질 수 있습니다. 이렇게 되면 딕셔너리 공격과 무력의 기술을 결합하여 많은 계정을 가진 대형 사이트에서도 상당한 양의 암호를 해독하는데, 그리 오랜 시간이 걸리지 않을 것입니다.

현재까지의 좀 더 강화된 방법으로는 뭐가 있을까요?

  • 각 사용자에게 고유 salt 값과 반복 횟수를 마련하는 것이고.
  • 좀 더 강력한 PBKDF2(http://en.wikipedia.org/wiki/PBKDF2), Bcrypt(http://www.openwall.com/crypt/), HMAC(http://en.wikipedia.org/wiki/HMAC)를 사용하는 것.
  • 불편하더라도 사용자에게 강한 강도의 패스워드를 받도록 유도하는 것.
정도가 될 것으로 보입니다.

PBKDF2 사용 샘플(Java)

public class PBKDF2 {

	//임의 salt를 생성
    private static byte[] createSalt() throws NoSuchAlgorithmException {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        byte[] salt = new byte[32];
        random.nextBytes(salt);
        return salt;
    }

    private static byte[] pbkdf2(char[] password, byte[] salt) 
     throws InvalidKeySpecException, NoSuchAlgorithmException {
        SecretKeyFactory sf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        // 반복 횟수 : 10000 번 결과 길이 : 256bit
        KeySpec ks = new PBEKeySpec(password, salt, 10000, 256);
        SecretKey sk = sf.generateSecret(ks);
        return sk.getEncoded();
    }

    private static void logging(String format, Object ... args) {
        System.out.printf(format + "%n", args);
    }

    public static void main(String[] args) 
     throws NoSuchAlgorithmException, InvalidKeySpecException {
        String p1 = args[0];
        String p2 = args[1];
        logging("password 1= %s", p1);
        logging("password 2= %s", p2);

        byte[] salt = createSalt();
        logging("salt: %s", Arrays.toString(salt));

        byte[] d1 = pbkdf2(p1.toCharArray(), salt);
        byte[] d2 = pbkdf2(p2.toCharArray(), salt);
        logging("derived 1= %s", Arrays.toString(d1));
        logging("derived 2= %s", Arrays.toString(d2));
    }
}
위의 10000이라는 숫자가 반복횟수이므로 이를 증가시켜 안전성을 높일 수 있습니다. 이 수를 사용자별로 데이터베이스에 저장하여 두면 중간에 반복 횟수를 높이고 안전성을 향상시킬 수도 있습니다.

[참조사이트]
Tags : , ,


Re: SHA1 + salt로 패스워드 보안 이슈 회피가 가능한가?

그런데 요즘 저렇게 어택하게 놔둔 싸이트가 없죠

무뇌충이 개발하지 않는 이상 세번정도 틀리면 다른 로직(인증(캡챠), 이메일 알림, 락킹(로그인 몇분동안 못함) 을 타게 되죠..

Avatar: 미물

Re: SHA1 + salt로 패스워드 보안 이슈 회피가 가능한가?

SK컴즈 등에서 처럼 개인정보가 유출되었을때도 대응할 수 있어야 하는게 보안의 개념이죠. 해커들은 우리들이 생각하는 것 이상으로 똑똑하니 방심은 금물이죠. 유출 안되게 하는것이 제일 우선이고 그 다음 유출되었을 경우도 가정해서 대응해 둬야합니다. ^^ 

Re: SHA1 + salt로 패스워드 보안 이슈 회피가 가능한가?

 설마 저걸 직접 인터넷으로 로그인 하겠습니까? 해도 미칠듯한 양의 접속 시도 기록이 남아서 걸리는 것도 시간문제고, 인터넷으로 일일이 접속시도를 하면 초당 수억번이나 되는 속도도 안 나오죠......

저건 암호화된 파일이 해킹으로 대량 유출 되었을 때 저렇게 순식간에 크랙할 수 있으므로 암호화가 믿을만 한 수준이 아니라는 겁니다.

Re: SHA1 + salt로 패스워드 보안 이슈 회피가 가능한가?

 ...이제부터 SHA1 쓰지 말고 SHA256 이상부터 쓰라고 권고가 나왔었습니다.


Add a comment Send a TrackBack