Para que serve a opção java.security.egd?

22

Em um projeto em que estou trabalhando, o aplicativo é iniciado usando um comando semelhante a este:

java -Djava.security.egd=file:/dev/urandom -jar app.jar

Eu nunca vi a java.security.egdopção antes. Pesquisando um pouco, parece usado para configurar a geração aleatória de números em um aplicativo Java.

Está certo? Quando deve ser aplicado?

davioooh
fonte

Respostas:

30

Os aplicativos Java podem e devem usar a classe java.security.SecureRandom para produzir valores aleatórios criptograficamente fortes usando um gerador de números pseudo-aleatórios criptograficamente fortes ( CSPRNG ). As implementações JDK padrão da classe java.util.Random não são consideradas criptograficamente fortes.

Os sistemas operacionais do tipo Unix possuem /dev/randomum arquivo especial que serve para números pseudo-aleatórios acessando ruído ambiental coletado de drivers de dispositivo e outras fontes. No entanto, ele bloqueia se houver menos entropia disponível do que o solicitado ; /dev/urandomnormalmente nunca bloqueia, mesmo que a semente do gerador de números aleatórios pseudoaleatórios não tenha sido totalmente inicializada com entropia desde a inicialização. Ainda existe um terceiro arquivo especial, /dev/arandomque bloqueia após a inicialização até que a semente tenha sido inicializada com segurança com entropia suficiente e nunca mais bloqueia novamente.

Por padrão, a JVM semeia a classe SecureRandom usando /dev/random, portanto, seu código Java pode bloquear inesperadamente . A opção -Djava.security.egd=file:/dev/./urandomna chamada da linha de comandos usada para iniciar o processo Java informa à JVM para usar /dev/urandom.

O extra /./parece fazer com que a JVM use o algoritmo SHA1PRNG, que usa o SHA-1 como base do PRNG (Pseudo Random Number Generator). É mais forte que o algoritmo NativePRNG usado quando /dev/urandomé especificado.

Finalmente, existe um mito que /dev/urandomé um gerador de números pseudo-aleatórios, um PRNG, enquanto /dev/randomé um gerador de números aleatórios “verdadeiro” . Isso simplesmente não é verdade, ambos /dev/randome /dev/urandomsão alimentados pelo mesmo CSPRNG (gerador de números pseudoaleatórios criptograficamente seguros). Somente o comportamento quando o respectivo pool fica sem entropia, de acordo com alguma estimativa, difere: /dev/randombloqueia, enquanto /dev/urandomnão.

E a entropia ficando baixa? Não importa.

Acontece que “parecer aleatório” é o requisito básico para muitos dos nossos blocos de construção criptográficos. E se você pegar a saída de um hash criptográfico, ele deve ser indistinguível de uma sequência aleatória para que as cifras o aceitem. Essa é a razão de usar o algoritmo SHA1PRNG, pois ele usa uma função hash e um contador, junto com uma semente.

Quando deve ser aplicado?

Sempre, eu diria.

Fontes:
https://gist.github.com/svrc/5a8accc57219b9548fe1
https://www.2uo.de/myths-about-urandom


EDIT 04/2020:

Um comentário menciona uma alteração no comportamento da classe SecureRandom no Java 8.

