Necesito implementar el cifrado AES de 256 bits, pero todos los ejemplos que he encontrado en línea usan un "KeyGenerator" para generar una clave de 256 bits, pero me gustaría usar mi propia contraseña. ¿Cómo puedo crear mi propia clave? He intentado rellenarlo a 256 bits, pero luego aparece un error que dice que la clave es demasiado larga. Tengo instalado el parche de jurisdicción ilimitada, así que ese no es el problema :)
Es decir. El KeyGenerator se ve así ...
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
EDITAR
En realidad, estaba rellenando la contraseña a 256 bytes, no bits, que es demasiado largo. El siguiente es un código que estoy usando ahora que tengo más experiencia con esto.
byte[] key = null; // TODO
byte[] input = null; // TODO
byte[] output = null;
SecretKeySpec keySpec = null;
keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(input)
Los bits "TODO" que debes hacer tú mismo :-)
java
encryption
cryptography
passwords
aes
Nippysaurus
fuente
fuente
Respuestas:
Comparta el
password
(achar[]
) ysalt
(unbyte[]
—8 bytes seleccionados por unSecureRandom
hace una buena sal — que no necesita mantenerse en secreto) con el receptor fuera de banda. Luego, para obtener una buena clave de esta información:Los números mágicos (que podrían definirse como constantes en alguna parte) 65536 y 256 son el recuento de iteración de derivación de clave y el tamaño de clave, respectivamente.
La función de derivación de clave se repite para requerir un esfuerzo computacional significativo, y eso evita que los atacantes prueben rápidamente muchas contraseñas diferentes. El recuento de iteraciones se puede cambiar según los recursos informáticos disponibles.
El tamaño de la clave se puede reducir a 128 bits, lo que todavía se considera cifrado "fuerte", pero no da mucho margen de seguridad si se descubren ataques que debilitan AES.
Utilizado con un modo de encadenamiento de bloques adecuado, la misma clave derivada se puede utilizar para cifrar muchos mensajes. En Cipher Block Chaining (CBC) , se genera un vector de inicialización aleatorio (IV) para cada mensaje, produciendo un texto de cifrado diferente incluso si el texto plano es idéntico. CBC puede no ser el modo más seguro disponible para usted (vea AEAD a continuación); Hay muchos otros modos con diferentes propiedades de seguridad, pero todos usan una entrada aleatoria similar. En cualquier caso, las salidas de cada operación de cifrado son el texto cifrado y el vector de inicialización:
Almacene el
ciphertext
y eliv
. En el descifrado,SecretKey
se regenera exactamente de la misma manera, utilizando la contraseña con los mismos parámetros de sal e iteración. Inicialice el cifrado con esta clave y el vector de inicialización almacenado con el mensaje:Java 7 incluyó soporte API para modos de cifrado AEAD , y el proveedor "SunJCE" incluido con las distribuciones OpenJDK y Oracle implementa estos a partir de Java 8. Se recomienda uno de estos modos en lugar de CBC; Protegerá la integridad de los datos y su privacidad.
A
java.security.InvalidKeyException
con el mensaje "Tamaño de clave ilegal o parámetros predeterminados" significa que la intensidad de la criptografía es limitada; los archivos de política de jurisdicción de fuerza ilimitada no están en la ubicación correcta. En un JDK, deben colocarse debajo${jdk}/jre/lib/security
Según la descripción del problema, parece que los archivos de políticas no están instalados correctamente. Los sistemas pueden tener fácilmente múltiples tiempos de ejecución de Java; vuelva a verificar para asegurarse de que se esté utilizando la ubicación correcta.
fuente
PBEwith<prf>and<encryption>
algoritmos; por ejemplo, SunJCE no proporciona y PBE para AES. En segundo lugar, habilitar jasypt no es un objetivo. Un paquete que pretende ofrecer seguridad sin requerir una comprensión de los principios subyacentes parece peligroso a primera vista.tmp.getEncoded()
como el hash. También debe almacenar lassalt
iteraciones y (65536 en este ejemplo) para que pueda volver a calcular el hash cuando alguien intenta autenticarse. En este caso, genere la sal con un generador de números aleatorios criptográficos cada vez que se cambie la contraseña.Considere usar el Módulo criptográfico Spring Security
Proporciona una abstracción simple para el cifrado y parece coincidir con lo que se requiere aquí,
Una mirada a las partes internas revela una estructura similar a la respuesta de Erickson .
Como se señaló en la pregunta, esto también requiere la Política de jurisdicción de fuerza ilimitada de Java Cryptography Extension (JCE) (de lo contrario, se encontrará
InvalidKeyException: Illegal Key Size
). Es descargable para Java 6 , Java 7 y Java 8 .Ejemplo de uso
Y salida de muestra,
fuente
NULL_IV_GENERATOR
utilizado por la utilidad Spring no es seguro. Si la aplicación no proporciona un IV, deje que el proveedor lo elija y consulte después de la inicialización.Después de leer las sugerencias de Erickson y obtener lo que pude de otras publicaciones y este ejemplo aquí , intenté actualizar el código de Doug con los cambios recomendados. Siéntase libre de editar para mejorarlo.
Algunas notas: esto utiliza una clave de cifrado de 128 bits; Java aparentemente no hará un cifrado de 256 bits listo para usar. La implementación de 256 requiere la instalación de algunos archivos adicionales en el directorio de instalación de Java.
Además, no soy una persona criptográfica. Presta atención.
fuente
printStackTrace()
CipherInputStream
yCipherOutputStream
no es un gran problema. Mezclar todas las excepciones debajo de la tabla es un problema. El hecho de que la sal de repente se haya convertido en un campo y que se requiera la IV es un problema. El hecho de que no siga las convenciones de codificación de Java es un problema. Y el hecho de que esto solo funcione en archivos mientras no se solicitó es un problema. Y que el resto del código es básicamente una copia tampoco ayuda. Pero tal vez lo modifique para mejorarlo, como se sugiere ...Generar su propia clave a partir de una matriz de bytes es fácil:
Pero crear una clave de 256 bits no es suficiente. Si el generador de claves no puede generar claves de 256 bits para usted, entonces la
Cipher
clase probablemente tampoco sea compatible con AES de 256 bits. Dice que tiene instalado el parche de jurisdicción ilimitada, por lo que el cifrado AES-256 debe ser compatible (pero también las claves de 256 bits también, así que esto podría ser un problema de configuración).Una solución alternativa para la falta de compatibilidad con AES-256 es tomar alguna implementación de AES-256 disponible gratuitamente y usarla como un proveedor personalizado. Esto implica crear su propia
Provider
subclase y usarla conCipher.getInstance(String, Provider)
. Pero esto puede ser un proceso complicado.fuente
Cipher
, no en el propio proveedor. Puede usar AES-256 en Java 8 y versiones anteriores, pero debe usar una API patentada. O un tiempo de ejecución que no plantea restricciones en el tamaño de la clave, por supuesto.Lo que he hecho en el pasado es hash la clave a través de algo como SHA256, luego extraiga los bytes del hash en el byte de clave [].
Después de tener su byte [] simplemente puede hacer:
fuente
Cipher aes256 = Cipher.getInstance("AES/OFB/NoPadding"); MessageDigest keyDigest = MessageDigest.getInstance("SHA-256"); byte[] keyHash = keyDigest.digest(secret.getBytes("UTF-8")); SecretKeySpec key = new SecretKeySpec(keyHash, "AES"); aes256.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(initializationVector));
También estoy haciendo lo mismo que lo sugerido en su respuesta, pero todavía termino con este java.security.InvalidKeyException: tamaño de clave ilegal ¿Es obligatorio descargar el archivo de política JCE?Además de las ediciones de @ Wufoo, la siguiente versión usa InputStreams en lugar de archivos para facilitar el trabajo con una variedad de archivos. También almacena el IV y Salt al comienzo del archivo, por lo que solo es necesario rastrear la contraseña. Dado que el IV y la sal no necesitan ser secretos, esto hace la vida un poco más fácil.
fuente
(Tal vez útil para otros con un requisito similar)
Tenía un requisito similar para usar
AES-256-CBC
cifrar y descifrar en Java.Para lograr (o especificar) el cifrado / descifrado de 256 bytes, la
Java Cryptography Extension (JCE)
política debe establecerse en"Unlimited"
Se puede configurar en el
java.security
archivo bajo$JAVA_HOME/jre/lib/security
(para JDK) o$JAVA_HOME/lib/security
(para JRE)crypto.policy=unlimited
O en el código como
Java 9 y versiones posteriores tienen esto habilitado por defecto.
fuente
Considere usar Encryptor4j del cual soy el autor.
Primero asegúrese de tener instalados los archivos de la Política de jurisdicción de fuerza ilimitada antes de proceder para que pueda usar las claves AES de 256 bits.
Luego haz lo siguiente:
Ahora puede usar el encriptador para encriptar su mensaje. También puede realizar el cifrado de transmisión si lo desea. Genera y antepone automáticamente un IV seguro para su conveniencia.
Si es un archivo que desea comprimir, eche un vistazo a esta respuesta Cifrar un archivo grande con AES usando JAVA para un enfoque aún más simple.
fuente
Use esta clase para el cifrado. Funciona.
Y estos son ivBytes y una clave aleatoria;
fuente