web-dev-qa-db-ja.com

javax.crypto.BadPaddingException:指定された最終ブロックに適切にパディングされない

サーバー上のフレームをdecryptする必要があります。暗号化されたフレームは、ソケット上のGPRSを介してクライアントデバイスから送信されます。暗号化TripleDesを使用して、指定されたキーを使用して実行されます。サーバー側のアルゴリズムとキー。フレームは、16進数とASCII文字列の組み合わせです。ここでの問題は次のとおりです。バイト配列にゼロを埋め込むと、次の例外が発生します。

javax.crypto.BadPaddingException: Given final block not properly padded

以下は私のコードです:

byte[] key = new byte[]{31, 30, 31, 36, 32, 11, 11, 11, 22, 26,
               30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30};
myKeySpec = new DESedeKeySpec(key);
mySecretKeyFactory = SecretKeyFactory.getInstance("TripleDES");
de = mySecretKeyFactory.generateSecret(myKeySpec);

    Cipher c = Cipher.getInstance("TripleDES");
c.init(Cipher.DECRYPT_MODE, key);

    int l = completeHexStr.length();

    if (l%8==1){
        completeHexStr = completeHexStr + "0000000";
    }else if (l%8==7){
        completeHexStr = completeHexStr + "0";
    }
byte decordedValue[] =completeHexString.getBytes();
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
System.out.println("decryptedValue= " + decryptedValue);

コード内で使用している関数は次のとおりです。

    public String stringToHex(String base) {
            StringBuffer buffer = new StringBuffer();
            int intValue = 0;
            for (int x = 0; x < base.length(); x++) {
                intValue = base.charAt(x);
                String hex = Integer.toHexString(intValue);
                if (hex.length() == 1) {
                    buffer.append("0" + hex + "");
                } else {
                    buffer.append(hex + "");
                }
            }
            return buffer.toString();
        }
    public String byteToAscii(byte[] b, int length) {
            String returnString = "";
            for (int i = 0; i < length; i++) {
                returnString += (char) (b[i] & 0xff);
            }
            return returnString;
        }

これは、クライアント側での暗号化に使用されるcのコードです。

