Java에서 암호화 적으로 강력한 난수를 원하면을 사용하십시오 SecureRandom
. 불행히도 SecureRandom
매우 느릴 수 있습니다. /dev/random
Linux에서 사용 하는 경우 충분한 엔트로피가 빌드되기를 기다리는 것을 차단할 수 있습니다. 성능 저하를 어떻게 피합니까?
누구든지이 문제에 대한 해결책으로 흔하지 않은 수학 을 사용 했습니까?
JDK 6에서이 성능 문제가 해결되었음을 확인할 수 있습니까?
Java에서 암호화 적으로 강력한 난수를 원하면을 사용하십시오 SecureRandom
. 불행히도 SecureRandom
매우 느릴 수 있습니다. /dev/random
Linux에서 사용 하는 경우 충분한 엔트로피가 빌드되기를 기다리는 것을 차단할 수 있습니다. 성능 저하를 어떻게 피합니까?
누구든지이 문제에 대한 해결책으로 흔하지 않은 수학 을 사용 했습니까?
JDK 6에서이 성능 문제가 해결되었음을 확인할 수 있습니까?
답변:
진정한 무작위 데이터를 원한다면 불행히도 기다려야합니다. 여기에는 SecureRandom
PRNG 의 시드가 포함됩니다 . SecureRandom
인터넷에 연결하여 특정 웹 사이트에서 시드 데이터를 다운로드 할 수 있지만 드문 수학은보다 빠른 실제 임의 데이터를 수집 할 수 없습니다 . 내 생각에 이것은 /dev/random
가능한 곳 보다 빠를 것 같지 않습니다 .
PRNG를 원하면 다음과 같이하십시오.
SecureRandom.getInstance("SHA1PRNG");
지원되는 문자열은 SecureRandom
SPI 공급자 에 따라 다르지만 Security.getProviders()
and를 사용하여 열거 할 수 있습니다 Provider.getService()
.
Sun은 SHA1PRNG를 좋아하므로 광범위하게 사용할 수 있습니다. PRNG가 진행되는 속도는 특히 빠르지는 않지만 PRNG는 엔트로피의 물리적 측정을 차단하지 않고 크 런칭 수치입니다.
예외는 호출하지 않는 경우이다 setSeed()
데이터를 얻기 전에, 다음 PRNG 당신이 전화를 처음 한 번 자신을 배정한다 next()
나 nextBytes()
. 일반적으로 시스템에서 상당히 적은 양의 실제 임의 데이터를 사용하여이 작업을 수행합니다. 이 호출은 차단 될 수 있지만 "PID와 함께 현재 시간을 해시하고 27을 추가하며 최선을 다함"의 변형보다 임의의 수의 소스를 훨씬 더 안전하게 만듭니다. 그래도 게임에 임의의 숫자 만 필요하거나 테스트 목적으로 동일한 시드를 사용하여 나중에 스트림을 반복 할 수있게하려면 안전하지 않은 시드가 여전히 유용합니다.
다음을 사용하여 Linux에서 가장 빠르지 만 약간 안전하지 않은 / dev / urandom을 선택할 수 있어야합니다.
-Djava.security.egd=file:/dev/urandom
그러나 이것은 Java 5 이상 ( Java Bug 6202721 ) 에서는 작동하지 않습니다 . 제안 된 해결 방법은 다음을 사용하는 것입니다.
-Djava.security.egd=file:/dev/./urandom
(추가 참고 /./
)
/dev/urandom
이지만 Sun은 이것을 마법의 문자열로 취급하고 /dev/random
어쨌든 사용 하므로 가짜로 사용해야합니다. 때입니다 file:
URL이 아닌 file:
URL은? 때마다 일이 그것을 결정하는 것은 아니다 :-(
file:/dev/urandom
설정 -Djava.security.egd
되거나 설정되어 있어도 정상적인 설정 은 항상 읽히 거나 호출되는 것처럼 보입니다 . 전혀 읽지 않는 해결 방법 (strace로 확인)securerandom.source
/dev/random/
SecureRandom.getSeed()
setSeed()
file:/dev/./urandom
/dev/random
/dev/urandom/
새로운 하드웨어에서 비밀을 생성하기 위해 그것을 사용하면 매우 예측 가능한 상태 일 수 있습니다. /dev/urandom/
엔트로피를 차단하지는 않습니다. 장치가 처음 부팅 할 때 가장 먼저하는 것이 공개-개인 키 쌍을 생성하는 것처럼 비밀이 지속되면 상황이 더욱 악화됩니다. 이러한 무서운 상황 외에도 /dev/urandom
일반적인 SecureRandom
알고리즘을 사용하는 것보다 좋은 것이 좋습니다 .
Linux에서 기본 구현 SecureRandom
은 NativePRNG
(소스 코드 here )이며 속도가 매우 느립니다. Windows에서 기본값은이며 SHA1PRNG
, 다른 사람들이 지적했듯이 명시 적으로 지정하면 Linux에서도 사용할 수 있습니다.
NativePRNG
운영 체제에서 (로부터 읽음) 엔트로피를 지속적으로 수신한다는 점에서 SHA1PRNG
Maths의 AESCounterRNG 와 다릅니다 /dev/urandom
. 다른 PRNG는 시딩 후 추가 엔트로피를 얻지 못합니다.
AESCounterRNG는 약 10 배 빠르며 SHA1PRNG
, IIRC 자체는 2 배 또는 3 배 빠릅니다 NativePRNG
.
초기화 후 엔트로피를 획득하는 더 빠른 PRNG가 필요한 경우 Fortuna 의 Java 구현을 찾을 수 있는지 확인하십시오 . Fortuna 구현의 핵심 PRNG는 AESCounterRNG에서 사용하는 것과 동일하지만 엔트로피 풀링 및 자동 시드의 정교한 시스템도 있습니다.
많은 Linux 배포판 (대부분 데비안 기반) /dev/random
은 엔트로피 에 사용하도록 OpenJDK를 구성합니다 .
/dev/random
정의상 느리고 차단할 수도 있습니다.
여기에서 차단을 해제하는 방법에 대한 두 가지 옵션이 있습니다.
옵션 1, 엔트로피 개선
에 대한 엔트로피를 더 얻으려면 haveged 데몬을 /dev/random
사용해보십시오 . HAVEGE 엔트로피를 지속적으로 수집하는 데몬이며 특별한 하드웨어가 필요하지 않고 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 문제 로 비트 코인 지갑의 보안이 저하되었습니다.
/dev/random
정의상 느리다 (그리고 심지어 막을 수있다)"는 틀렸다; 전적으로 시스템 구성에 따라 다릅니다. 최근 기계 사용될 수있는 CPU의 예를 들어 빠른 RNG를 가질 수 있으며, BSD 시스템은 일반적으로에 대해 같은 구현을 가지고 /dev/random
와 /devl/urandom
. 그럼에도 불구하고 반드시 빠른 속도에 의존 해서는 안됩니다 /dev/random
. VM에서는 호스트 OS의 RNG를 사용할 수 있도록 클라이언트 VM에 클라이언트 도구 세트를 설치할 수 있습니다.
진정으로 "암호 적으로 강력한"임의성을 원한다면 강력한 엔트로피 소스가 필요합니다. /dev/random
시스템 이벤트가 엔트로피 (디스크 읽기, 네트워크 패킷, 마우스 이동, 키 누르기 등)를 수집 할 때까지 기다려야하므로 속도가 느립니다.
더 빠른 솔루션은 하드웨어 난수 생성기입니다. 이미 마더 보드에 내장되어있을 수 있습니다. hw_random 문서 에서 확인하고 사용 방법에 대한 지침을 확인 하십시오. rng-tools 패키지에는 하드웨어로 생성 된 엔트로피를에 공급하는 데몬이 포함되어 /dev/random
있습니다.
시스템에서 HRNG를 사용할 수없고 성능을 위해 엔트로피 강도를 기꺼이 희생하려는 경우의 데이터를 사용하여 좋은 PRNG를 시드 /dev/random
하고 PRNG가 많은 작업을 수행하도록 할 수 있습니다. SP800-90 에는 NIST가 승인 한 PRNG가 몇 가지 간단하게 구현되어 있습니다.
Java 8을 사용하여 Linux 호출 SecureRandom.getInstanceStrong()
에서 NativePRNGBlocking
알고리즘을 제공 한다는 것을 알았습니다 . 이것은 종종 몇 초 동안 차단하여 몇 바이트의 소금을 생성합니다.
NativePRNGNonBlocking
대신 명시 적으로 요청하도록 전환 했으며 이름에서 예상 한대로 더 이상 차단되지 않았습니다. 나는 이것이 보안의 의미가 무엇인지 전혀 모른다. 아마도 비 차단 버전은 사용되는 엔트로피의 양을 보장 할 수 없습니다.
업데이트 : 좋아, 나는 이 훌륭한 설명을 발견했다 .
간단히 말해서 블로킹을 피하려면을 사용하십시오 new SecureRandom()
. 이것은를 사용 /dev/urandom
하지 않으며 기본적으로 안전합니다 /dev/random
. 게시물에서 : "/ dev / random을 호출하려는 유일한 시간은 시스템이 처음 부팅되고 엔트로피가 아직 누적되지 않은 경우입니다."
SecureRandom.getInstanceStrong()
절대적으로 가장 강력한 RNG를 제공하지만 많은 차단이 영향을 미치지 않는 상황에서만 사용하는 것이 안전합니다.
getInstanceStrong()
그런 TLS 인증서의 경우와 장기 키 위해. 그런 다음에도 new SecureRandom()
FIPS 호환 키 페어 생성기 또는 난수 생성기를 사용 하려고합니다. 그래서 그래,이, 답변을 제공 하는 경우 /dev/urandom
차단하지 않습니다 : 그것은 여전히 결국 시스템의 엔트로피에 의존 결국; 그러나 그것은 일반적으로 매우 좋은 조언 입니다 . /dev/urandom
차단 된 경우 Java 애플리케이션이 아닌 문제의 원인을 수정해야 할 수도 있습니다.
시스템에 인공적인 무작위성을 제공하는 도구가 적어도 우분투에는 있습니다. 명령은 간단합니다 :
rngd -r /dev/urandom
정면에 sudo가 필요할 수 있습니다. rng-tools 패키지가 없으면 설치해야합니다. 나는 이것을 시도했고 그것은 분명히 나를 도왔다!
출처 : 매트 대 세계
sudo rngd -r /dev/urandom
과 결합 해야 sudo apt install rng-tools
했다
나는 같은 문제에 직면했다 . 올바른 검색어로 인터넷 검색을 한 후 DigitalOcean 에 대한이 멋진 기사를 보았습니다 .
나는 단지 여기 기사에서 관련 부분을 인용하고 있습니다.
HAVEGE 원칙과 이전에 연관된 라이브러리를 기반으로 프로세서는 프로세서에서 코드 실행 시간의 변화에 따라 임의성을 생성 할 수 있습니다. 동일한 하드웨어의 동일한 환경에서도 하나의 코드가 동일한 정확한 시간을 실행하는 것은 거의 불가능하기 때문에 단일 또는 여러 프로그램을 실행하는 타이밍은 임의의 소스를 시드하는 데 적합해야합니다. 처리 된 구현은 루프를 반복적으로 실행 한 후 프로세서의 타임 스탬프 카운터 (TSC) 차이를 사용하여 시스템의 임의 소스 (일반적으로 / dev / random)를 시드합니다.
이 기사의 단계를 수행하십시오. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged
여기에 게시했습니다
당신이 언급 한 문제 /dev/random
는 SecureRandom
알고리즘이 아니라 알고리즘의 무작위 소스에 관한 것입니다. 둘은 직교입니다. 둘 중 어느 쪽이 속도를 늦추는 지 알아 내야합니다.
귀하가 링크 한 흔하지 않은 수학 페이지에서는 무작위 소스를 다루지 않는다고 명시 적으로 언급하고 있습니다.
BouncyCastle과 같은 다른 JCE 공급자를 사용하여 구현 SecureRandom
이 더 빠른지 확인할 수 있습니다.
간단한 검색 은 기본 구현을 Fortuna로 대체하는 Linux 패치도 보여줍니다. 이에 대해 더 잘 모르겠지만 조사해 주셔서 감사합니다.
또한 잘못 구현 된 SecureRandom
알고리즘 및 / 또는 임의성 소스 를 사용하는 것은 매우 위험하지만 , 사용자 정의 구현으로 자신의 JCE 공급자를 롤업 할 수 있습니다 SecureRandomSpi
. 제공 업체에 서명하려면 Sun과의 절차를 거쳐야하지만 실제로는 매우 간단합니다. 암호화 라이브러리에 대한 미국 수출 제한 사항을 알고 있다는 양식을 팩스로 보내면됩니다.
재귀 알고리즘의 초기화 소스로 보안 랜덤을 사용하십시오. UncommonMath 대신 Mersenne 트위스터를 사용하여 대량 작업에 사용할 수 있습니다.
http://en.wikipedia.org/wiki/Mersenne_twister
예를 들어, 클라이언트에 하나의 메르 센 트위스터 의사 랜덤 생성기를 사용하여 클라이언트 당 하나의 보안 랜덤을 생성하여 충분히 높은 수준의 무작위 화를 얻을 수 있습니다.
Random
좋지만 그렇지는 않다 SecureRandom
.
문서 에 따르면 SecureRandom에서 사용하는 다양한 알고리즘은 다음과 같습니다.
리눅스에 대해 물어 봤기 때문에 Windows 구현은 무시하고 직접 설치하지 않는 한 Solaris에서만 실제로 사용할 수있는 SunPKCS11도 무시합니다. 그러면 묻지 않을 것입니다.
동일한 문서에 따르면이 알고리즘이 사용하는 것은
SHA1PRNG
초기 시딩은 현재 시스템 속성과 java.security 엔트로피 수집 장치의 조합을 통해 수행됩니다.
NativePRNG
nextBytes()
는 /dev/urandom
generateSeed()
용도를 사용 합니다./dev/random
잠금
nextBytes()
및 generateSeed()
사용/dev/random
NativePRNGNon 차단
nextBytes()
및 generateSeed()
사용/dev/urandom
즉,를 사용하면 SecureRandom random = new SecureRandom()
작동하는 목록 (일반적으로 NativePRNG)을 찾을 때까지 해당 목록으로 내려갑니다. 그리고 그것은 그 자체에서 시드 /dev/random
(또는 시드를 명시 적으로 생성하는 경우 사용) 한 /dev/urandom
다음 다음 바이트, int, double, booleans, what-have-yous를 얻는 데 사용 합니다.
/dev/random
차단 이므로 (엔트로피 풀에 충분한 엔트로피가 될 때까지 차단됨) 성능이 저하 될 수 있습니다.
그것에 대한 하나의 솔루션은 충분한 엔트로피를 생성하기 위해 피난처와 같은 것을 사용하고, 다른 솔루션은 /dev/urandom
대신 사용 합니다. 당신은 전체 JVM의 그 설정할 수 있지만, 더 나은 솔루션이 특정 인스턴스를하고있다 SecureRandom
사용하여 SecureRandom random = SecureRandom.getInstance("NativePRNGNonBlocking")
. NativePRNGNonBlocking 인 경우이 메소드는 NoSuchAlgorithmException을 발생시킬 수 있으므로 기본값으로 폴백 할 준비를하십시오.
SecureRandom random;
try {
random = SecureRandom.getInstance("NativePRNGNonBlocking");
} catch (NoSuchAlgorithmException nsae) {
random = new SecureRandom();
}
또한 다른 * nix 시스템에서는 /dev/urandom
다르게 작동 할 수 있습니다 .
/dev/urandom
임의 충분?기존의 지혜 /dev/random
는 무작위 로만 충분합니다. 그러나 일부 목소리는 다릅니다. 에서 "사용 SecureRandom의 올바른 방법" 및 "는 / dev / urandom의에 대한 신화" , 그 주장되는 /dev/urandom/
단지 좋은 같습니다.
Information Security 스택 사용자 는 이에 동의합니다 . 기본적으로 요청해야 할 경우 /dev/urandom
목적에 적합합니다.
나는이 문제에 스스로 부딪치지 않았지만 프로그램 시작시 즉시 씨앗을 생성하려고 시도하는 스레드를 생성 한 다음 죽습니다. 랜덤을 호출하는 메소드는 해당 스레드가 활성 상태 인 경우 해당 스레드에 참여하므로 첫 번째 호출은 프로그램 실행 초기에 발생하는 경우에만 차단됩니다.
내 경험은 PRNG의 느린 초기화에만 있었고 그 이후에는 임의의 데이터가 생성되지 않았습니다. 보다 열성적인 초기화 전략을 시도하십시오. 생성 비용이 많이 들기 때문에 싱글 톤처럼 취급하고 동일한 인스턴스를 재사용하십시오. 한 인스턴스에 대해 너무 많은 스레드 경합이있는 경우이를 풀링하거나 스레드 로컬로 만듭니다.
난수 생성에서 타협하지 마십시오. 취약점이 있으면 모든 보안이 손상됩니다.
COTS 원자 붕괴 기반 생성기가 많지는 않지만 실제로 임의의 데이터가 많이 필요한 경우 몇 가지 계획이 있습니다. HotBits를 포함하여 항상 흥미로운 것을 볼 수있는 사이트 중 하나는 John Walker의 Fourmilab입니다.
SecureRandom
는 지난 10 년 동안 엔트로피 수집에서 몇 번 변경 되었다고 생각합니다 .
SecureRandom
는 여전히 문제 일 가능성은 적지 만 시스템의 낮은 엔트로피는 항상 문제가됩니다. 싱글 톤을 사용하면 디자인 반 패턴 인 강력하게 결합 된 코드가 생성됩니다. 따라서 극도의주의를 기울여 사용해야합니다. 문제를 해결하려면 코드의 모든 참조를 반대로 바꾸는 것이 좋습니다.
RNG 요구 사항에 대해 더 명확하게 들리는 것처럼 들립니다. 가장 강력한 암호화 RNG 요구 사항은 내가 이해하는 것처럼 알고리즘을 생성하는 데 사용 된 알고리즘을 알고 이전에 생성 된 모든 난수를 알고 있더라도 암호화 된 RNG 요구 사항은 비현실적인 양의 컴퓨팅 능력을 소비하지 않고 미래.
이 무작위성을 완벽하게 보장 할 필요가 없다면 적절한 성능 균형이있을 수 있습니다. Uncommons-Maths 또는 Fortuna의 AESCounterRNG에 대한 Dan Dyer의 답변 에 동의하는 경향이 있습니다 (저자 중 한 명은 암호화 전문가 인 Bruce Schneier입니다). 나는 어느 쪽도 사용한 적이 없지만 아이디어는 언뜻보기에 평판이 좋습니다.
나는 것이라고 생각 주기적으로 초기 랜덤 시드를 생성 할 수 있다면 것을 (예를 들어 하루에 한번 또는 시간 또는 무엇이든 당), 당신은 스트림 암호는 단지 다음 XOR을 사용하는 경우 (스트림의 연속 덩어리에서 난수를 생성하는 빠른 스트림 암호를 사용할 수 있습니다 null 스트림을 전달하거나 XOR 비트를 직접 가져옵니다. ECRYPT E 스트림프로젝트에는 성능 벤치 마크를 포함하여 많은 정보가 있습니다. 이것은 당신이 그것을 보충 한 시점 사이에 엔트로피를 유지하지 않을 것입니다. 따라서 누군가가 임의의 숫자와 사용하는 알고리즘 중 하나를 알고 있다면 기술적으로 많은 컴퓨팅 능력으로 스트림 암호를 깨고 미래의 난수를 예측할 수 있도록 내부 상태를 추측하십시오. 그러나 엔트로피 유지 비용을 정당화하기 위해 위험과 그 결과가 충분한 지 여부를 결정해야합니다.
편집 : 여기 에이 주제와 매우 관련이있는 인터넷에서 발견 된 RNG에 대한 몇 가지 암호화 과정 노트가 있습니다.
하드웨어가 지원하는 경우 필자가 작성한 Java RdRand Utility 를 사용해보십시오 .
인텔의 RDRAND
지침을 기반으로하며 SecureRandom
대량 구현시 대역폭 문제 가 10 배 이상 빠르며 대역폭 문제가 없습니다.
이 구현은 명령을 제공하는 CPU에서만 작동합니다 (예 : rdrand
프로세서 플래그가 설정된 경우). RdRandRandom()
생성자를 통해 명시 적으로 인스턴스화해야합니다 . 구체적 Provider
으로 구현 되지 않았습니다.
RDRAND
좋은 출처 라고 생각 하지만 조금 신뢰할 수 없다. 수집가에게 많은 정보를 입력해야합니다 (David Johnston에 대한 위반 없음).