Seguridad de Java: ¿tamaño de clave ilegal o parámetros predeterminados?

409

Había hecho una pregunta sobre esto antes, pero no fue respondida correctamente y no condujo a ninguna parte.

Así que he aclarado algunos detalles sobre el problema y realmente me gustaría escuchar sus ideas sobre cómo podría solucionar esto o qué debería intentar.

Tengo Java 1.6.0.12 instalado en mi servidor Linux y el siguiente código se ejecuta perfectamente.

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);
}

Hoy instalé Java 1.6.0.26 en el usuario de mi servidor y cuando intento ejecutar mi aplicación, obtengo la siguiente excepción. Supongo que tiene algo que ver con la configuración de instalación de Java porque funciona en la primera, pero no funciona en la versión 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

La línea 25 es: c.init(Cipher.DECRYPT_MODE, secretKeySpec);

Notas:
* java.security en el directorio java 1.6.0.12 del servidor coincide casi por completo con el archivo java.security 1.6.0.26. No hay proveedores adicionales en el primero.
* La pregunta anterior está aquí .

Rihards
fuente
44
Esto también puede ser arrojado como error: Caused by: java.security.InvalidKeyException: Illegal key size(sin los "o parámetros predeterminados") en Java 8
hackajar
Simplemente use OpenJDK y funcionará.
Rodrigo Asensio
@RodrigoAsensio: estoy usando OpenJDK y no funciona con él. Debe instalar los archivos jar ilimitados de archivos de política de jurisdicción de fuerza. Y luego funcionará.
anjanb
55
Actualiza a la respuesta @AniketThakur. Desde Java 9 y Java 8u151 ya no es necesario descargar e instalar manualmente los archivos de política de jurisdicción. Para habilitar la criptografía ilimitada, se puede usar la nueva propiedad de seguridad crypto.policy. Si la nueva propiedad de seguridad (crypto.policy) se establece en el archivo java.security, o se ha establecido dinámicamente mediante la llamada Security.setProperty () antes de que se inicialice el marco JCE, se respetará esa configuración. Por defecto, la propiedad será indefinida.
Marcin Kłopotek

Respuestas:

722

Lo más probable es que no tenga el archivo de fuerza ilimitado instalado ahora.

Es posible que deba descargar este archivo:

Java Cryptography Extension (JCE) Archivos de política de jurisdicción de fuerza ilimitada 6

Java Cryptography Extension (JCE) Archivos de política de jurisdicción de fuerza ilimitada 7 Descargar

Java Cryptography Extension (JCE) Archivos de política de jurisdicción de fuerza ilimitada 8 Descarga (solo se requiere para versiones anteriores a Java 8 u162)

Extraiga los archivos jar del zip y guárdelos ${java.home}/jre/lib/security/.

James Black
fuente
2
@JamesBlack - Sí, y para asegurarse de que todas las bases estaban cubiertas puse debajo del JAR Java/jre/lib/security, Java/jdk/lib/securityy Java/jdk/jre/lib/security. Ejecutar 'java -version' devuelve los detalles esperados.
Aroth
55
Para el SDK de IBM (por ejemplo, WebSphere), descargue los archivos de política de jurisdicción ilimitada de www14.software.ibm.com/webapp/iwm/web/preLogin.do?source=jcesdk
quietmint
44
Desde Java 9 y Java 8u151 ya no es necesario descargar e instalar manualmente los archivos de política de jurisdicción. Para habilitar la criptografía ilimitada, se puede usar la nueva propiedad de seguridad crypto.policy. Si la nueva propiedad de seguridad (crypto.policy) se establece en el archivo java.security, o se ha establecido dinámicamente mediante la llamada Security.setProperty () antes de que se inicialice el marco JCE, se respetará esa configuración. Por defecto, la propiedad será indefinida.
Marcin Kłopotek
44
Por lo tanto, esta respuesta votada ahora está desactualizada y en desuso. ¿Cómo votamos o suprimimos esta respuesta para que stackoverflow.com/a/46857694/2808798 pueda ser la respuesta "aceptada"?
Jesse Adelman
3
@JesseAdelman - Lamentablemente, esto tiene casi 7 años, no se puede hacer mucho. Quien pregunte necesitaría cambiarlo.
James Black
54

Los archivos de jurisdicción JRE / JDK / Java 8 se pueden encontrar aquí:

Java Cryptography Extension (JCE) Archivos de política de jurisdicción de fuerza ilimitada 8 Descargar

Como James dijo anteriormente:
instale los archivos ${java.home}/jre/lib/security/.

Saad Malik
fuente
2
Intenté usar 6 y 7, pero no funcionaron. Tuve que instalar 8. Gracias.
Jason Kim
99
Nueva versión JDK 8u151 tiene "Nueva propiedad de seguridad para controlar la política de cifrado". Ahora es un cambio de propiedad para cambiar. El resultado final: elimine el "#" de la línea "# crypto.policy = unlimited" en "lib \ security \ java.security" para habilitar el uso de claves de 256 bits. oracle.com/technetwork/java/javase/8u151-relnotes-3850493.html
hemisphire
1
¡Gracias! Como se trata de una propiedad de seguridad, también puede llamar a Security.setProperty ("crypto.policy", "unlimited"). Fuente: enlace de
@hemisphire
42

