web-dev-qa-db-fra.com

La longueur d'entrée doit être multiple de 16 lors du déchiffrement avec un chiffrement rembourré

J'ai un serveur et un programme de socket client, un serveur envoie un message crypté au client, c'est-à-dire le code côté serveur:

cipher2 = Cipher.getInstance("AES"); 
secretKeySpec = new SecretKeySpec(decryptedText, "AES");
cipher2.init(Cipher.ENCRYPT_MODE, secretKeySpec);
feedback = "Your answer is wrong".getBytes();
cipher2.doFinal(feedback);
dos.writeInt(feedback.length);
dos.write(feedback);

le code côté client:

int result_len = 0;
result_len = din.readInt();            
byte[] result_Bytes = new byte[result_len];
din.readFully(result_Bytes);
cipher2 = Cipher.getInstance("AES");
cipher2.init(Cipher.DECRYPT_MODE, aesKey);             
byte[] encrypt = cipher2.doFinal(result_Bytes);

Lancer d'exception sur byte[] encrypt = cipher2.doFinal(result_Bytes);

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.Sun.crypto.provider.CipherCore.doFinal(CipherCore.Java:750)
    at com.Sun.crypto.provider.CipherCore.doFinal(CipherCore.Java:676)
    at com.Sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.Java:313)
    at javax.crypto.Cipher.doFinal(Cipher.Java:2086)

quel est le problème?

11
hkguile

Eu un problème similaire. Mais il est important de comprendre la cause profonde et cela peut varier pour différents cas d'utilisation.

Scénario 1
Vous essayez de déchiffrer une valeur qui n'a pas été encodée correctement en premier lieu.

byte[] encryptedBytes = Base64.decodeBase64(encryptedBase64String);

Si la chaîne est mal configurée pour une raison quelconque ou n'a pas été encodée correctement, vous verrez l'erreur "La longueur d'entrée doit être multiple de 16 lors du déchiffrement avec un chiffrement rembourré"

scénario 2
Maintenant, si par hasard vous utilisez cette chaîne encodée dans l'URL (en essayant de passer la valeur base64Encoded dans l'URL, cela échouera. Vous devriez faire URLEncoding puis passer le jeton, cela fonctionnera.

Scénario
Lors de l'intégration avec l'un des fournisseurs, nous avons constaté que nous devions effectuer le chiffrement de Base64 à l'aide d'URLEncoder, mais nous n'avons pas besoin de le décoder, car il a été effectué en interne par le fournisseur.

8
vsingh

Je sais que ce message est ancien et remonte à longtemps - mais j'ai également eu un problème avec exactement la même erreur:

le problème que j'ai eu était lié au fait que le texte chiffré a été converti en chaîne et en byte[] lorsque vous essayez de le DÉCRYPTER.

    private Key getAesKey() throws Exception {
    return new SecretKeySpec(Arrays.copyOf(key.getBytes("UTF-8"), 16), "AES");
}

private Cipher getMutual() throws Exception {
    Cipher cipher = Cipher.getInstance("AES");
    return cipher;// cipher.doFinal(pass.getBytes());
}

public byte[] getEncryptedPass(String pass) throws Exception {
    Cipher cipher = getMutual();
    cipher.init(Cipher.ENCRYPT_MODE, getAesKey());
    byte[] encrypted = cipher.doFinal(pass.getBytes("UTF-8"));
    return encrypted;

}

public String getDecryptedPass(byte[] encrypted) throws Exception {
    Cipher cipher = getMutual();
    cipher.init(Cipher.DECRYPT_MODE, getAesKey());
    String realPass = new String(cipher.doFinal(encrypted));
    return realPass;
}
3
2Big2BeSmall
2
slipset

C'est une très vieille question, mais ma réponse peut aider quelqu'un.

  • Dans la méthode de chiffrement, n'oubliez pas de coder votre chaîne en Base64
  • Dans la méthode de décryptage, n'oubliez pas de décoder votre chaîne en Base64

Ci-dessous est le code de travail

    import Java.util.Arrays;
    import Java.util.Base64;

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

    public class EncryptionDecryptionUtil {

    public static String encrypt(final String secret, final String data) {


        byte[] decodedKey = Base64.getDecoder().decode(secret);

        try {
            Cipher cipher = Cipher.getInstance("AES");
            // rebuild key using SecretKeySpec
            SecretKey originalKey = new SecretKeySpec(Arrays.copyOf(decodedKey, 16), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, originalKey);
            byte[] cipherText = cipher.doFinal(data.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(cipherText);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Error occured while encrypting data", e);
        }

    }

    public static String decrypt(final String secret,
            final String encryptedString) {


        byte[] decodedKey = Base64.getDecoder().decode(secret);

        try {
            Cipher cipher = Cipher.getInstance("AES");
            // rebuild key using SecretKeySpec
            SecretKey originalKey = new SecretKeySpec(Arrays.copyOf(decodedKey, 16), "AES");
            cipher.init(Cipher.DECRYPT_MODE, originalKey);
            byte[] cipherText = cipher.doFinal(Base64.getDecoder().decode(encryptedString));
            return new String(cipherText);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Error occured while decrypting data", e);
        }
    }


    public static void main(String[] args) {

        String data = "This is not easy as you think";
        String key = "---------------------------------";
        String encrypted = encrypt(key, data);
        System.out.println(encrypted);
        System.out.println(decrypt(key, encrypted));
      }
  }

Pour générer une clé, vous pouvez utiliser la classe ci-dessous

    import Java.security.NoSuchAlgorithmException;
import Java.security.SecureRandom;
import Java.util.Base64;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class SecretKeyGenerator {

    public static void main(String[] args) throws NoSuchAlgorithmException {

        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");

        SecureRandom secureRandom = new SecureRandom();
        int keyBitSize = 256;
        keyGenerator.init(keyBitSize, secureRandom);

        SecretKey secretKey = keyGenerator.generateKey();

 System.out.println(Base64.getEncoder().encodeToString(secretKey.getEncoded()));
    }

}
1
Aniket Kulkarni