java.util의 차이.랜덤 및 java.security.Secure Random
저희 팀은 랜덤 토큰을 생성하는 서버 측 코드(자바)를 건네받았는데, 이에 대해 질문이 있습니다.
이러한 토큰의 용도는 세션 ID, 비밀번호 재설정 링크 등에 매우 중요합니다.따라서 누군가가 추측하거나 실행 가능한 방법으로 강요하는 것을 피하기 위해 암호적으로 무작위여야 합니다.토큰은 "롱"이므로 64비트입니다.
이 코드에서는 현재java.util.Random
class를 지정하여 이러한 토큰을 생성합니다.의 매뉴얼java.util.Random
에는 다음 사항이 명시되어 있습니다.
java.util 인스턴스.랜덤은 암호학적으로 안전하지 않습니다.대신 SecureRandom을 사용하여 보안에 민감한 응용 프로그램에서 사용하기 위해 암호화로 안전한 의사 난수 생성기를 얻는 것이 좋습니다.
단, 현재 코드 사용방법은java.util.Random
이것은 - 이 명령어를 인스턴스화합니다.java.security.SecureRandom
class를 사용하여SecureRandom.nextLong()
의 인스턴스화에 사용되는 시드를 취득하는 방법java.util.Random
class. 그리고 그것은java.util.Random.nextLong()
method를 지정합니다.
그래서 지금 제 질문은요 - 아직 안전하지 않은가요?java.util.Random
를 사용하여 시드하고 있습니다.java.security.SecureRandom
? 코드가 사용되도록 수정해야 합니까?java.security.SecureRandom
토큰을 생성하는 데만 사용할 수 있습니까?
현재 코드 시드는Random
기동시에 1회
표준 Oracle JDK 7 구현에서는 Linear Congruential Generator라는 것을 사용하여 랜덤 값을 생성합니다.java.util.Random
.
취득처java.util.Random
소스 코드(JDK 7u2, 메서드에 대한 코멘트에서protected int next(int bits)
이것은 랜덤 값을 생성하는 것입니다.
이것은 D. H. Lehmer에 의해 정의되고 Donald E. Knuth에 의해 기술된 것과 같은 선형 합동 의사 난수 생성기이며, 컴퓨터 프로그래밍의 기술, Volume 3: Seminumumerical Algorithms, 섹션 3.2.1에서 설명된다.
선형 합동 생성기의 예측 가능성
Hugo Krawczyk는 이러한 LCG가 어떻게 예측될 수 있는지에 대해 꽤 좋은 논문을 썼습니다("How to predictive generators")운이 좋고 관심이 있다면 웹에서 다운로드 가능한 무료 버전을 찾을 수 있습니다.또, 시큐러티 크리티컬한 목적으로 LCG를 사용해서는 안 된다는 것을 나타내는 조사도 많이 있습니다.즉, 세션 ID 등에 대해 원하지 않는 랜덤 번호를 현재 예측할 수 있습니다.
선형 합동 생성기를 끊는 방법
공격자가 풀 사이클 후에 LCG가 반복될 때까지 기다려야 한다는 가정은 잘못된 것입니다.최적의 사이클(재발 관계에 있는 계수 m)을 사용하더라도 전체 사이클보다 훨씬 짧은 시간에 미래 값을 예측하기가 매우 쉽습니다.LCG의 출력값을 충분히 확인하면 쉽게 풀 수 있는 모듈러 방정식입니다.
"더 나은" 씨앗을 사용한다고 해서 보안이 향상되는 것은 아닙니다.다음에 의해 생성된 임의의 값으로 시드하는 것은 전혀 문제가 되지 않습니다.SecureRandom
주사위를 여러 번 굴려 값을 산출할 수도 있습니다.
공격자는 단순히 관찰된 출력 값에서 시드를 계산합니다.이것은 2^48보다 훨씬 적은 시간이 소요됩니다.java.util.Random
불신자는 이 실험을 시도할 수 있으며, 여기서 당신은 미래를 예측할 수 있다.Random
대략 2^16의 시간 내에 2개의(!) 출력 값만 관찰하는 출력입니다.현대의 컴퓨터에서는 랜덤한 숫자의 출력을 예측하는 데 단 1초도 걸리지 않습니다.
결론
현재 코드를 바꿉니다.사용하다SecureRandom
배타적으로그러면 적어도 결과를 예측하기 어렵다는 보장이 조금은 있을 것이다.암호화로 보호된 PRNG의 속성을 원하는 경우(이 경우 원하는 속성입니다),SecureRandom
사용법을 바꾸는 영리한 방법은 거의 항상 보안성이 떨어지는 결과를 낳게 됩니다
랜덤에는 최대 128비트의 SecureRandom을 사용할 수 있는48비트밖에 없어요따라서 시큐어랜덤에서 반복될 가능성은 매우 작습니다.
랜덤으로 사용하는 것은system clock
시드 생성에 사용됩니다.따라서 공격자가 시드가 생성된 시간을 알고 있으면 쉽게 복제할 수 있습니다.하지만 SecureRandom은Random Data
에서os
(키 입력 간격 등입니다.대부분의 OS는, 이러한 데이터를 파일에 보존합니다./dev/random and /dev/urandom in case of linux/solaris
시드로 사용합니다.
따라서 작은 토큰 크기(랜덤의 경우)가 정상인 경우 SecureRandom을 사용하여 시드를 생성하므로 변경 없이 코드를 계속 사용할 수 있습니다.그러나 더 큰 토큰을 원하는 경우(이 토큰은 대상일 수 없음)brute force attacks
) SecureRandom을 사용합니다.
그냥 랜덤인 경우2^48
현재 고도의 CPU를 사용하면 실제 시간에 문제를 해결할 수 있기 때문에 시도가 필요합니다.단, 시큐어 랜덤을 위해서2^128
이러한 시도는 필수적이며, 오늘날의 진보된 기계를 사용하더라도 손익분기점에 도달하는 데는 수년이 걸릴 것입니다.
자세한 내용은 이 링크를 참조하십시오.
편집
@emboss가 제공하는 링크를 읽어본 결과, 아무리 랜덤이라도 시드를 java.util과 함께 사용하면 안 된다는 것을 알 수 있습니다.랜덤. 출력을 관찰하면 씨앗을 쉽게 계산할 수 있습니다.
SecureRandom으로 이동 - 네이티브 PRNG 사용(위 링크에 기재되어 있는 바와 같이)은 다음 링크에서 랜덤 값을 취득하기 때문에/dev/random
에의 각 호출에 대해 파일을 작성하다nextBytes()
이렇게 하면 공격자가 출력 내용을 제어하지 않는 한 아무것도 알아낼 수 없습니다./dev/random
file(매우 있음직하지 않음)
sha1 prng 알고리즘은 시드를 한 번만 계산하며 VM이 동일한 시드를 사용하여 몇 달 동안 실행되는 경우 출력을 수동적으로 관찰하는 공격자에 의해 시드가 깨질 수 있습니다.
메모 - 전화하는 경우nextBytes()
OS가 랜덤 바이트(메모)를 쓸 수 있는 속도보다 빠릅니다./dev/random
NATIVE PRNG를 사용하면 문제가 발생할 수 있습니다.이 경우 SecureRandom의 SHA1 PRNG 인스턴스를 사용하여 몇 분(또는 일정 간격)마다 이 인스턴스를 시드합니다.nextBytes()
시큐어랜덤의 네이티브 PRNG 인스턴스의 경우.이 두 가지를 병렬로 실행하면 운영 체제에서 얻은 엔트로피를 소진하지 않으면서 진정한 랜덤 값으로 정기적으로 시드할 수 있습니다.
두 번 실행하면java.util.Random.nextLong()
같은 씨앗을 가진다면, 그것은 같은 숫자를 생산하게 될 것이다.보안상의 이유로,java.security.SecureRandom
예측 가능성이 훨씬 낮기 때문입니다.
두 클래스는 비슷해요, 그냥 바꾸면 될 것 같아요.Random
로.SecureRandom
리팩터링 도구를 사용하면 기존 코드 대부분이 작동합니다.
기존 코드를 변경하는 것이 저렴한 작업이라면 Javadoc에서 제안하는 SecureRandom 클래스를 사용하는 것이 좋습니다.
랜덤 클래스 실장에서는 SecureRandom 클래스가 내부적으로 사용되고 있는 경우에도 마찬가지입니다.다음과 같은 것을 당연하게 여겨서는 안 된다.
- 다른 VM 구현에서도 동일한 작업을 수행합니다.
- 향후 버전의 JDK에서 랜덤클래스를 실장하는 경우에도 SecureRandom 클래스가 사용됩니다.
따라서 문서의 제안을 따르고 SecureRandom을 직접 사용하는 것이 좋습니다.
현재의 레퍼런스 실장java.util.Random.nextLong()
이 메서드에 대해2개의 콜을 발신한다.next(int)
이는 현재 시드의 32비트를 직접 노출합니다.
protected int next(int bits) {
long nextseed;
// calculate next seed: ...
// and store it in the private "seed" field.
return (int)(nextseed >>> (48 - bits));
}
public long nextLong() {
// it's okay that the bottom word remains signed.
return ((long)(next(32)) << 32) + next(32);
}
결과의 상위 32비트nextLong()
그 당시 씨앗의 일부입니다.시드 폭은 48비트(javadoc)이므로 나머지 16비트(65.536번 시도)에 걸쳐 반복하여 두 번째 32비트를 생성한 시드를 판별하면 됩니다.
시드를 알면 다음 토큰을 모두 쉽게 계산할 수 있습니다.
출력 사용nextLong()
직접적으로는 PNG의 비밀이기도 하고, 전체 비밀을 매우 적은 비용으로 계산할 수 있는 수준이기도 하다.위험해!
* 2번째 32비트가 마이너스인 경우는 약간의 노력이 필요하지만, 그것을 알 수 있습니다.
씨앗은 무의미하다.양호한 랜덤 발생기는 선택된 프라이머리 넘버가 다릅니다.모든 랜덤 생성기는 숫자에서 시작하여 '링'을 통해 반복됩니다.즉, 하나의 번호에서 다른 번호로 이전 내부 값을 사용합니다.하지만 잠시 후 당신은 다시 시작점에 도달하고 처음부터 다시 시작합니다.사이클을 실행합니다.(랜덤 제너레이터로부터의 반환값이 내부값이 아님)
링 작성에 소수를 사용하는 경우, 가능한 모든 번호의 풀 사이클을 완료하기 전에 해당 링 내의 모든 번호가 선택됩니다.소수 이외의 숫자를 사용하면 모든 숫자가 선택되지 않고 짧은 주기를 얻을 수 있습니다.
소수가 클수록 첫 번째 요소로 돌아가기 전에 사이클이 길어집니다.따라서 안전한 랜덤 생성기는 사이클이 길기 때문에 다시 시작점에 도달하기 전에 안전합니다.단주기만큼 쉽게 숫자 생성을 예측할 수 없습니다.
다른 말:다 바꿔야 돼요.
Random과 secureRandom의 차이와 SecureRandom 클래스의 중요성을 쉽게 이해할 수 있도록 기본적인 단어를 사용해 보겠습니다.
OTP(One Time Password)가 어떻게 생성되는지 궁금하지 않으십니까?OTP를 생성하려면 Random 및 SecureRandom 클래스도 사용합니다.OTP를 강화하려면 SecureRandom이 더 좋습니다.이는 현재 기계에서는 거의 불가능한 OTP를 크래킹하는 데 2^128이 소요되기 때문입니다.그러나 랜덤 클래스를 사용하면 데이터를 손상시킬 수 있는 다른 사람에 의해 크래킹이 발생할 수 있습니다.크래킹하는 데 2^48밖에 걸리지 않았기 때문입니다.
언급URL : https://stackoverflow.com/questions/11051205/difference-between-java-util-random-and-java-security-securerandom
'programing' 카테고리의 다른 글
텍스트 상자에 입력하는 동안 목록 검색 VueJs (0) | 2022.08.13 |
---|---|
Vuex 및 VueJs(변환 핸들러 외부에 있는 vuex 스토어 상태를 변환하지 마십시오) (0) | 2022.08.13 |
프로젝트에 vuetify를 추가하는 동안 오류가 발생했습니다. (0) | 2022.08.13 |
vuex를 사용하여 ajax api-module 로드, 저장 및 새로고침 (0) | 2022.08.13 |
Linux에서 pthread_create에 대한 참조가 정의되지 않았습니다. (0) | 2022.08.13 |