SHA1PRNG e NativePRNG foram corrigidos para respeitar adequadamente as propriedades de origem de semente SecureRandom no arquivo java.security. (A solução alternativa obscura usando file: /// dev / urandom e file: / dev /./ urandom não é mais necessária.)

Isso já havia sido apontado pelos testes mencionados na seção Fontes acima. O extra /./é necessário para alterar o algoritmo usado pelo SecureRanom no Java 8 de NativePRNG para SHA1PRNG.

No entanto, tenho algumas notícias que gostaria de compartilhar. De acordo com o JEP-273 , desde o Java 9, a classe SecureRandom implementa os três mecanismos do Gerador de bits aleatórios determinísticos (DRBG) descritos no NIST 800-90Ar1 . Esses mecanismos implementam algoritmos modernos tão fortes quanto o SHA-512 e o AES-256.

O JDK tinha dois tipos de implementações do SecureRandom :

  • Um deles depende da plataforma e é baseado em chamadas nativas ou dispositivos de SO, como a leitura /dev/{u}randomno Unix ou o uso do CryptoAPI no Windows. As versões mais recentes do Linux e Windows já suportam DRBG, mas versões mais antigas e sistemas incorporados podem não .
  • O outro tipo é uma implementação Java pura que usa uma implementação RNG baseada em SHA1 mais antiga, que não é tão forte quanto os algoritmos usados ​​pelos mecanismos DRBG aprovados.

Enquanto isso, o Java 13 Security Developer's Guide ainda lê

No Linux e macOS, se o dispositivo de coleta de entropia em java.security estiver definido como file:/dev/urandomou file:/dev/random, NativePRNG será preferido como SHA1PRNG. Caso contrário, é preferido o SHA1PRNG.

Para esclarecer como os novos mecanismos DRBG são executados em conjunto com os PRNGs anteriores, executei alguns testes no macOS (Darwin) com o AdoptOpenJDK (build 13.0.2 + 8). Aqui estão os resultados:

file: / dev / random
Ordem de preferência dos provedores:

SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG

file: / dev / urandom
Ordem de preferência dos provedores:

SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG

file: / dev /./ urandom
Ordem de preferência dos provedores:

SecureRandom.DRBG
SecureRandom.SHA1PRNG
SecureRandom.NativePRNG

Conclusão:

Eu recomendo o uso -Djava.security.egd=file:/dev/./urandompara garantir o aproveitamento da implementação SecureRandom mais forte disponível, independentemente da plataforma usada, evitando o bloqueio inesperado do código.

dbaltor
fonte
11
No Java 8, a "solução obscura" do extra ./ no nome do arquivo não é mais necessária; portanto, você pode simplesmente usar "/ dev / urandom", consulte: docs.oracle.com/javase/8/docs / notas técnicas / guias / segurança /…
Kamal
Obrigado por atualizar a resposta (especialmente sobre as alterações no Java 9 e 13). No entanto, pelo meu entendimento, no Java 8, a configuração do "dispositivo de coleta de entropia" como / dev / urandom ou /dev/./urandom deve gerar exatamente os mesmos resultados, caso contrário, a correção não faria sentido. Do ponto de vista do sistema operacional, eles apontam para o mesmo arquivo idêntico, de modo que não deve afetar o Java (antes da correção, mas era um bug, não um recurso pretendido). Portanto, sua declaração "/ /. Extra é necessária para influenciar a seleção do PRNG". não deve mais ser verdade, a partir do Java 8.
Kamal
Obrigado @ Kamal por seus comentários. Minha frase anterior "seleção PRNG" não era clara o suficiente. Eu o reformulei para esclarecer que estou falando sobre o algoritmo usado: NativePRNG ou SHA1PRNG. O uso de /dev/urandomseletores NativePRNG alimentados por /dev/urandomenquanto /dev/./urandomseleciona SHA1PRNG (também alimentado por /dev/urandom) ao usar o Java 8. A partir do Java 9 em diante, o DRBG prevalece quando a /dev/./urandomorigem é especificada.
dbaltor
1

Isso não é mais necessário se você estiver usando o JDK 8 ou superior

O problema foi corrigido pelo Java e aqui estão alguns links

Esboço

SHA1PRNG e NativePRNG foram corrigidos para respeitar adequadamente as propriedades de origem de semente SecureRandom no arquivo java.security. (A solução alternativa obscura usando file: /// dev / urandom e file: / dev /./ urandom não é mais necessária.)

Para mais informações (pesquise aleatoriamente na página):

https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8.html

https://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html

Venu Madhav
fonte
Eu não acredito que isso esteja correto. Para obter mais informações: tersesystems.com/blog/2015/12/17/… As correções no Java 8 dizem apenas que agora respeitam as propriedades de origem da semente SecureRandom no arquivo java.security. Mas, por padrão, ainda contém: securerandom.source = arquivo: / dev / random A "solução alternativa obscura" refere-se ao extra ./ no nome do arquivo, também mencionado pela resposta aceita (e mais votada) aqui.
Kamal
A "solução obscura" foi necessária apenas em circunstâncias específicas, consulte: bugs.java.com/bugdatabase/view_bug.do?bug_id=6202721
Kamal em
@ Kamal Os links que você postou referem-se ao Java 6 e anterior,
Venu Madhav
Esse é exatamente o ponto, foi corrigido no Java 8. De acordo com o relatório de erro, a "solução alternativa obscura" (adicionando ./ extra no nome do arquivo) foi necessária após o Java 1.4.2 e até 6. Estou assumindo no Java 7 também, caso contrário, não seria mencionado como corrigido no Java 8. A configuração / dev / urandom em vez de / dev / random ainda é necessária, se você deseja usar um dispositivo não-bloqueador.
Kamal
0

Isso está relacionado à diferença entre o linux /dev/randome o /dev/urandomgerador de números aleatórios.

Retirado deste link

O bug Java 6202721 afirma que o java.security.SecureRandom usa / dev / random em vez de / dev / urandom, mesmo que / dev / urandom seja especificado porque, na época (por volta de 2004) / dev / urandom não estava funcionando corretamente. O bug nunca foi revertido agora que / dev / urandom funciona muito bem. Portanto, você precisa fingir obscurecendo a configuração usando /dev/./urandom para forçar o uso de SHA1PRNG em vez de / dev / random.

Para responder sua pergunta

Quando deve ser aplicado?

Com base no link acima, isso é algo exclusivo das versões 5 e seguintes do Java que resultou de problemas com o / dev / urandom nos sistemas Linux em 2004.

Ruelos Joel
fonte
Provavelmente, existe um erro de digitação nesse artigo, pois o Java Bug 6202721 realmente afirma "Este é um problema se / dev / urandom foi escolhido porque / dev / random não está funcionando corretamente". Portanto, sua conclusão "resultou de problemas com / dev / urandom" está incorreta. Veja a resposta aceita para uma explicação sobre como escolher / dev / urandom em vez do padrão (/ dev / random). É uma boa ideia na maioria dos casos.
Kamal