stackoverflow - javax.crypto.IllegalBlockSizeException: La longitud de entrada debe ser mĂșltiple de 16 al descifrar con cifrado rellenado
java encrypt password (3)
Esta pregunta ya tiene una respuesta aquí:
Recibo un error de descifrado en clase java:
javax.crypto.IllegalBlockSizeException :
Input length must be multiple of 16 when decrypting with padded cipher.
¿Qué puedo hacer para resolver este problema?
ACTUALIZAR:
Olvidé mencionar que está funcionando una vez y cuando la segunda vez estoy tratando de ejecutarlo nuevamente, se produce el error mencionado anteriormente.
package com.tb.module.service;
import java.security.Key;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
/**
* This class is used for encrypt and decrypt the password field.
*
*/
public class PswdEnc {
private static final String ALGO = "AES";
private static final byte[] keyValue = new byte[] { ''T'', ''h'', ''e'', ''B'', ''e'', ''s'', ''t'',''S'', ''e'', ''c'', ''r'',''e'', ''t'', ''K'', ''e'', ''y'' };
public static String encrypt(String Data) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGO);
return key;
}
}
Algunos comentarios:
import sun.misc.*;
No hagas esto No es estándar y no se garantiza que sea igual entre las implementaciones. Hay otras bibliotecas con conversión de Base64 disponibles.
byte[] encVal = c.doFinal(Data.getBytes());
Estás confiando en la codificación de caracteres predeterminada aquí. Siempre especifique qué codificación de caracteres está utilizando: byte[] encVal = c.doFinal(Data.getBytes("UTF-8"));
Los valores predeterminados pueden ser diferentes en diferentes lugares.
Como lo señaló @thegrinner, debe verificar explícitamente la longitud de sus matrices de bytes. Si hay una discrepancia, entonces compárelas byte por byte para ver dónde está la diferencia.
Bueno, eso es debido a
solo puede cifrar datos en bloques de 128 bits o 16 bytes. Es por eso que está recibiendo la excepción IllegalBlockSizeException. y la única forma es cifrar esos datos directamente en la cadena.
mirar esto. Intenta y podrás resolver esto
public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
String decordedValue = new BASE64Decoder().decodeBuffer(encryptedData).toString().trim();
System.out.println("This is Data to be Decrypted" + decordedValue);
return decordedValue;
}
Espero que eso ayude.
El algoritmo que está utilizando, "AES", es una abreviatura de "AES / ECB / NoPadding". Lo que esto significa es que está utilizando el algoritmo AES con un tamaño de clave de 128 bits y un tamaño de bloque , con el modo de operación ECB y sin relleno .
En otras palabras: solo puede cifrar datos en bloques de 128 bits o 16 bytes. Es por eso que está recibiendo la excepción IllegalBlockSizeException
.
Si desea cifrar datos en tamaños que no sean múltiplos de 16 bytes, tendrá que usar algún tipo de relleno o una secuencia de cifrado. Por ejemplo, podría usar el modo CBC (un modo de operación que transforma efectivamente un cifrado de bloque en un cifrado de flujo ) especificando "AES / CBC / NoPadding" como algoritmo, o el relleno PKCS5 especificando "AES / ECB / PKCS5", que agregará automáticamente algunos bytes al final de sus datos en un formato muy específico para hacer que el tamaño del texto cifrado se multiplique por 16 bytes, y de manera que el algoritmo de descifrado entienda que debe ignorar algunos datos.
En cualquier caso, te sugiero encarecidamente que detengas ahora mismo lo que estás haciendo y estudies un poco de material introductorio sobre criptografía. Por ejemplo, compruebe Crypto I en Coursera . Debe comprender muy bien las implicaciones de elegir un modo u otro, cuáles son sus fortalezas y, lo más importante, sus debilidades. Sin este conocimiento, es muy fácil construir sistemas que son muy fáciles de romper.
Actualización: en base a sus comentarios sobre la pregunta, ¡¡¡nunca encripte las contraseñas cuando las almacene en una base de datos ! Nunca debes hacer esto. Debe HASH las contraseñas, debidamente saladas, que son completamente diferentes de cifrar. Realmente, por favor, no haga lo que está tratando de hacer ... Al cifrar las contraseñas, se pueden descifrar. Lo que esto significa es que usted, como administrador de la base de datos y quien conoce la clave secreta, podrá leer cada contraseña almacenada en su base de datos. O bien sabías esto y estás haciendo algo muy, muy mal, o no lo sabías, y deberías escandalizarte y detenerlo.