#include <svc_sec.h>
const unsigned char fixed_key[] = { 0x31, 0x30, 0x31, 0x36, 0x32, 0x11, 0x11, 0x11, 0x22, 0x26, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
int Comm_Encrypt_Data(unsigned char *Test_Input_Data, int Len_Input_Data)
{
int Count_Input_Data, Counter_Input_Data;
unsigned long Timer_1;
unsigned char Init_Vector[8];
int Counter_Init_Vector, Temp_Byte_Count;
unsigned char *Temp_Dst_Ptr, *Temp_Src_Ptr;
unsigned char Temp_Input_Frame[9], Temp_Output_Frame[9];
unsigned char Test_Output_Data[500];
unsigned char Test_Key_Arr[9];

memset(&Init_Vector[0], '\0', sizeof(Init_Vector));
memset(Test_Key_Arr, '0', sizeof(Test_Key_Arr));
memcpy(Test_Key_Arr, &fixed_key[0], 8);
Test_Key_Arr[sizeof(Test_Key_Arr)-1] = '\0';

Display_Data("KEY: ", Test_Key_Arr, sizeof(Test_Key_Arr)-1);

memset(Test_Output_Data, '\0', sizeof(Test_Output_Data));
memcpy(Test_Output_Data, Test_Input_Data, 48);

Count_Input_Data = Len_Input_Data -48 -3; //minus Data before payload, 3 bytes of '|' and CRC
Counter_Input_Data = 0;
while(Counter_Input_Data < Count_Input_Data)
{
Temp_Byte_Count = Count_Input_Data- Counter_Input_Data;
if(Temp_Byte_Count > 8)
Temp_Byte_Count = 8;

memcpy(Temp_Input_Frame, &Test_Input_Data[48+Counter_Input_Data], Temp_Byte_Count);
//succeeding bytes to be 0
if(Temp_Byte_Count < 8)
{
memset(&Temp_Input_Frame[Temp_Byte_Count], '0', (8-Temp_Byte_Count));

}

Display_Data("InPut Data Before Init",Temp_Input_Frame, Temp_Byte_Count);

//============Initialize the data
Temp_Dst_Ptr = (unsigned char *)Temp_Input_Frame;
Temp_Src_Ptr = (unsigned char *)&Init_Vector[0];
for(Counter_Init_Vector =0;Counter_Init_Vector < 8; Counter_Init_Vector++)
*Temp_Dst_Ptr++ ^= *Temp_Src_Ptr++;
//============Initializing data ends

DES(DESE, (unsigned char *)&Test_Key_Arr[0],
(unsigned char *)&Temp_Input_Frame[0], (unsigned char *)&Temp_Output_Frame[0]);
//DES(TDES3KE, (unsigned char *)&Test_Key_Arr[0],
// (unsigned char *)&Temp_Input_Frame[0], (unsigned char *)&Temp_Output_Frame[0]);
Display_Data("AFTER DES::::", Temp_Output_Frame, Temp_Byte_Count);

memcpy(&Test_Output_Data[48+Counter_Input_Data], Temp_Output_Frame, Temp_Byte_Count);
Counter_Input_Data += Temp_Byte_Count;

if(Counter_Input_Data < Count_Input_Data)
{
memcpy(Init_Vector, Temp_Output_Frame, 8);

}
}

{
memset(Test_Input_Data, '\0', Len_Input_Data);
memcpy(&Test_Input_Data[0], &Test_Output_Data[48], Counter_Input_Data); //1 Separator + 2 CRCs
}
Display_Data("Final Output Frame", Test_Input_Data, Counter_Input_Data);
return Counter_Input_Data;
}

Java Cryptographyの新人です。方法を教えてください?フレームを復号化するために適切に機能するコードを誰でも投稿できます。よろしくお願いします。

14
java2485

コードの主な問題は、デフォルトのPKCS5Paddingを使用して復号化することです。 "TripleDES"は内部的に"TripleDES/ECB/PKCS5Padding"になります。これは、Sun JCEプロバイダーに実装されているとおりです。他のほとんどのプロバイダーはこのデフォルトをコピーします。

ゼロパディングを期待しているようです。つまり、代わりに"DESede/ECB/NoPadding"を使用する必要があります。その後、外部関数を使用してプレーンテキストのサイズを計算できます(注意しない場合、ゼロパディングを削除すると、最後にゼロ値のプレーンテキストが削除される場合があります)。

その他の問題:

  • 復号化する前にデータを埋め込もうとします(npadデータ復号化する必要があります)
  • エンコーディングと文字エンコーディングの問題、たとえば"0"の文字値でパディングしようとするなど、おそらく間違っている

実際に使用されているモードがわからないため、"ECB"と示しました。あなたが見つけることができるなら、あなたは正しいモードとパディングアルゴリズムであなたの質問を修正することができます。 ECBが機能しない場合は、CBCモードも試してみてください。

ECBモードは、非常に特殊な状況を除いて安全に使用できないことに注意してください。ランダム化されたIVでCBCを使用することは最小限の要件です。

10
Maarten Bodewes

(3)DESは、8バイトのブロックを暗号化/復号化します。すべてのテキストが正確に8バイトであるとは限らないため、最後のブロックにはプレーンテキストのオリジナルではないバイトが含まれている必要があります。

トリックは、どれがプレーンテキストの最後の文字であるかを見つけることです。プレーンテキストの長さが事前にわかっている場合もあります。その場合、埋め込み文字は実際には何でもかまいません。

プレーンテキストの長さがわからない場合は、確定的なパディングアルゴリズムを使用する必要があります。 PKCS5Padding。 PKCS5Paddingは、プレーンテキストがN *ブロックサイズのバイトサイズであっても、常にパディングを実行します。これの理由は単純です。それ以外の場合、最後のバイトがプレーンテキストかパディングかがわかりません。

後で動作するコードを試してみるつもりです...テストする必要があります。それまでの間、パディングアルゴリズムを使用してみてください。

6
Calin Andrei

受信した暗号文で使用されているパディングがドキュメントに記載されていない場合は、「NoPadding」で復号化します。これにより、最後のブロックであらゆる種類のパディングが受け入れられます。次に、最後のブロックのヘクスを見てください。これにより、暗号化側で使用されているパディングがわかります。正しいタイプのパディングを期待するようにコードを修正してください。さまざまなタイプのパディングがカバーされています here

4
rossum

stringToHexメソッドを確認したところ、正しくないようです。代わりにこれを試してください:

        StringBuilder rep = new StringBuilder();
        for (byte b : base.getBytes) {
            rep.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
        }
        System.out.println(rep);

また、私はこれを見つけました TripleDes with Padding の例。この例で使用しているアルゴリズムと変換を試すことができます。

3
alain.janinm