Para JAVA 7, el enlace de descarga es jce-7-download

Copie los dos archivos jar descargados en Java \ jdk1.7.0_10 \ jre \ lib \ security
Haga una copia de seguridad de los archivos jar más antiguos para estar más seguro.

Para JAVA 8, el enlace de descarga es jce-8-download
Copie los frascos descargados en Java \ jdk1.8.0_45 \ jre \ lib \ security
Haga una copia de seguridad de los frascos más antiguos para estar más seguro.

C Deepak
fuente
39

Con Java 9, Java 8u161 , Java 7u171 y Java 6u181, la limitación ahora está desactivada de forma predeterminada. Ver problema en Java Bug Database .


A partir de Java 8u151 , puede deshabilitar la limitación mediante programación.

En versiones anteriores, los archivos de jurisdicción de JCE tenían que descargarse e instalarse por separado para permitir que el JDK utilizara criptografía ilimitada. Los pasos de descarga e instalación ya no son necesarios.

En cambio, ahora puede invocar la siguiente línea antes del primer uso de las clases JCE (es decir, preferiblemente justo después del inicio de la aplicación):

Security.setProperty("crypto.policy", "unlimited");
Sebastian S
fuente
¿Qué pasa en Android? ¿En qué nivel de API se pueden resolver estos métodos de restricción?
TheRealChx101
31

Esta es una solución de código único . No es necesario descargar ni meterse con los archivos de configuración.

Es una solución basada en la reflexión, probada en java 8

Llame a este método una vez, temprano en su programa.

// Importaciones

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
fuente
44
Tenga en cuenta que esto puede violar el acuerdo de licencia de Java SE: D. RESTRICCIONES DE TECNOLOGÍA JAVA. No puede crear, modificar o cambiar el comportamiento de, ni autorizar a sus licenciatarios para crear, modificar o cambiar el comportamiento de clases, interfaces o subpaquetes que de alguna manera se identifiquen como "java", "javax", " javafx "," sol "," oráculo "o convención similar a la especificada por Oracle en cualquier designación de convención de nomenclatura. [...] fuente
SimMac
Muchas gracias
16

Experimenté el mismo error al usar Windows 7 x64, Eclipse y JDK 1.6.0_30. En la carpeta de instalación de JDK hay una jrecarpeta. Esto me desconcertó al principio ya que estaba agregando los frascos antes mencionados a la carpeta lib / security del JDK sin suerte. Ruta completa:

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

Descargue y extraiga los archivos contenidos en la jcecarpeta de este archivo en esa carpeta.

Brian Bowman
fuente
16

En Java, de forma predeterminada, AES admite una clave de 128 bits, si planea utilizar una clave de 192 bits o 256 bits, Java cumplier lanzará una excepción de tamaño de clave ilegal, que está obteniendo.

La solución es, como sugirieron victor & James, deberá descargar JCE (Java Cryptography Extension) según su versión de JRE (java6, java7 o java8).

El zip JCE contiene el siguiente JAR:

  1. local_policy.jar
  2. US_export_policy.jar

Debe reemplazar estos frascos de su <JAVA_HOME>/jre/lib/security. si está en un sistema unix, probablemente se referirá a/home/urs/usr/lib/jvm/java-<version>-oracle/

A veces, simplemente reemplazar local_policy.jar, US_export_policy.jar en la carpeta de seguridad no funciona en Unix, por lo que sugiero copiar primero la carpeta de seguridad en su escritorio, reemplazar la carpeta de escritorio / seguridad del jar, eliminar la carpeta de seguridad de / jre / lib / & mueva la carpeta de seguridad del escritorio a / jre / lib /.

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

Ketan Vishwakarma
fuente
5

Hay una breve discusión de lo que parece ser el tema aquí . La página a la que enlaza parece haber desaparecido, pero una de las respuestas podría ser lo que necesita:

De hecho, fue útil copiar US_export_policy.jar y local_policy.jar de core / lib / jce a $ JAVA_HOME / jre / lib / security. Gracias.

RHSeeger
fuente
Gracias, pero ya tenía US_export_policy.jary local_policy.jaren mi carpeta lib / security una vez que instalé Java ... Y no pude encontrar core / lib / jce por cierto en mi carpeta de instalación de Java.
Rihards
5

el problema es el contenido del archivo default_local.policy en local_policy.jar en la carpeta jre \ lib \ security , si instala el 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;
};

Si no necesita configuraciones válidas en todo el mundo, simplemente puede editar este archivo y cambiar el contenido

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

esto es lo que obtienes si descargas el JCE de Oracle.

max
fuente
4

También recibí el problema, pero después de reemplazar uno existente con el descargado (de JCE), se resolvió el problema. Los nuevos archivos criptográficos proporcionaron una fuerza ilimitada.

Dev G
fuente
2

