Java

Java - Math.random() 보안 취약점

codeManager 2025. 6. 1. 11:01
반응형

Java에서 Math.random()은 간단한 의사 난수(pseudo-random number)를 생성하는 데 사용되지만, 보안적인 목적으로는 절대 사용하면 안 됩니다.

Math.random()은 예측 가능한 알고리즘을 사용하며, 이는 공격자가 다음 난수를 예측하거나 역추적할 수 있게 하여 보안 취약점을 야기할 수 있습니다.

보안적으로 안전한 난수 생성이 필요한 경우, Java에서는 java.security.SecureRandom 클래스를 사용해야 합니다.

 

 

java.security.SecureRandom의 장점

SecureRandom은 다음과 같은 이유로 보안적인 상황에 적합합니다:

  1. 암호학적으로 안전한 의사 난수 생성기 (CSPRNG): SecureRandom은 Math.random()이나 java.util.Random과 달리 암호학적으로 강력한 알고리즘(예: SHA1PRNG, NativePRNG, DRBG 등)을 사용하여 난수를 생성합니다. 이는 생성된 난수가 통계적으로 무작위일 뿐만 아니라, 예측 불가능하고 역추적 불가능하게 만듭니다.
  2. 엔트로피 소스 활용: SecureRandom은 운영체제에서 제공하는 엔트로피 소스(예: Linux의 /dev/random 또는 /dev/urandom)를 활용하여 초기 시드(seed)를 생성합니다. 이 시드는 예측 불가능하며, 이를 기반으로 생성되는 난수도 예측 불가능하게 됩니다.
  3. 다양한 난수 생성 메서드: SecureRandom은 nextInt(), nextLong(), nextBytes() 등 다양한 타입의 난수를 생성하는 메서드를 제공합니다. 특히 바이트 배열을 채우는 nextBytes()는 암호화 키, 솔트(salt), 토큰 등 보안 관련 데이터를 생성할 때 매우 유용합니다.

 

예시 코드

import java.security.SecureRandom;

public class SecureRandomExample {

    public static void main(String[] args) {
        // 1. SecureRandom 인스턴스 생성 (기본 알고리즘 사용)
        SecureRandom secureRandom = new SecureRandom();

        // 2. 다양한 타입의 보안적으로 안전한 난수 생성
        // 정수 생성
        int randomNumber = secureRandom.nextInt();
        System.out.println("Secure Random Integer: " + randomNumber);

        // 특정 범위의 정수 생성 (예: 0부터 99까지)
        int randomBoundedNumber = secureRandom.nextInt(100);
        System.out.println("Secure Random Bounded Integer (0-99): " + randomBoundedNumber);

        // 긴 정수 생성
        long randomLong = secureRandom.nextLong();
        System.out.println("Secure Random Long: " + randomLong);

}

 

주의사항

  • SecureRandom은 Math.random()이나 java.util.Random보다 난수 생성 속도가 느릴 수 있습니다. 이는 더 복잡한 알고리즘과 외부 엔트로피 소스를 사용하기 때문입니다. 따라서 성능이 매우 중요하고 보안이 중요하지 않은 단순 시뮬레이션이나 게임 등에서는 java.util.Random을 고려할 수 있습니다.
  • SecureRandom 인스턴스를 생성할 때 초기 시드링(seeding) 과정에서 시간이 다소 걸릴 수 있습니다. 따라서 반복적으로 SecureRandom 객체를 생성하는 것보다는, 한 번 생성하여 재사용하는 것이 좋습니다.
반응형