티스토리 뷰

반응형

이전 글에서 암호화 모듈을 잠깐 언급하였는데요, 여기에서 사용한 소스를 확인해보고자 합니다. 이를 진행하기 위해서는 Java에서 제공해주는 Security를 사용합니다. 

저와 같은 경우 소스의 구현을 이렇게 진행해보았습니다. 

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

@Slf4j
@Component
public class Sha256Encryption {

    public String encryptString(String rawString) {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            log.error(e.getMessage());
        }
        messageDigest.update(generateSalt());
        messageDigest.update(rawString.getBytes());
        return String.format("%064x", new BigInteger(1, messageDigest.digest()));
    }

    private byte[] generateSalt() {
        SecureRandom random = new SecureRandom();
        byte[] bytes = new byte[20];
        random.nextBytes(bytes);
        return bytes;
    }
}

위와 같이 소스를 적용해보았는데 generateSalt 라는 메소드가 의문입니다. Salt이면 소금이라는 의미를 가지고 있는데, 이는 왜 적용하는 것일까요? 이와 관련된 글은 아래에서 확인해볼 수 있습니다.

https://simplicable.com/new/salt-vs-pepper

 

Cryptography: Salt vs Pepper

The difference between cryptographic salt and pepper.

simplicable.com

간단히 이 글을 요약해보자면, Salt의 경우는 암호화 해시 함수를 생성하기 위해 임의의 데이터를 기존의 데이터에 추가하는 값입니다. Salt는 해시 값과 함께 저장할 수 있으며 해시 값을 알고 있다면 복호화가 가능합니다. 이 글에서는 Salt와 대조하는 것으로 Pepper(후추) 가 있습니다. Pepper는 Salt와 다르게 해시 값을 저장하지 않아 복호화가 불가능한 값입니다. 

보통의 경우 프로젝트를 개발할 때 사용자의 비밀번호를 유추하지 못하도록 암호화 모듈을 많이 적용하곤 합니다. 이전에 MySQL에서 제공해주던 PASSWORD 함수가 Deprecated 되었기 때문에 현재 방법으로는 소스 내에서 해시 함수와 적용하여 암호화된 비밀번호 값을 주로 DB에 넣어줍니다. 

그렇다면 암호화 알고리즘을 일반 사용자가 복호화하는건 어떨까?

결론부터 말하자면 로직을 개발한 개발자가 아니라면 불가능합니다. 암호화 알고리즘의 경우 해시 값을 넣고 그 값으로 적게는 80번, 많게는 몇 억번의 루프를 돌려 암호화된 값이 생성이 되는 것이기 때문에 그 값을 알아낼 수는 있어도 적어도 그만큼의 시간 복잡도에 해당하는 시간이 소모됩니다. 하나의 비밀번호를 복호화 하는데 걸리는 시간은 환산하게 된다면 적어도 10년의 시간이 소요된다고 합니다.

보다 정확한 사용처와 쓰임을 알고 싶다면 뭐니뭐니해도 나무위키에 설명이 자세히 나와 있습니다. 여기에는 현재 사용해도 괜찮은 암호화 기법과 사용하면 안되는 기법도 나열되어 있으니 심심풀이로 읽어보면 정말 좋을 것 같습니다.

https://namu.wiki/w/%EC%95%94%ED%98%B8%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98


JUnit 테스트

위 소스를 확인해보기 위해 아래와 같이 테스트 클래스를 작성해보았습니다. 

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
class Sha256EncryptionTest {
    @Autowired
    Sha256Encryption sha256Encryption;

    @Test
    void encryption_test() {
        String rawString = "test";
        String encryptString = sha256Encryption.encryptString(rawString);
        System.out.println("encryptString1 = " + encryptString);

        String encryptString2 = sha256Encryption.encryptString(rawString);
        System.out.println("encryptString2 = " + encryptString2);

        assertThat(rawString)
                .isNotEqualTo(encryptString)
                .isNotEqualTo(encryptString2);
        assertThat(encryptString).isNotEqualTo(encryptString2);
    }
}

이렇게 두개의 값을 생성해서 비교를 하는 이유는 각 시간마다 생성되는 해시 값이 난수이고, 같은 입력값이 들어가더라도 완전 다른 값이 도출되기 때문입니다. 

반응형
댓글
공지사항