javax.krypto.BadPaddingException

Pracuję nad algorytmem AES i mam ten wyjątek, którego nie mogłem rozwiązać.

javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)

Wyjątek występuje w części deszyfrującej. Inicjalizuję klucz w innym miejscu niż algorytm deszyfrowania

KeyGenerator kgen = KeyGenerator.getInstance("AES");//key generation for AES
kgen.init(128); // 192 and 256 bits may not be available

Następnie przekazuję go z zaszyfrowanym tekstem, który odczytuję z pliku do następującej metody

 public String decrypt(String message, SecretKey skey) {

    byte[] raw = skey.getEncoded();
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    // Instantiate the cipher
    Cipher cipher;

    byte[] original = null;
    try {
        cipher = Cipher.getInstance("AES");

        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        System.out.println("Original string: "
                + message);
        original = cipher.doFinal(message.trim().getBytes());  //here where I got the exception
        String originalString = new String(original);
       }
 //catches

Edytuj oto metoda szyfrowania.

public String encrypt(String message, SecretKey skey) {
    byte[] raw = skey.getEncoded();
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

    // Instantiate the cipher

    Cipher cipher;
    byte[] encrypted = null;
    try {
        cipher = Cipher.getInstance("AES");

        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        encrypted = cipher.doFinal(message.getBytes());
        System.out.println("raw is " + encrypted);

    } catches
    return asHex(encrypted);
}

A oto metoda asHex

  public static String asHex(byte buf[]) {
    StringBuffer strbuf = new StringBuffer(buf.length * 2);
    int i;

    for (i = 0; i < buf.length; i++) {
        if (((int) buf[i] & 0xff) < 0x10) {
            strbuf.append("0");
        }

        strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
    }

    return strbuf.toString();
}

Tutaj czytam szyfr formularz tekstowy pliku

static public String readFile(String filePath) {
    StringBuilder file = new StringBuilder();
    String line = null;
    try {
        FileReader reader = new FileReader(filePath);
        BufferedReader br = new BufferedReader(reader);
        if (br != null) {
            line = br.readLine();
            while (line != null) {
                file.append(line);
                //      System.out.println("line is " + line);
                line = br.readLine();

            }
        }
        br.close();
        reader.close();
    } catch (IOException ex) {
        Logger.getLogger(FileManagement.class.getName()).log(Level.SEVERE, null, ex);
    }
    System.out.println("line is " + file.toString());
    return String.valueOf(file);

}
Czy ktoś może pomóc?
Author: Kyle Falconer, 2011-01-03

5 answers

Ok, problem polega na tym, że konwertujesz zaszyfrowane bajty na łańcuch szesnastkowy (za pomocą metody asHex), ale nie konwertujesz łańcucha szesnastkowego z powrotem do tablicy bajtów poprawnie do deszyfrowania. Nie możesz używać getBytes.

Możesz użyć następującej metody do konwersji ciągu szesnastkowego na tablicę bajtów:

public static byte[] fromHexString(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

A następnie zmień metodę deszyfrowania na używaną:

original = cipher.doFinal(fromHexString(message));
 13
Author: dogbane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:58:47

Miałem zły wyjątek Padding i nie byłem w stanie znaleźć w Internecie rozwiązanie mojego problemu. Ponieważ znalazłem go po ciężkich godzinach pracy, daję go tutaj.

Mój problem polegał na tym, że czytałem plik na dysku twardym i szyfrowałem go przez bufor, zawsze wywołując metodę doFinal() zamiast update (). Więc podczas odszyfrowywania, miałem błędy wypełnienia

    input = new FileInputStream(file);
    output = new FileOutputStream(newFile);

    Cipher cipher = Cipher.getInstance("DES");
    cipher.init(Cipher.ENCRYPT_MODE, mySecretKey);

    byte[] buf = new byte[1024];

    count = input.read(buf);
    while (count >= 0) {
        output.write(cipher.update(buf, 0, count)); // HERE I WAS DOING doFinal() method
        count = input.read(buf);
    }
    output.write(cipher.doFinal()); // AND I DID NOT HAD THIS LINE BEFORE
    output.flush();

I podczas odszyfrowywania tą samą metodą, ale za pomocą init szyfrowego z DECRYPT_MODE

    input = new FileInputStream(file);
    output = new FileOutputStream(newFile);

    Cipher cipher = Cipher.getInstance("DES");
    cipher.init(Cipher.DECRYPT_MODE, mySecretKey);

    byte[] buf = new byte[1024];

    count = input.read(buf);

    while (count >= 0) {
        output.write(cipher.update(buf, 0, count)); // HERE I WAS DOING doFinal() method

        //AND HERE WAS THE BadPaddingExceotion -- the first pass in the while structure

        count = input.read(buf);
    }
    output.write(cipher.doFinal()); // AND I DID NOT HAD THIS LINE BEFORE
    output.flush();

Z kodem napisanym, nie mam już żadnego BadPaddingException.

Mogę sprecyzować, że ten wyjątek pojawia się tylko wtedy, gdy oryginalna długość pliku (uzyskana przez plik.długość ()) jest większa niż bufor. W przeciwnym razie nie musimy przechodzić kilka razy w strukturze while I możemy zaszyfrować w jednym przejściu wywołaniem doFinal (). To uzasadnia losowy charakter wyjątku po rozmiarze pliku, który próbujesz zaszyfrować.

Mam nadzieję, że miałeś dobra lektura!

 3
Author: Mav3656,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-04 08:29:44

Domyślam się, że wyrażenie message.trim().getBytes() nie zwraca tych samych bajtów, które są generowane podczas szyfrowania wiadomości. W szczególności metoda trim() może usunąć bajty, które zostały dodane jako wypełnienie w zaszyfrowanej wiadomości.

Sprawdź, czy zarówno zwracana tablica metody doFinal() podczas szyfrowania, jak i zwracana tablica message.trim().getBytes():

  1. otrzymano tę samą liczbę bajtów (długość tablicy)
  2. otrzymałem te same bajty w tablicy
 1
Author: Progman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-02 23:12:38
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair rsaKeyPair = kpg.genKeyPair();
byte[] txt = "This is a secret message.".getBytes();
System.out.println("Original clear message: " + new String(txt));

// encrypt
Cipher cipher;
try
{
    cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, rsaKeyPair.getPublic());
    txt = cipher.doFinal(txt);
}
catch (Throwable e)
{
    e.printStackTrace();
    return;
}
System.out.println("Encrypted message: " + new String(txt));

// decrypt
try
{
    cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.DECRYPT_MODE, rsaKeyPair.getPrivate());
    txt = cipher.doFinal(txt);
}
catch (Throwable e)
{
    e.printStackTrace();
    return;
}
System.out.println("Decrypted message: " + new String(txt));
 0
Author: Jaya shree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-26 12:45:25

Oto rozwiązanie, które udało mi się połączyć za pomocą klucza jks z szyfrowaniem RSA

import javax.crypto.Cipher;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.cert.Certificate;

public class Main {

    public static void main(String[] args) {

        byte[] txt = "This is a secret message for your own eyes only".getBytes();
        byte[] encText;
        try{

            // Load the keystore
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            char[] password = "keystorePassword".toCharArray();
            java.io.FileInputStream fis = new java.io.FileInputStream("/path/to/keystore/myKeyStore.jks");
            ks.load(fis, password);
            fis.close();

            Key rsakey = ks.getKey("mykeyalias", password);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

            // Encrypt
            Certificate cert = ks.getCertificate("mykeyalias");
            try
            {
                cipher.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
                encText = cipher.doFinal(txt);
                System.out.println(encText.toString());
            }
            catch (Throwable e)
            {
                e.printStackTrace();
                return;
            }

            // Decrypt
            cipher.init(Cipher.DECRYPT_MODE, rsakey);
            String decrypted = new String(cipher.doFinal(encText));
            System.out.println(decrypted);


        } catch (Exception e) {
            System.out.println("error" + e);
        }
}
 -1
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-27 19:45:23