Estou tentando implementar um algoritmo de criptografia baseado em senha, mas recebo esta exceção:
javax.crypto.BadPaddingException: bloco final fornecido não preenchido corretamente
Qual pode ser o problema?
Aqui está o meu 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;
}
}
(O teste 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
. Devo tratar isso como uma chave errada?dependendo do algoritmo de criptografia que você está usando, pode ser necessário adicionar alguns bytes de preenchimento no final antes de criptografar uma matriz de bytes para que o comprimento da matriz de bytes seja múltiplo do tamanho do bloco:
Especificamente no seu caso, o esquema de preenchimento que você escolheu é PKCS5, que é descrito aqui: http://www.rsa.com/products/bsafe/documentation/cryptoj35html/doc/dev_guide/group_ CJ _SYM__PAD.html
(Presumo que você tenha o problema ao tentar criptografar)
Você pode escolher seu esquema de preenchimento ao instanciar o objeto Cipher. Os valores suportados dependem do provedor de segurança que você está usando.
A propósito, você tem certeza de que deseja usar um mecanismo de criptografia simétrica para criptografar senhas? Não seria melhor um hash unilateral? Se você realmente precisa ser capaz de descriptografar senhas, o DES é uma solução bastante fraca, você pode estar interessado em usar algo mais forte como AES se precisar ficar com um algoritmo simétrico.
fonte
Eu conheci esse problema devido ao sistema operacional, simples para plataforma diferente sobre a implementação do JRE.
terá o mesmo valor no Windows, mas será diferente no Linux. Portanto, no Linux precisa ser alterado para
"SHA1PRNG" é o algoritmo usado, você pode consultar aqui para obter mais informações sobre algoritmos.
fonte
Isso também pode ser um problema quando você insere a senha errada para sua chave de assinatura.
fonte