[java] 타이밍 공격 방지

암호화와 보안은 현대 애플리케이션 개발에서 매우 중요한 부분입니다. 그 중에서도 타이밍 공격은 암호화를 우회하거나 보안을 약화시키는 데 사용되는 주요 공격 방법 중 하나입니다.

타이밍 공격은 암호화나 인증과정에서 소요되는 시간 차이를 이용하여 비밀 정보를 추측하는 공격입니다. 이를 방지하기 위해서는 타이밍 공격에 취약한 코드를 작성하지 않는 것이 중요합니다.

자바에서는 시간 차이에 의한 타이밍 공격을 방지하기 위해 몇 가지 방법을 제공합니다. 여기에는 중요한 두 가지 방법을 살펴보겠습니다.

1. 암호화 시간 동일화

암호화 작업은 입력 데이터의 크기에 따라 소요 시간이 달라질 수 있습니다. 이러한 차이가 타이밍 공격에 취약한 표시를 만들 수 있습니다. 따라서 암호화 작업이 고정된 시간동안 실행되도록 만들어야 합니다. Java에서는 Thread.sleep() 메소드를 사용하여 고정된 시간동안 스레드를 일시 정지시킬 수 있습니다.

다음은 Thread.sleep() 메소드를 사용하여 암호화 작업을 고정된 시간동안 실행하는 예제 코드입니다.

public byte[] encrypt(byte[] data) {
    long startTime = System.currentTimeMillis();
    
    // 암호화 작업 수행
    
    long endTime = System.currentTimeMillis();
    long elapsedTime = endTime - startTime;
    
    // 암호화 작업이 일정 시간동안 실행되도록 스레드를 일시 정지
    long sleepTime = FIXED_TIME - elapsedTime;
    if(sleepTime > 0) {
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    return encryptedData;
}

이 예제에서 FIXED_TIME은 암호화 작업이 소요되는 고정된 시간을 의미합니다. 암호화 작업이 실제 소요 시간보다 짧을 경우, 남은 시간만큼 Thread.sleep() 메소드를 호출하여 스레드를 일시 정지시킵니다.

2. 비교 연산 시간 동일화

타이밍 공격은 비교 연산에서도 발생할 수 있습니다. 예를 들어 비밀번호 검증 과정에서 비밀번호가 틀렸을 때와 맞았을 때 각각 다른 시간이 소요된다면, 타이밍 공격에 취약한 코드가 됩니다. 따라서 비교 연산 시간을 대략적으로 동일하게 유지하는 것이 중요합니다.

Java에서는 SecureString.equals() 메소드를 사용하여 비교 연산 시간을 동일화시킬 수 있습니다. 이 메소드는 주어진 문자열과 현재 문자열이 일치하는지 확인하면서, 항상 동일한 시간을 소요합니다.

다음은 SecureString.equals() 메소드를 사용하여 비밀번호 검증을 수행하는 예제 코드입니다.

public boolean verifyPassword(String password, String input) {
    SecureString securePassword = new SecureString(password.toCharArray());
    SecureString secureInput = new SecureString(input.toCharArray());
    
    return securePassword.equals(secureInput);
}

이 예제에서 securePassword.equals(secureInput) 메소드를 사용하여 비밀번호와 입력값을 비교하고, 비교 연산에 항상 동일한 시간이 소요되도록 합니다.

결론

암호화와 보안을 위해 타이밍 공격에 대한 방어책을 갖추는 것은 매우 중요합니다. Java에서는 암호화 작업 및 비교 연산 시간을 동일화시키는 몇 가지 방법을 제공하고 있습니다. 이러한 방법을 적절히 활용하여 보안성을 향상시키는 것이 좋습니다.


참고자료: