Segurança Java: tamanho de chave ilegal ou parâmetros padrão?

409

Eu fiz uma pergunta sobre isso antes, mas ela não foi respondida corretamente e não levou a lugar algum.

Portanto, esclareço alguns detalhes sobre o problema e gostaria muito de ouvir suas idéias sobre como corrigir isso ou o que devo tentar.

Eu tenho o Java 1.6.0.12 instalado no meu servidor Linux e o código abaixo funciona perfeitamente.

String key = "av45k1pfb024xa3bl359vsb4esortvks74sksr5oy4s5serondry84jsrryuhsr5ys49y5seri5shrdliheuirdygliurguiy5ru";
try {
    Cipher c = Cipher.getInstance("ARCFOUR");

    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "ARCFOUR");
    c.init(Cipher.DECRYPT_MODE, secretKeySpec);

    return new String(c.doFinal(Hex.decodeHex(data.toCharArray())), "UTF-8");

} catch (InvalidKeyException e) {
    throw new CryptoException(e);
}

Hoje instalei o Java 1.6.0.26 no meu usuário do servidor e quando tento executar meu aplicativo, recebo a seguinte exceção. Meu palpite seria que ele tem algo a ver com a configuração da instalação Java, porque funciona na primeira, mas não funciona na versão posterior.

Caused by: java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
    at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
    at my.package.Something.decode(RC4Decoder.java:25) ~[my.package.jar:na]
    ... 5 common frames omitted

A linha 25 é: c.init(Cipher.DECRYPT_MODE, secretKeySpec);

Notas:
* java.security no diretório java 1.6.0.12 do servidor corresponde quase completamente ao arquivo java.security 1.6.0.26 . Não há fornecedores adicionais no primeiro.
* A pergunta anterior está aqui .

Rihards
fonte
4
Isso também pode ser gerado como erro: Caused by: java.security.InvalidKeyException: Illegal key size(sem os "ou parâmetros padrão") no Java 8
hackajar
Basta usar o OpenJDK e ele funcionará.
Rodrigo Asensio
@RodrigoAsensio: Estou usando o OpenJDK e ele não funciona. Você deve instalar os arquivos jar ilimitados do Strength Jurisdiction Policy Files. E então vai funcionar.
Anjanb
5
Atualize para a resposta @AniketThakur. Desde o Java 9 e o Java 8u151, não é mais necessário baixar e instalar manualmente os arquivos de políticas de jurisdição. Para habilitar criptografia ilimitada, pode-se usar a nova propriedade crypto.policy Security. Se a nova propriedade Security (crypto.policy) estiver configurada no arquivo java.security ou tiver sido configurada dinamicamente usando a chamada Security.setProperty () antes da inicialização da estrutura do JCE, essa configuração será respeitada. Por padrão, a propriedade será indefinida.
Marcin Kłopotek

Respostas:

722

Provavelmente você não tem o arquivo de força ilimitado instalado agora.

Pode ser necessário fazer o download deste arquivo:

Arquivos de política de jurisdição de força ilimitada da Java Cryptography Extension (JCE) 6

Arquivos de política de jurisdição de força ilimitada da Java Cryptography Extension (JCE) 7 Download

Arquivos de política de jurisdição de força ilimitada da Java Cryptography Extension (JCE) 8 Download (necessário apenas para versões anteriores ao Java 8 u162)

Extraia os arquivos jar do zip e salve-os ${java.home}/jre/lib/security/.

James Black
fonte
2
@JamesBlack - Sim, e para se certificar de todas as bases foram cobertas I colocado sob o JAR Java/jre/lib/security, Java/jdk/lib/securitye Java/jdk/jre/lib/security. Executar 'java -version' retorna os detalhes esperados.
Aroth 26/10/12
5
Para o SDK da IBM (por exemplo, WebSphere), faça o download dos arquivos de política de jurisdição ilimitada em www14.software.ibm.com/webapp/iwm/web/preLogin.do?source=jcesdk
quietmint 27/12/13
4
Desde o Java 9 e o Java 8u151, não é mais necessário baixar e instalar manualmente os arquivos de políticas de jurisdição. Para habilitar criptografia ilimitada, pode-se usar a nova propriedade crypto.policy Security. Se a nova propriedade Security (crypto.policy) estiver configurada no arquivo java.security ou tiver sido configurada dinamicamente usando a chamada Security.setProperty () antes da inicialização da estrutura do JCE, essa configuração será respeitada. Por padrão, a propriedade será indefinida.
Marcin Kłopotek
4
Portanto, esta resposta votada está desatualizada e obsoleta. Como aprovamos ou suprimimos esta resposta para que stackoverflow.com/a/46857694/2808798 possa ser a resposta "aceita"?
Jesse Adelman
3
@JesseAdelman - Infelizmente, isso tem quase 7 anos, pouco pode ser feito. Quem pediu precisaria mudar isso.
18718 James Black
54

Os arquivos de jurisdição JRE / JDK / Java 8 podem ser encontrados aqui:

Arquivos de política de jurisdição de força ilimitada da Java Cryptography Extension (JCE) 8 Download

Como James disse acima:
Instale os arquivos no ${java.home}/jre/lib/security/.

Saad Malik
fonte
2
Tentei usar 6 e 7, mas eles não funcionaram. Teve que instalar 8. Obrigado.
Jason Kim
9
A nova versão do JDK 8u151 possui "Nova propriedade de segurança para controlar a política de criptografia". Agora é uma alteração de propriedade para alternar. A linha inferior: remova o "#" da linha "# crypto.policy = unlimited" em "lib \ security \ java.security" para ativar o uso de chaves de 256 bits. oracle.com/technetwork/java/javase/8u151-relnotes-3850493.html
hemisphire
1
Obrigado! Como essa é uma propriedade de segurança, você também pode chamar Security.setProperty ("crypto.policy", "ilimitado"). Fonte: link de
@hemisphire
42

Para o JAVA 7, o link de download é jce-7-download

Copie os dois frascos baixados em Java \ jdk1.7.0_10 \ jre \ lib \ security
Faça um backup de frascos antigos para ficar mais seguro.

Para o JAVA 8, o link de download é jce-8-download
Copie os jars baixados em Java \ jdk1.8.0_45 \ jre \ lib \ security
Faça um backup dos jars antigos para ficar mais seguro.

C Deepak
fonte
39

Com Java 9, Java 8u161 , Java 7u171 e Java 6u181, a limitação agora está desativada por padrão. Veja o problema no Java Bug Database .


A partir do Java 8u151, é possível desativar a limitação programaticamente.

Em versões mais antigas, os arquivos de jurisdição JCE precisavam ser baixados e instalados separadamente para permitir que criptografia ilimitada fosse usada pelo JDK. As etapas de download e instalação não são mais necessárias.

Agora você pode chamar a seguinte linha antes do primeiro uso das classes JCE (ou seja, de preferência logo após o início do aplicativo):

Security.setProperty("crypto.policy", "unlimited");
Sebastian S
fonte
E no Android? Em qual nível da API esses métodos de restrição podem ser resolvidos?
TheRealChx101 9/01/19
31

Esta é uma solução apenas de código . Não há necessidade de baixar ou mexer com arquivos de configuração.

É uma solução baseada em reflexão, testada em java 8

Chame esse método uma vez, no início do seu programa.

// Importações

import javax.crypto.Cipher;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;

//método

public static void fixKeyLength() {
    String errorString = "Failed manually overriding key-length permissions.";
    int newMaxKeyLength;
    try {
        if ((newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES")) < 256) {
            Class c = Class.forName("javax.crypto.CryptoAllPermissionCollection");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissionCollection = con.newInstance();
            Field f = c.getDeclaredField("all_allowed");
            f.setAccessible(true);
            f.setBoolean(allPermissionCollection, true);

            c = Class.forName("javax.crypto.CryptoPermissions");
            con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissions = con.newInstance();
            f = c.getDeclaredField("perms");
            f.setAccessible(true);
            ((Map) f.get(allPermissions)).put("*", allPermissionCollection);

            c = Class.forName("javax.crypto.JceSecurityManager");
            f = c.getDeclaredField("defaultPolicy");
            f.setAccessible(true);
            Field mf = Field.class.getDeclaredField("modifiers");
            mf.setAccessible(true);
            mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
            f.set(null, allPermissions);

            newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");
        }
    } catch (Exception e) {
        throw new RuntimeException(errorString, e);
    }
    if (newMaxKeyLength < 256)
        throw new RuntimeException(errorString); // hack failed
}

Créditos: Delthas

Jako
fonte
4
Observe que isso pode violar o contrato de licença do Java SE: D. RESTRIÇÕES DE TECNOLOGIA JAVA. Você não pode criar, modificar ou alterar o comportamento ou autorizar seus licenciados a criar, modificar ou alterar o comportamento de classes, interfaces ou subpacotes identificados de qualquer forma como "java", "javax", " javafx", "sol",‘oráculo’ou convenção semelhante, conforme especificado pela oracle em qualquer designação convenção de nomenclatura [...]. source
SimMac
Muito obrigado
16

Ocorreu o mesmo erro ao usar o Windows 7 x64, Eclipse e JDK 1.6.0_30. Na pasta de instalação do JDK, há uma jrepasta. Isso me assustou no começo, pois eu adicionava os frascos acima mencionados à pasta lib / security do JDK sem sorte. Caminho completo:

C:\Program Files\Java\jdk1.6.0_30\jre\lib\security

Faça o download e extraia os arquivos contidos na jcepasta deste arquivo para essa pasta.

Brian Bowman
fonte
16

Em Java, por padrão, o AES suporta uma chave de 128 bits, se você planeja usar a chave de 192 bits ou 256 bits, o java complier emitirá uma exceção de tamanho de chave ilegal, que você está recebendo.

A solução é tão vitoriosa e sugerida por James, você precisará fazer o download do JCE (Java Cryptography Extension) conforme sua versão do JRE (java6, java7 ou java8).

O zip do JCE contém o seguinte JAR:

  1. local_policy.jar
  2. US_export_policy.jar

Você precisa substituir esses recipientes do seu <JAVA_HOME>/jre/lib/security. se você estiver em um sistema unix, provavelmente se referirá a/home/urs/usr/lib/jvm/java-<version>-oracle/

Às vezes, apenas substituir local_policy.jar, US_export_policy.jar na pasta de segurança não funciona no unix, então sugiro copiar a pasta de segurança para a área de trabalho primeiro, substituir a pasta @ Desktop / security do jar, excluir a pasta de segurança de / jre / lib / e mova a pasta de segurança da área de trabalho para / jre / lib /.

por exemplo: sudo mv security /usr/lib/jvm/java-7-oracle/jre/lib

Ketan Vishwakarma
fonte
5

Há uma breve discussão sobre o que parece ser esse problema aqui . A página para a qual ele vincula parece ter desaparecido, mas uma das respostas pode ser o que você precisa:

De fato, copiar US_export_policy.jar e local_policy.jar do core / lib / jce para $ JAVA_HOME / jre / lib / security ajudou. Obrigado.

RHSeeger
fonte
Obrigado, mas eu tinha US_export_policy.jare local_policy.jarna minha pasta lib / segurança já uma vez eu instalei o Java .. E eu não poderia encontrar core / lib / JCE pela maneira na minha pasta de instalação do Java.
Rihards 26/06
5

o problema é o conteúdo do arquivo default_local.policy em local_policy.jar na pasta jre \ lib \ security , se você instalar o JRE:

// Some countries have import limits on crypto strength. This policy file
// is worldwide importable.

grant {
    permission javax.crypto.CryptoPermission "DES", 64;
    permission javax.crypto.CryptoPermission "DESede", *;
    permission javax.crypto.CryptoPermission "RC2", 128,
                                     "javax.crypto.spec.RC2ParameterSpec", 128;
    permission javax.crypto.CryptoPermission "RC4", 128;
    permission javax.crypto.CryptoPermission "RC5", 128,
          "javax.crypto.spec.RC5ParameterSpec", *, 12, *;
    permission javax.crypto.CryptoPermission "RSA", *;
    permission javax.crypto.CryptoPermission *, 128;
};

se você não precisar de configurações válidas em todo o mundo, basta editar este arquivo e alterar o conteúdo para

// Country-specific policy file for countries with no limits on crypto strength.
grant {
    // There is no restriction to any algorithms.
    permission javax.crypto.CryptoAllPermission;
};

é isso que você obtém se você baixar o JCE da Oracle.

max
fonte
4

Também obtive o problema, mas depois de substituir o existente pelo baixado (do JCE), resolvi-o. Novos arquivos de criptografia forneceram força ilimitada.

Dev G
fonte
2

Por padrão, o Java suporta apenas tamanhos de chave AES de 128 bits (16 bytes) para criptografia. Se você não precisar de mais do que o padrão suportado, poderá cortar a chave no tamanho adequado antes de usar Cipher. Consulte javadoc para obter as chaves suportadas padrão.

Este é um exemplo de geração de uma chave que funcionaria com qualquer versão da JVM sem modificar os arquivos de políticas. Use a seu próprio critério.

Aqui está um bom artigo sobre se os tamanhos das chaves de 128 a 256 são importantes no Blog do AgileBits

SecretKeySpec getKey() {
    final pass = "47e7717f0f37ee72cb226278279aebef".getBytes("UTF-8");
    final sha = MessageDigest.getInstance("SHA-256");

    def key = sha.digest(pass);
    // use only first 128 bit (16 bytes). By default Java only supports AES 128 bit key sizes for encryption.
    // Updated jvm policies are required for 256 bit.
    key = Arrays.copyOf(key, 16);
    return new SecretKeySpec(key, AES);
}
keaplogik
fonte
A documentação das classes Cipher aponta para tamanhos de chave válidos para cada tipo de criptografia.
keaplogik
Consulte o documento Oracle Algoritmos de criptografia (criptografia) AES: Advanced Encryption Standard, conforme especificado pelo NIST no FIPS 197. Também conhecido como algoritmo de Rijndael por Joan Daemen e Vincent Rijmen, o AES é uma cifra de bloco de 128 bits que suporta chaves de 128, 192, e 256 bits.
Zaph
Isso pode ser verdade, mas é exigido apenas por cada versão Java para suportar 128 bits, conforme especificado na documentação da classe. Teste você mesmo e verá que precisará do jar de políticas da resposta de James Black para fazer outros tamanhos de chave
keaplogik
Qualquer implementação do AES que não suportasse chaves de 256 bits seria essencialmente inútil porque não seria capaz de descriptografar números substanciais de criptografias do AES usando chaves de 256 bits.
Zaph
1
Se uma chave de 256 bits é necessária, a melhor solução, talvez a única solução, é instalar o arquivo de diretivas, se necessário, não truncar a chave que enfraquece a segurança e pode não ser possível no caso de interoperabilidade.
Zaph
2

A partir do Java 9 ou 8u151, é possível usar uma linha de comentário no arquivo:

<JAVA_HOME>/jre/lib/security/java.security

E mudar:

#crypto.policy=unlimited

para

crypto.policy=unlimited
Ahmed Ashour
fonte
2

Se você estiver usando a distribuição Linux com o apt e tiver adicionado o webupd8 PPA, basta executar o comando

apt-get install oracle-java8-unlimited-jce-policy

Outras atualizações:

  1. Os Arquivos de Política de Jurisdição de Força Ilimitada estão incluídos no Java 9 e são usados ​​por padrão
  2. A partir do Java 8 Update 161 , o Java 8 padroniza a Política de Jurisdição de Força Ilimitada.
  3. A partir da atualização 151 do Java 8 , a Política de jurisdição de força ilimitada é incluída no Java 8, mas não é usada por padrão. Para habilitá-lo, é necessário editar o arquivo java.security em <java_home>/jre/lib/security(para JDK) ou <java_home>/lib/security(para JRE). Remova o comentário (ou inclua) a linha

    crypto.policy=unlimited

    Certifique-se de editar o arquivo usando um editor executado como administrador. A mudança de política entra em vigor somente após reiniciar a JVM

Antes do Java 8 Update 151, o restante das respostas é válido. Faça o download dos arquivos de políticas de jurisdição de força ilimitada do JCE e substitua.

Para obter mais detalhes, você pode consultar minha postagem no blog pessoal abaixo - Como instalar arquivos de política de jurisdição de força ilimitada do Java Cryptography Extension (JCE)

Aniket Thakur
fonte
1

existem duas opções para resolver esse problema

opção número 1: use certificado com menos comprimento RSA 2048

opção número 2: você atualizará dois jars no jre\lib\security que usar java http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

ou você usa o IBM websphere ou qualquer servidor de aplicativos que usa seu java. o principal problema que enfrentei, usei a certificação com comprimento máximo, quando implantei ouvidos no websphere a mesma exceção é lançada

Java Security: Illegal key size or default parameters?

eu atualizei a pasta java intsalled no websphere com dois jars https://www14.software.ibm.com/webapp/iwm/web/reg/pick.do?source=jcesdk&lang=pt_BR

você pode verificar a referência no link https://www-01.ibm.com/support/docview.wss?uid=swg21663373

Shaaban Ebrahim
fonte
1

Certifique-se de usar a versão mais recente do JDK / JRE .

No meu caso, eu coloquei o JCE na pasta JRE, mas não ajudou. Isso aconteceu porque eu estava executando meu projeto diretamente do IDE (usando o JDK).

Atualizei meu JDK e JRE para a versão mais recente (1.8.0_211) e o problema havia passado.

Mais detalhes: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8170157

Ruslan Sheremet
fonte
1

O JDK padrão suporta criptografia apenas através de chaves de 128 bits, devido às restrições americanas. Então, para criptografia apoio de chave longa 256 bit temos de substituir local_policy.jare US_export_policy.jarsna $JAVA_HOME/java-8-oracle/jre/lib/securitypasta caso contrário ele vai dar:

java.security.InvalidKeyException: tamanho da chave ilegal ou padrão

Sulabh Jain
fonte
0

Você precisa ir lá

/jdk1.8.0_152 / jre | / lib | / segurança | java.security e descomente o

#crypto.policy=unlimited

para

crypto.policy=unlimited
Fzum
fonte