문제

Java에서 암호적으로 강한 무작위 숫자를 원한다면 사용합니다. SecureRandom. 안타깝게도, SecureRandom 매우 느릴 수 있습니다. 사용하는 경우 /dev/random Linux에서는 충분한 엔트로피가 구축되기를 기다릴 수 있습니다. 성과 페널티를 어떻게 피합니까?

누구든지 사용했습니다 드문 수학 이 문제에 대한 해결책으로?

이 성능 문제가 JDK 6에서 해결되었음을 확인할 수 있습니까?

도움이 되었습니까?

해결책

진정한 임의의 데이터를 원한다면 불행히도 기다려야합니다. 여기에는 A에 대한 씨앗이 포함됩니다 SecureRandom prng. 드문 수학은 실제 임의 데이터를 수집 할 수 없습니다. SecureRandom, 인터넷에 연결하여 특정 웹 사이트에서 시드 데이터를 다운로드 할 수 있습니다. 내 생각에 이것은 이것이 더 빠를 것 같지 않다는 것입니다. /dev/random 사용할 수있는 곳.

PRNG를 원한다면 다음과 같이하십시오.

SecureRandom.getInstance("SHA1PRNG");

지원되는 문자열은 다음과 같습니다 SecureRandom SPI 제공자이지만 사용을 열거 할 수 있습니다 Security.getProviders() 그리고 Provider.getService().

Sun은 Sha1prng를 좋아하므로 널리 사용할 수 있습니다. PRNG가 진행됨에 따라 특히 빠르지는 않지만 PRNG는 엔트로피의 물리적 측정을 막는 것이 아니라 숫자를 크 랜치로 만들 것입니다.

전화하지 않으면 예외입니다 setSeed() 데이터를 얻기 전에 PRNG는 처음으로 전화를 걸면 자체를 시드합니다. next() 또는 nextBytes(). 일반적으로 시스템에서 상당히 적은 양의 실제 임의 데이터를 사용하여이를 수행합니다. 이 호출은 차단할 수 있지만 "PID와 함께 현재 시간을 해시, 27을 추가하고 최선을 다할 수있는"변형보다 임의의 숫자 소스가 훨씬 더 안전하게 만들 것입니다. 만약 당신이 필요한 모든 것이 게임의 임의 숫자 만 있거나, 테스트 목적으로 동일한 시드를 사용하여 향후 스트림을 반복 할 수있게하려면 안전하지 않은 씨앗이 여전히 유용합니다.

다른 팁

다음을 사용하여 Linux에서 더 빠르고 조명이없는 보안 /Dev /Urandom을 선택할 수 있어야합니다.

-Djava.security.egd=file:/dev/urandom

그러나 이것은 Java 5 이상에서 작동하지 않습니다 (Java 버그 6202721). 제안 된 워크 라운드는 다음과 같습니다.

-Djava.security.egd=file:/dev/./urandom

(추가에 주목하십시오 /./)

Linux에서는 기본 구현입니다 SecureRandom ~이다 NativePRNG (소스 코드 여기), 이것은 매우 느린 경향이 있습니다. Windows에서는 기본값입니다 SHA1PRNG, 다른 사람들이 지적한 것처럼 명시 적으로 지정하면 Linux에서 사용할 수도 있습니다.

NativePRNG ~와 다르다 SHA1PRNG 그리고 드문 수학 ' aescounterrng 그것은 운영 체제로부터 엔트로피를 지속적으로 받는다는 점에서 /dev/urandom). 다른 PRNG는 파종 후 추가 엔트로피를 획득하지 않습니다.

Aescounterrng는 약 10 배 빠릅니다 SHA1PRNG, IIRC 자체가 2 ~ 3 배 더 빠릅니다. NativePRNG.

초기화 후 엔트로피를 획득하는 더 빠른 PRNG가 필요한 경우 Java 구현을 찾을 수 있는지 확인하십시오. FORTUNA. Fortuna 구현의 핵심 PRNG는 Aescounterrng가 사용하는 것과 동일하지만 엔트로피 풀링 및 자동 재조정의 정교한 시스템도 있습니다.

많은 Linux 배포판 (주로 데비안 기반)을 사용하도록 OpenJDK를 구성합니다. /dev/random 엔트로피 용.

/dev/random 정의에 따라 느리게 (그리고 차단할 수도 있음).

