3

私はほとんど問題ありません。テキストを暗号化してからこのテキストを復号化しようとすると、エラーが発生します。

javax.crypto.IllegalBlockSizeException:パディングされた暗号で復号化する場合、入力長は16の倍数である必要があります

これが私のコードです:

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 *
 * @author Grzesiek
 */
public class SymmethricCipherCBC {


    /* Klucz: */
    private byte[] keyBytes = new byte[] {
            0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
            0x00,0x01,0x02,0x03,0x04,0x05
        };

   /* Wektor inicjalizacyjny: */
   private byte[] ivBytes = new byte[] {
            0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
            0x00,0x01,0x02,0x03,0x04,0x05
        };

   private Cipher cipher;
   private SecretKeySpec keySpec;
   private IvParameterSpec ivSpec;



   public SymmethricCipherCBC() throws NoSuchAlgorithmException, NoSuchPaddingException{
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Utworzenie obiektu dla operacji szyfrowania/deszyfrowania algorytmem AES w trybie CBC.
        keySpec = new SecretKeySpec(keyBytes, "AES"); // Utworzenie obiektu klucza dla algorytmu AES z tablicy bajtow
        ivSpec = new IvParameterSpec(ivBytes); // // Utworzenie obiektu dla wektora inicjalizacyjnego
   }


   public String encryptText(String plainText) throws NoSuchAlgorithmException, 
                                                    InvalidKeyException, 
                                                    NoSuchPaddingException, 
                                                    InvalidAlgorithmParameterException, 
                                                    ShortBufferException, 
                                                    IllegalBlockSizeException, 
                                                    BadPaddingException,
                                                    UnsupportedEncodingException{

       int cipherTextLength;
       byte[] cipherText; // Bufor dla szyfrogramu

       byte[] plainTextBytes = plainText.getBytes(); // Reprezentacja tekstu jawnego w bajtach

       cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); //Inicjalizacja obiektu dla operacji szyfrowania z kluczem okreslonym przez keySpec:   

       cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)]; //Utworzenie buforu dla szyfrogramu

       cipherTextLength = cipher.update(plainTextBytes, 0, plainTextBytes.length, cipherText, 0); // Szyfrowanie tekstu jawnego

       cipherTextLength += cipher.doFinal(cipherText, cipherTextLength); //Zakonczenie szyfrowania

       return new BigInteger(1, cipherText).toString(16); // zapisanie 16 

   }


   public String decryptText(String ciptherTextString) throws InvalidKeyException, InvalidAlgorithmParameterException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{

       byte[] cipherTextBytes = ciptherTextString.getBytes();

       cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);  //Inicjalizacja obiektu cipher dla odszyfrowywania z kluczem okreslonym przez keySpec

       byte[] plainTextBytes = new byte[cipher.getOutputSize(cipherTextBytes.length)];  // Utworzenie wyzerowanej tablicy

       int plainTextLength = cipher.update(cipherTextBytes, 0, cipherTextBytes.length, plainTextBytes, 0);
       plainTextLength += cipher.doFinal(plainTextBytes, plainTextLength);

       return new String(plainTextBytes); //Odtworzona wiadomosc
   }
}

私が何をすべきかアイデアはありますか?

4

2 に答える 2

4

あなたはそれを必要以上に難しくしていて、あなたはそれをするときにあなたの暗号文を暗号化しています

cipher.doFinal(cipherText, cipherTextLength);

私はそれをそのまま書き直します:

public String encryptText(String plainText) throws ... {
    byte[] plainTextBytes = plainText.getBytes("UTF8");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); 
    byte[] encrypted = cipher.doFinal(plainTextBytes);
    return toHex(encrypted);
}

public String decryptText(String cipherTextString) throws ... {
    byte[] cipherTextBytes = fromHex(cipherTextString);
    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
    byte[] plainTextBytes = cipher.doFinal(cipherTextBytes);
    return new String(plainTextBytes, "UTF8");
}
于 2013-01-03T23:04:43.500 に答える
0

私の知る限り、暗号化アルゴリズムから出力されたバイト配列を取得し、BigIntegerを使用して16進文字列に変換しています。次に、復号化アルゴリズムは16進文字列を取得し、それを16進文字列のASCII文字のバイト表現に変換します。.toString()

これはあなたのコードが間違っているところです(他の場所の中でも)。たとえば、16進文字列出力「FFFF」をバイト配列[0xff, 0xff]に変換するのではなく、バイト配列に変換します[0x46,0x46,0x46,0x46](たとえば、大文字のFのASCIIバイト表現)。これは、変換のすべてのバイトが間違っているだけでなく、バ​​イト配列の長さが間違っていることを意味します(これにより、質問にリストした例外が発生します)。

代わりに、暗号化方式から戻り、復号化方式のパラメーターとしてbyte[]受け入れる必要があります。byte[]それができない場合は、Apache Commons CodecのHexクラスのようなものを使用して、バイト配列と16進文字列の間で確実に変換する必要があります。

于 2013-01-03T22:52:51.913 に答える