De forma predeterminada, Java solo admite tamaños de clave AES de 128 bits (16 bytes) para el cifrado. Si no necesita más de la compatibilidad predeterminada, puede recortar la clave al tamaño adecuado antes de usarla Cipher. Consulte javadoc para obtener las claves compatibles predeterminadas.

Este es un ejemplo de generación de una clave que funcionaría con cualquier versión de JVM sin modificar los archivos de política. Úselo a su propia discreción.

Aquí hay un buen artículo sobre si las claves de 128 a 256 tamaños de clave son importantes en el Blog de 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
fuente
La documentación de las clases de cifrado apunta a tamaños de clave válidos para cada tipo de cifrado.
keaplogik
Consulte el documento de Oracle Algoritmos de cifrado (cifrado) AES: Estándar de cifrado avanzado según lo especificado por NIST en FIPS 197. También conocido como el algoritmo Rijndael por Joan Daemen y Vincent Rijmen, AES es un cifrado de bloque de 128 bits que admite claves de 128, 192, y 256 bits.
zaph
Eso puede ser cierto, pero solo cada versión de Java requiere que sea compatible con 128 bits como se especifica en la documentación de la clase. Pruébelo usted mismo y descubrirá que necesitará el frasco de políticas de la respuesta de James Black para hacer otros tamaños de clave
keaplogik
Cualquier implementación de AES que no admitiera claves de 256 bits sería esencialmente inútil porque no sería capaz de descifrar cantidades importantes de cifrados AES utilizando claves de 256 bits.
zaph
1
Si se necesita una clave de 256 bits, la mejor solución, quizás la única solución, es instalar el archivo de Política si es necesario, no truncar la clave que potencialmente debilita la seguridad y puede no ser posible en el caso de la interoperabilidad.
zaph
2

A partir de Java 9 u 8u151, puede usar comentar una línea en el archivo:

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

Y cambio:

#crypto.policy=unlimited

a

crypto.policy=unlimited
Ahmed Ashour
fuente
2

Si está utilizando la distribución de Linux con apt y ha agregado PPA webupd8, simplemente puede ejecutar el comando

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

Otras actualizaciones

  1. Los archivos de política de jurisdicción de fuerza ilimitada se incluyen con Java 9 y se usan por defecto
  2. A partir de la Actualización 161 de Java 8, Java 8 adopta de manera predeterminada la Política de jurisdicción de fuerza ilimitada.
  3. A partir de la Actualización 151 de Java 8 , la Política de jurisdicción de fuerza ilimitada se incluye con Java 8 pero no se usa de manera predeterminada. Para habilitarlo, debe editar el archivo java.security en <java_home>/jre/lib/security(para JDK) o <java_home>/lib/security(para JRE). Descomentar (o incluir) la línea

    crypto.policy=unlimited

    Asegúrese de editar el archivo utilizando un editor ejecutado como administrador. El cambio de política solo tiene efecto después de reiniciar la JVM

Antes de Java 8 Update 151, el resto de las respuestas son válidas. Descargue los archivos de política de jurisdicción de fuerza ilimitada de JCE y reemplácelos.

Para obtener más detalles, puede consultar la publicación de mi blog personal a continuación: Cómo instalar los archivos de política de jurisdicción de fuerza ilimitada de Java Cryptography Extension (JCE)

Aniket Thakur
fuente
1

hay dos opciones para resolver este problema

opción número 1: usar certificado con menor longitud RSA 2048

opción número 2: actualizará dos frascos en jre\lib\security lo que utilice java http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

o utiliza IBM websphere o cualquier servidor de aplicaciones que use su java. El principal problema al que me enfrenté fue la certificación con la longitud máxima, cuando desplegué orejas en websphere, se lanzó la misma excepción

Java Security: Illegal key size or default parameters?

Actualicé la carpeta Java intsalled en websphere con dos frascos https://www14.software.ibm.com/webapp/iwm/web/reg/pick.do?source=jcesdk&lang=en_US

Puede consultar la referencia en el enlace https://www-01.ibm.com/support/docview.wss?uid=swg21663373

Shaaban Ebrahim
fuente
1

Asegúrese de utilizar la última versión de JDK / JRE .

En mi caso, había puesto JCE en la carpeta JRE, pero no ayudó. Sucedió porque estaba ejecutando mi proyecto desde el IDE directamente (usando JDK).

Luego actualicé mi JDK y JRE a la última versión (1.8.0_211) y el problema desapareció.

Más detalles: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8170157

Ruslan Sheremet
fuente
1

El JDK predeterminado admite el cifrado solo a través de claves de 128 bits debido a restricciones estadounidenses. Entonces, para admitir el cifrado a partir de una clave de 256 bits, debemos reemplazar local_policy.jary US_export_policy.jarsen la $JAVA_HOME/java-8-oracle/jre/lib/securitycarpeta, de lo contrario, dará:

java.security.InvalidKeyException: tamaño de clave ilegal o predeterminado

Sulabh Jain
fuente
0

Tienes que ir ahi

/jdk1.8.0_152 | / jre | / lib | / seguridad | java.security y descomentar el

#crypto.policy=unlimited

a

crypto.policy=unlimited
Fzum
fuente