여기에서 차단 해제 방법에 대한 두 가지 옵션이 있습니다.

  1. 엔트로피를 개선하십시오
  2. 무작위성 요구 사항을 줄입니다.

옵션 1, 엔트로피 향상

더 많은 엔트로피를 얻기 위해 /dev/random, 시도하십시오 adged 악마. Hasge 엔트로피를 지속적으로 수집하고 특수 하드웨어, CPU 자체 및 시계 만 필요하지 않기 때문에 가상화 된 환경에서도 작동하는 데몬입니다.

우분투/데비안에서 :

apt-get install haveged
update-rc.d haveged defaults
service haveged start

Rhel/Centos :

yum install haveged
systemctl enable haveged
systemctl start haveged

옵션 2. 무작위성 요구 사항을 줄입니다

어떤 이유로 위의 솔루션이 도움이되지 않거나 암호적으로 강한 무작위성에 신경 쓰지 않으면 전환 할 수 있습니다. /dev/urandom 대신, 차단하지 않도록 보장됩니다.

전 세계적으로 수행하려면 파일을 편집하십시오 jre/lib/security/java.security 기본 Java 설치에서 사용할 수 있습니다 /dev/urandom (다른 때문입니다 벌레 지정해야합니다 /dev/./urandom).

이와 같이:

#securerandom.source=file:/dev/random
securerandom.source=file:/dev/./urandom

그러면 명령 줄에 지정할 필요가 없습니다.


참고 : 암호화를하는 경우 필요 좋은 엔트로피. 지목 사항 - 안드로이드 PRNG 문제 비트 코인 지갑의 보안을 줄였습니다.

나는 전화와 비슷한 문제가있었습니다 SecureRandom 헤드리스 데비안 서버에서 한 번에 약 25 초 동안 차단. 나는 그것을 설치했다 haveged 보장하는 데몬 /dev/random 헤드리스 서버에서 필요한 엔트로피를 생성하려면 이와 같은 것을 필요로합니다. 내 전화 SecureRandom 이제 아마도 밀리 초를 섭취 할 수 있습니다.

진정으로 "암호화 적으로 강한"무작위성을 원한다면 강력한 엔트로피 소스가 필요합니다. /dev/random 시스템 이벤트가 엔트로피 (디스크 판독, 네트워크 패킷, 마우스 움직임, 키 프레스 등)를 모을 때까지 기다려야하기 때문에 느립니다.

더 빠른 솔루션은 하드웨어 임의 번호 생성기입니다. 이미 마더 보드에 하나의 내장이있을 수 있습니다. 확인하십시오 hw_random 문서 가지고 있는지 알아내는 방법과 사용 방법에 대한 지침. RNG-Tools 패키지에는 데몬이 포함되어있어 하드웨어 생성 엔트로피를 /dev/random.

시스템에서 HRNG를 사용할 수없고 성능을 위해 엔트로피 강도를 기꺼이 희생하려는 경우 데이터를 사용하여 좋은 PRNG를 시드하고 싶을 것입니다. /dev/random, PRNG가 많은 작업을 수행하도록하십시오. NIST 승인 PRNG가 등재 된 몇 가지가 있습니다 SP800-90 구현하기가 간단합니다.

시스템에 인공 무작위성을 공급하는 도구 (적어도 우분투에는)가 있습니다. 명령은 단순히 다음과 같습니다.

rngd -r /dev/urandom

그리고 당신은 정면에 sudo가 필요할 수 있습니다. RNG-Tools 패키지가없는 경우 설치해야합니다. 나는 이것을 시도했고 그것은 확실히 도움이되었습니다!

원천: 매트 대 세계

나는 같은 직면했다 문제. 올바른 검색어로 검색 한 후에는이 멋진 기사를 발견했습니다. Digitalocean.

HADGED는 보안을 손상시키지 않고 잠재적 인 솔루션입니다.

나는 단지 여기서 기사에서 관련 부분을 인용하고 있습니다.

