Estoy tratando de implementar un algoritmo de cifrado basado en contraseña, pero obtengo esta excepción:
javax.crypto.BadPaddingException: el bloque final dado no se rellenó correctamente
¿Cuál podría ser el problema?
Aquí está mi código:
public class PasswordCrypter {
private Key key;
public PasswordCrypter(String password) {
try{
KeyGenerator generator;
generator = KeyGenerator.getInstance("DES");
SecureRandom sec = new SecureRandom(password.getBytes());
generator.init(sec);
key = generator.generateKey();
} catch (Exception e) {
e.printStackTrace();
}
}
public byte[] encrypt(byte[] array) throws CrypterException {
try{
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(array);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public byte[] decrypt(byte[] array) throws CrypterException{
try{
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(array);
} catch(Exception e ){
e.printStackTrace();
}
return null;
}
}
(La prueba JUnit)
public class PasswordCrypterTest {
private static final byte[] MESSAGE = "Alpacas are awesome!".getBytes();
private PasswordCrypter[] passwordCrypters;
private byte[][] encryptedMessages;
@Before
public void setUp() {
passwordCrypters = new PasswordCrypter[] {
new PasswordCrypter("passwd"),
new PasswordCrypter("passwd"),
new PasswordCrypter("otherPasswd")
};
encryptedMessages = new byte[passwordCrypters.length][];
for (int i = 0; i < passwordCrypters.length; i++) {
encryptedMessages[i] = passwordCrypters[i].encrypt(MESSAGE);
}
}
@Test
public void testEncrypt() {
for (byte[] encryptedMessage : encryptedMessages) {
assertFalse(Arrays.equals(MESSAGE, encryptedMessage));
}
assertFalse(Arrays.equals(encryptedMessages[0], encryptedMessages[2]));
assertFalse(Arrays.equals(encryptedMessages[1], encryptedMessages[2]));
}
@Test
public void testDecrypt() {
for (int i = 0; i < passwordCrypters.length; i++) {
assertArrayEquals(MESSAGE, passwordCrypters[i].decrypt(encryptedMessages[i]));
}
assertArrayEquals(MESSAGE, passwordCrypters[0].decrypt(encryptedMessages[1]));
assertArrayEquals(MESSAGE, passwordCrypters[1].decrypt(encryptedMessages[0]));
try {
assertFalse(Arrays.equals(MESSAGE, passwordCrypters[0].decrypt(encryptedMessages[2])));
} catch (CrypterException e) {
// Anything goes as long as the above statement is not true.
}
try {
assertFalse(Arrays.equals(MESSAGE, passwordCrypters[2].decrypt(encryptedMessages[1])));
} catch (CrypterException e) {
// Anything goes as long as the above statement is not true.
}
}
}
javax.crypto.BadPaddingException: Given final block not properly padded
. ¿Debería tratar esto como una clave incorrecta?Dependiendo del algoritmo de criptografía que esté utilizando, es posible que deba agregar algunos bytes de relleno al final antes de encriptar una matriz de bytes para que la longitud de la matriz de bytes sea múltiplo del tamaño del bloque:
Específicamente en su caso, el esquema de relleno que eligió es PKCS5, que se describe aquí: http://www.rsa.com/products/bsafe/documentation/cryptoj35html/doc/dev_guide/group_ CJ _SYM__PAD.html
(Supongo que tiene el problema cuando intenta cifrar)
Puede elegir su esquema de relleno cuando crea una instancia del objeto Cipher. Los valores admitidos dependen del proveedor de seguridad que esté utilizando.
Por cierto, ¿está seguro de que desea utilizar un mecanismo de cifrado simétrico para cifrar contraseñas? ¿No sería mejor un hash unidireccional? Si realmente necesita poder descifrar contraseñas, DES es una solución bastante débil, puede estar interesado en usar algo más fuerte como AES si necesita permanecer con un algoritmo simétrico.
fuente
Me encontré con este problema debido al sistema operativo, simple a una plataforma diferente sobre la implementación de JRE.
obtendrá el mismo valor en Windows, mientras que es diferente en Linux. Entonces en Linux debe cambiarse a
"SHA1PRNG" es el algoritmo utilizado, puede consultar aquí para obtener más información sobre los algoritmos.
fuente
Esto también puede ser un problema cuando ingresa una contraseña incorrecta para su clave de firma.
fuente