web-dev-qa-db-ja.com

不正なブロックサイズの例外パディングされた暗号で復号化する場合、入力長は16の倍数である必要があります

私のアプリケーションでは、secretKeyを使用してデータを暗号化および復号化しています。そのために私はAESアルゴリズムを使用しています。しかし、復号化で例外が発生します。秘密鍵を使用してすでに暗号化されている3つの値のうちの1つです。

例外は:

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher.

以下は私のコードです:

関数からencyrpt値へ

public static String symmetricEncrypt(String text, String secretKey) {
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] raw;
    String encryptedString;
    SecretKeySpec skeySpec;
    BASE64Encoder bASE64Encoder = new BASE64Encoder();
    byte[] encryptText = text.getBytes();
    Cipher cipher;
    try {
        raw = decoder.decodeBuffer(secretKey);
        skeySpec = new SecretKeySpec(raw, "AES");
        cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        encryptedString = bASE64Encoder.encode(cipher.doFinal(encryptText));
    } 
    catch (Exception e) {
        e.printStackTrace();
        return "Error";
    }
    return encryptedString;
}

値を復号化する関数

public static String symmetricDecrypt(String text, String secretKey) {
    BASE64Decoder decoder = new BASE64Decoder();
    BASE64Decoder base64Decoder = new BASE64Decoder();
    Cipher cipher;
    String encryptedString;
    byte[] encryptText = null;
    byte[] raw;
    SecretKeySpec skeySpec;
    try {
        raw = decoder.decodeBuffer(secretKey);
        skeySpec = new SecretKeySpec(raw, "AES");
        encryptText = base64Decoder.decodeBuffer(text);
        cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        encryptedString = new String(cipher.doFinal(encryptText));
    } catch (Exception e) {
        e.printStackTrace();
        return "Error";
    }
    return encryptedString;
}

以下は私が暗号化および復号化している値です

String secretKey = "XMzDdG4D03CKm2IxIWQw7g==";
String value1= "ABCD";
String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA==";
String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4=";
String value4= "20000";

/**  Ecnryption and decryption of value1 **/
String encryptedValue1= symmetricEncrypt(value1, secretKey);
String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey);

/**  Decryption of  enctypedValue1 **/
String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey);
System.out.println(decryptedValue2);

/**  Decryption of  enctypedValue2 (Not decrypted)**/
String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey);
System.out.println(decryptedValue3);

/**  Ecnryption and decryption of value4 **/
String encryptedValue4= symmetricEncrypt(value4, secretKey);
String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey);

テスト機能では、以下の3つのテストケースを記述しました。

  1. 秘密鍵を使用して暗号化および復号化される新しい値(value1)。
  2. 同じ秘密鍵を使用して復号化されている2つの暗号化された値(enctypedValue1、enctypedValue2)の例。同じ秘密鍵を使用して復号化するときに問題が発生したencryptedValue2。
  3. 秘密鍵を使用して暗号化および復号化される新しい値(value4)。

EncryptionValue2を復号化すると、次の例外が発生します。

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher

以下は私がこれまでに導き出したものです。

  1. 問題のある値は、デコード中に問題があるようです。復号化できない81の長さの配列を返しますか?

  2. この問題が発生した場合は、すべての値で発生しているはずです。

  3. これは値固有の問題ですか、それともパディングに関連する問題ですか、それとも異なるブラウザ、異なるOSで異なる動作をする可能性がありますか?

7
JankiPanwala

私は問題なくコードを実行することができました。ただし、エンコード/デコードにはApacheのBase64を使用しました...おそらくBase64にバグがあります。自分で書いた場合、見逃してしまう可能性が高いです。実際の本番コードでは、Apacheなどの十分にテストされたライブラリを使用してください。

Base64で使用したライブラリはここにあります: http://commons.Apache.org/proper/commons-codec/download_codec.cgi

完全に機能するコードは次のとおりです。

    package security.symmatric;

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

    import org.Apache.commons.codec.binary.Base64;

    public class AES {
        public static String symmetricEncrypt(String text, String secretKey) {
            byte[] raw;
            String encryptedString;
            SecretKeySpec skeySpec;
            byte[] encryptText = text.getBytes();
            Cipher cipher;
            try {
                raw = Base64.decodeBase64(secretKey);
                skeySpec = new SecretKeySpec(raw, "AES");
                cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText));
            } 
            catch (Exception e) {
                e.printStackTrace();
                return "Error";
            }
            return encryptedString;
        }

        public static String symmetricDecrypt(String text, String secretKey) {
            Cipher cipher;
            String encryptedString;
            byte[] encryptText = null;
            byte[] raw;
            SecretKeySpec skeySpec;
            try {
                raw = Base64.decodeBase64(secretKey);
                skeySpec = new SecretKeySpec(raw, "AES");
                encryptText = Base64.decodeBase64(text);
                cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);
                encryptedString = new String(cipher.doFinal(encryptText));
            } catch (Exception e) {
                e.printStackTrace();
                return "Error";
            }
            return encryptedString;
        }

        public static void main(String[] args) {
            String secretKey = "XMzDdG4D03CKm2IxIWQw7g==";
            String value1= "ABCD";
            String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA==";
            String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4=";
            String value4= "20000";

            /**  Ecnryption and decryption of value1 **/
            String encryptedValue1= symmetricEncrypt(value1, secretKey);
            String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey);
            System.out.println(decryptedValue1);

            /**  Decryption of  enctypedValue1 **/
            String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey);
            System.out.println(decryptedValue2);

            /**  Decryption of  enctypedValue2 **/
            String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey);
            System.out.println(decryptedValue3);

            /**  Ecnryption and decryption of value4 **/
            String encryptedValue4= symmetricEncrypt(value4, secretKey);
            String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey);
            System.out.println(decryptedValue4);
        }
    }
11
Multithreader