HADGE 원칙을 기반으로하고 이전에 관련 라이브러리를 기반으로 한 HADGED는 프로세서에서 코드 실행 시간의 변형에 따라 임의성을 생성 할 수 있습니다. 동일한 하드웨어의 동일한 환경에서도 한 코드가 동일한 시간을 실행하는 데 거의 불가능하기 때문에 단일 또는 여러 프로그램을 실행하는 타이밍이 무작위 소스를 시드하는 데 적합해야합니다. agged 구현은 루프를 반복적으로 실행 한 후 프로세서 타임 스탬프 카운터 (TSC)의 차이를 사용하여 시스템의 임의 소스 (일반적으로 /dev /random)를 종자합니다.

설치 방법

이 기사의 단계를 따르십시오. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

나는 그것을 게시했다 여기

반복 알고리즘의 보안 무작위로 초기화 소스를 사용하십시오. 그런 다음 비공식적 인 작업 대신 대량 작업에 Mersenne 트위스터를 사용할 수 있습니다.

http://en.wikipedia.org/wiki/mersenne_twister

지금 새로 고침을 한 다음 초기화에 사용되는 보안 랜덤을 확인하십시오. 예를 들어 클라이언트 당 하나의 Mersenne Twister Pseudo Random Generator를 사용하여 클라이언트 당 하나의 보안 무작위 생성을 가질 수 있습니다.

Java 8을 사용하여 Linux 통화에서 SecureRandom.getInstanceStrong() 나에게 줄 것이다 NativePRNGBlocking 연산. 이것은 종종 몇 초 동안 차단하여 몇 바이트의 소금을 생성합니다.

나는 명시 적으로 요청했다 NativePRNGNonBlocking 대신, 이름에서 예상대로 더 이상 차단되지 않습니다. 나는 이것의 보안 영향이 무엇인지 전혀 모른다. 아마도 비 블로킹 버전은 사용되는 엔트로피의 양을 보장 할 수 없습니다.

업데이트: 알았어, 나는 찾았다 이 훌륭한 설명.

간단히 말해서 차단을 피하기 위해 사용하십시오 new SecureRandom(). 이것은 사용합니다 /dev/urandom, 차단하지 않고 기본적으로 보안 /dev/random. 게시물에서 : " /dev /random을 호출하려는 유일한 시간은 기계가 처음 부팅되고 엔트로피가 아직 축적되지 않은시기입니다."

SecureRandom.getInstanceStrong() 당신에게 절대적인 가장 강력한 RNG를 제공하지만, 많은 차단이 당신에게 영향을 미치지 않는 상황에서 사용하는 것은 안전합니다.

당신이 언급 한 문제 /dev/random is not with the SecureRandom 알고리즘이지만 사용하는 임의성 원인이 있습니다. 두 사람은 직교입니다. 둘 중 하나가 속도를 늦추고 있는지 알아 내야합니다.

당신이 링크 한 드문 수학 페이지는 그들이 무작위성의 원천을 다루지 않는다는 것을 명시 적으로 언급합니다.

Bouncycastle과 같은 다른 JCE 제공 업체를 시도하여 SecureRandom 보다 빠르다.

간단한 검색 또한 기본 구현을 Fortuna로 대체하는 Linux 패치가 표시됩니다. 나는 이것에 대해 더 많이 모르지만, 당신은 조사를 환영합니다.

또한 나쁜 구현을 사용하는 것이 매우 위험하지만 SecureRandom 알고리즘 및/또는 Randomness 소스는 사용자 정의 구현으로 자체 JCE 제공 업체를 굴릴 수 있습니다. SecureRandomSpi. 제공자가 서명하기 위해 Sun과의 과정을 거쳐야하지만 실제로는 매우 간단합니다. 그들은 당신이 암호화 라이브러리에 대한 미국 수출 제한을 알고 있다는 형태를 팩스로 보내야합니다.

나는이 문제를 직접 맞지 않았지만 프로그램 시작에서 스레드를 생성하여 즉시 씨앗을 생성하려고 시도한 다음 죽습니다. 랜덤을 호출하는 방법은 살아있는 경우 해당 스레드에 결합되므로 첫 번째 호출은 프로그램 실행 초기에 발생하는 경우에만 차단됩니다.

제 경험은 PRNG의 초기화가 느리게 진행되었으며 그 후에 무작위 데이터의 생성이 아니라 PRNG의 초기화가 느려졌습니다. 보다 간절한 초기화 전략을 시도하십시오. 그들은 비싸기 때문에 싱글 톤처럼 취급하고 동일한 인스턴스를 재사용하십시오. 한 예에 대한 스레드 경합이 너무 많으면 풀을 풀거나 스레드 로컬로 만드십시오.

