BadPaddingException только с буквами, такими как "o", "b", "c" - PullRequest
1 голос
/ 27 марта 2019

Я делаю программу, которая работает с криптографией сообщений Socket.Но когда в моих сообщениях есть «o», «b» или «c» и другие буквы, я получаю это исключение в момент расшифровки.

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
    at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at teste1.Decrypt.decrypt(Decrypt.java:15)
    at teste1.Server.main(Server.java:24)

Да, мое сообщение прибывает завершенным со всеми символами, так что я не думаю, что какой-то персонаж был потерян в передаче.Так что я действительно не знаю, в чем проблема, потому что я пытался многое изменить, но я продолжал получать это исключение.

Расшифровать класс:

package teste1;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;

public class Decrypt{

    String IV = "AAAAAAAAAAAAAAAA";

    public String decrypt(String str, String keys) throws Exception{
        Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(keys.getBytes("UTF-8"), "AES");
        decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
        return new String(decrypt.doFinal(str.getBytes()),"UTF-8");
    }

}

Если хочеткласс шифрования тоже:

package teste1;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Encrypt {

    String IV = "AAAAAAAAAAAAAAAA";

    public byte[] encrypt(String menE, String keys) throws Exception {
        Cipher encrypt = Cipher.getInstance("AES/EBC/PKCS5Padding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(keys.getBytes("UTF-8"), "AES");
        encrypt.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
        return encrypt.doFinal(menE.getBytes());
    }
}

1 Ответ

2 голосов
/ 28 марта 2019

Это происходит из-за того, что строки изменяют ваши байты, вам действительно следует использовать Base64 , если строки обязательны.

Если вы хотите протестировать этот код:

byte[] aByte = {-45};
System.out.println(Arrays.toString(new String(aByte, StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8)));

Будет выведено: [-17, -65, -67] (что не -45).

В любом случае, несколько советов для вас:

  • Вы не можетешифровать с помощью «ECB» и расшифровывать с помощью «CBC».
  • IV не должно быть константой.вы должны сгенерировать новый IV для каждого сообщения и отправить его вместе с сообщением.
  • Не указывайте "UTF-8" use StandardCharsets.UTF_8 (обратите внимание, что при использовании android: StandardCharsets.UTF-8 - это API 19+, поэтому вам следуетесть константа для Charset.forName("UTF-8"))

Вот пример кода для того, как сделать это с Base64:

public byte[] encrypt(String message, String key, String iv) throws Exception {
        Cipher encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
        encrypt.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(Base64.getDecoder().decode(iv)));
        return encrypt.doFinal(/*Get bytes from your message*/message.getBytes(StandardCharsets.UTF_8));
    }

    public String decrypt(String encryptedMessage, String key, String iv) throws Exception{
        Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
        decrypt.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(Base64.getDecoder().decode(iv)));
        return new String(decrypt.doFinal(Base64.getDecoder().decode(encryptedMessage)), StandardCharsets.UTF_8);
    }

И запустить его с

//your message
    String message = "Hello World!";
    //generate a new AES key. (an AES key is just a random sequence 16 bytes)
    SecureRandom random = new SecureRandom();
    byte[] aesKey = new byte[16];
    random.nextBytes(aesKey);
    //generate a new initialization vector (iv) which is also a random sequence of 16 bytes.
    byte[] iv = new byte[16];
    random.nextBytes(iv);

    String aesKeyAsString = Base64.getEncoder().encodeToString(aesKey);
    String ivAsString = Base64.getEncoder().encodeToString(iv);
    //encrypt
    byte[] encrypted = encrypt(message, aesKeyAsString, ivAsString);
    //enocde your encrypted byte[] to String
    String encryptedString = Base64.getEncoder().encodeToString(encrypted);
    //decrypt
    String decrypted = decrypt(encryptedString, aesKeyAsString, ivAsString);
    //print your results
    System.out.println("Encrypted: " + encryptedString + " Decrypted: " + decrypted);

Выходы:

Зашифровано: | зашифрованная строка зависит от сгенерированного ключа и iv |Расшифровано: Hello World!

Вы также можете использовать более эффективный способ и использовать byte [] вместо Strings, но это ваш выбор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...