임의의 숫자 생성에 타협하지 마십시오. 약점은 모든 보안을 손상시킵니다.

나는 COTS Atomic-Decay 기반 생성기가 많이 보이지 않지만 실제로 많은 임의의 데이터가 필요하다면 몇 가지 계획이 있습니다. 핫 브릿을 포함하여 항상 볼 수있는 흥미로운 것들이있는 사이트는 다음과 같습니다. John Walker의 Fourmilab.

RNG 요구 사항에 대해 더 명확 해야하는 것 같습니다. 가장 강력한 암호화 RNG 요구 사항 (내가 이해하는 것처럼)은 생성하는 데 사용 된 알고리즘을 알고 있더라도 이전에 생성 된 모든 임의의 숫자를 알고 있더라도 미래, 비현실적인 양의 컴퓨팅 능력을 소비하지 않고.

이 완전한 무작위성을 보장 할 필요가 없다면 적절한 성능 트레이드 오프가있을 수 있습니다. 나는 동의하는 경향이있다 댄 다이어의 반응 비 공통의 장전군의 Aescounterrng 또는 Fortuna에 대해 (저자 중 한 명은 암호화 전문가 인 Bruce Schneier)입니다. 나는 어느 쪽도 사용한 적이 없지만 아이디어는 언뜻보기에 평판이 좋은 것처럼 보입니다.

나는 할 것이다 생각한다 초기 임의의 종자를 주기적으로 생성 할 수 있다면 (예 : 하루 또는 시간 또는 시간 이상) 빠른 스트림 암호를 사용하여 스트림의 연속 덩어리에서 임의의 숫자를 생성 할 수 있습니다 (스트림 암호가 XOR을 사용하는 경우에는 널의 흐름이나 XOR 비트를 직접 잡습니다). Ecrypt 's estream 프로젝트에는 성능 벤치 마크를 포함한 많은 좋은 정보가 있습니다. 이것은 당신이 그것을 보충하는 지점들 사이에 엔트로피를 유지하지 않을 것이므로, 누군가가 임의의 숫자 중 하나와 당신이 사용한 알고리즘을 알고 있다면 기술적으로 많은 컴퓨팅 전력으로 스트림 암호를 깨뜨리는 것이 가능할 수 있습니다. 미래의 임의 숫자를 예측할 수있는 내부 상태를 추측하십시오. 그러나 그 위험과 그 결과가 엔트로피 유지 비용을 정당화하기에 충분한 지 여부를 결정해야합니다.

편집 : 여기에 있습니다 RNG에 대한 암호화 과정 참고 나는이 주제와 매우 관련이있는 '그물을 발견했습니다.

하드웨어가 지원하는 경우 시도해보십시오 Java Rdrand 유틸리티 사용 그 중 나는 저자입니다.

인텔을 기반으로합니다 RDRAND 교육 및보다 약 10 배 빠릅니다 SecureRandom 대량 구현을위한 대역폭 문제가 없습니다.


이 구현은 명령을 제공하는 CPU에만 작동합니다 (즉, rdrand 프로세서 플래그가 설정 됨). 당신은 그것을 통해 그것을 명시 적으로 인스턴스화해야합니다 RdRandRandom() 건설자; 구체적이지 않습니다 Provider 구현되었습니다.

다른 것을 볼 수있는 것은 Securerandom.source 파일 Lib/Security/Java.security입니다.

/dev /random보다는 /dev /urandom을 사용하는 데 성능 이점이있을 수 있습니다. 임의 숫자의 품질이 중요하다면 보안을 깨뜨리는 타협을하지 마십시오.

잘 알고있는 알고리즘을 구현하는 Apache Commons Math Project를 사용해 볼 수 있습니다.

https://commons.apache.org/proper/commons-math/userguide/random.html

그러나 성능에주의하십시오. 기본 생성자 RandomDataGenerator 전용 인스턴스를 만듭니다 Well19937c, 그것은 매우 비싼 작업입니다.

문서에 따르면이 수업 아니다 스레드 안전하지만 하나의 스레드만이 클래스에 액세스 할 수 있도록 보장 할 수 있다면 스레드 당 하나의 인스턴스 만 초기화 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top