2009-05-15 20 views
7

मैं जावा में एक फ़ाइल को डिक्रिप्ट करने का प्रयास कर रहा हूं जिसे रिजेंडेल/सीबीसी/पीकेसीएस 7 का उपयोग करके सी # में एन्क्रिप्ट किया गया था। मैं निम्न अपवाद बार आ रही है:BadPaddingException: पैड ब्लॉक दूषित

javax.crypto.BadPaddingException: पैड ब्लॉक भ्रष्ट
org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal (अज्ञात स्रोत)
javax.crypto.Cipher.doFinal पर पर (DashoA13 * ..)
AESFileDecrypter.decrypt (AESFileDecrypter.java:57) पर

जब doFinal(inpbytes) विधि पहले बाइट [] के लिए वेब सर्वर द्वारा कहा जाता है। मुझे लगता है कि यह कुंजी या चतुर्थ के साथ एक समस्या है। मेरे पास परीक्षण के लिए मेरे फाइल सिस्टम पर एन्क्रिप्टेड फाइलें हैं I क्या कोई ऐसा कुछ है जो नीचे दिए गए मेरे कोड के साथ कोई भी ग़लत रूप से गलत देख सकता है?

*** keyStr बेस 64 इनकोडिंग

public AESFileDecrypter(String keyStr){ 
    try { 
      Security.addProvider(new BouncyCastleProvider()); 
      convertIvParameter(); 
      key = new sun.misc.BASE64Decoder().decodeBuffer(keyStr); 

      //use the passed in Base64 decoded key to create a key object 
      decryptKey = new SecretKeySpec(key, "AES"); 

      //specify the encryption algorithm 
      decryptCipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); 

      //make a parameter object for the initialization vector(IV)    
      IvParameterSpec ivs = new IvParameterSpec(_defaultIv); 

      //initialize the decrypter to the correct mode, key used and IV 
      decryptCipher.init(Cipher.DECRYPT_MODE, decryptKey, ivs);  
     } 
    catch (Exception e) { 
      e.printStackTrace(); 
    } 
} 

public void convertIvParameter() { 

    int[] iv = new int[] {11, 190, 165, 33, 68, 88, 11, 200, 245, 35, 68, 23, 60, 24, 223, 67}; 

    _defaultIv = new byte[16]; 

    for(int x = 0; x < _defaultIv.length; x++) { 
     _defaultIv[x] = (byte)iv[x]; 
    } 
} 

public void decryptUpdate(byte[] inpBytes) throws Exception { 
    //decrypt the byte passed in from the web server 
    decryptCipher.update(inpBytes); 
} 

public byte[] decryptFinal() throws Exception { 
    //decrypt the byte passed in from the web server 
    return decryptCipher.doFinal(); 
} 

//sends bytes to the client for diaply 
private void sendBytes(FileInputStream fis, OutputStream os)throws Exception { 
    //set the buffer size to send 4k segments of data 
aesFileDecrypter = new AESFileDecrypter(<Insert Key string here>); 

    byte[] buffer = new byte[4096]; 
    int bytes = 0, totalBytes = fis.available(); 

    //while there is still data to be sent keep looping and write the data 
    //to the output stream as the buffer is filled 
    try { 
     while ((bytes = fis.read(buffer)) != -1) { 
      aesFileDecrypter.decryptUpdate(buffer); 
      //os.write(buffer, 0, bytes); 
     } 

     os.write(aesFileDecrypter.decryptFinal(), 0, totalBytes); 
    } 
    catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

उत्तर

1

जहां तक ​​मैं जानता हूँ कि एईएस क्रिप्ट पर आधारित है, लेकिन विनिर्देश बिल्कुल वैसा ही नहीं है। मैं सी # में साइफर और जावा में उपयोग किए जाने वाले आकारों के लिए उपयोग की जाने वाली कुंजी और ब्लॉक आकार की जांच करने का सुझाव दूंगा। (.Net differences between Rijndael and AES)।

+1

उत्तर के लिए धन्यवाद। एईएस 256-बिट के लिए है, और सी # में सिफर डेटा के 4k भाग का उपयोग कर रहा है। कतर में मैं हर बार उसी आकार का उपयोग कर रहा हूं जिसे मैं कॉल करता हूं() –

6

सबसे पहले, नीचे दी गई टिप्पणियों से स्पष्ट होने के लिए, आपको प्रत्येक ब्लॉक पर doFinal() को कॉल नहीं करना चाहिए, क्योंकि DoFinal() अंत में किसी भी पैडिंग की अपेक्षा करता है, जो स्पष्ट रूप से मध्यवर्ती ब्लॉक में नहीं होगा। इंटरमीडिएट डेटा पर या तो (ए) कॉल अपडेट(), फिर अंत में doFinal(), या (बी) बस अपने सभी डेटा को एक बफर या बाइट सरणी में व्यवस्थित करने की व्यवस्था करें, और पूरे जॉब लॉट पर एक बार DoFinal() को कॉल करें।

यह आपके द्वारा पोस्ट किए गए कोड से स्पष्ट नहीं है कि वास्तव में आप क्या कर रहे हैं, लेकिन इसका उल्लेख केवल मामले में किया जाना चाहिए।

उसमें असफल होने पर तो के रूप में एक पहला कदम डिबगिंग के लिए, मेरा सुझाव था इन दोनों में से जो भी आप के लिए आसान है:

  • कोई पैडिंग के साथ ईसीबी मोड में डिक्रिप्ट और आप क्या मिलता देखकर। डेटा के पहले ब्लॉक को देखें जो इसे वापस लाता है। यदि आप इसे अपने आईवी बाइट्स के साथ एक्सओआर कर सकते हैं और अपेक्षित डिक्रिप्ट डेटा प्राप्त कर सकते हैं, तो आप जानते हैं कि आपकी कुंजी ठीक है।
  • डीकोडिंग और जांच के बाद बेस 64 एन्कोडिंग और जावा के बाद सी # से वास्तविक कुंजी बाइट्स को डंप करना वे समान हैं।

जैसा कि मुझे याद है, सी # ने हस्ताक्षरित बाइट्स (जबकि जावा हस्ताक्षर किए हैं) हैं, इसलिए कुछ ऐसे स्थान हैं जहां बाइट हस्ताक्षर के साथ चीजों को गलत तरीके से गलत करने के लिए जगह है।

+0

एक और टिप्पणी जो मुझे बताया गया था कि एक प्रमुख मुद्दा हर ब्लॉक पर "डोफिनल()" को कॉल कर रहा है (इसे केवल एक बार किया जाना चाहिए)। यह सुझाव दिया गया था कि मैं या तो अद्यतन करने के लिए doFinal बदलता हूं, और अंत में केवल अंतिम प्रदर्शन करता हूं। या सिफर धाराओं का उपयोग करें –

+0

आह हाँ, क्षमा करें, मैंने स्पष्ट रूप से आपके कोड को पर्याप्त रूप से पर्याप्त नहीं पढ़ा है। यदि आप प्रत्येक ब्लॉक के लिए doFinal() को कॉल कर रहे हैं, तो यह गलत है। –

+0

धन्यवाद निएल ... मैंने अद्यतन कोड में जोड़ा। मैं अब SendBytes विधि (जो वेब सर्वर में रहता है) से अद्यतन विधि को कॉल करने का प्रयास कर रहा था। और जब मैं इनपुट स्ट्रीम के माध्यम से लूप करता हूं, तो doFinal() विधि को कॉल करें। अभी भी doFinal() विधि पर एक ही अपवाद प्राप्त करें, इसलिए यह प्रत्येक बाइट [] पर अद्यतन() कर फ़ाइल स्ट्रीम के माध्यम से सफलतापूर्वक लूप करता है। कोई सुझाव? –

1

डूफिनल() ऊपर दिए गए कोड को पूर्ववत कर रहा था, और मैं अपडेट/डूफिनल दृष्टिकोण के बजाय सिफर स्ट्रीम का उपयोग कर समाप्त हुआ। इस तरह से मैं CipherInputStream के पैरामीटर के रूप में FileInputStream और मेरे सिफर का उपयोग कर सकता हूं, और फिर आउटपुटस्ट्रीम के माध्यम से आउटपुट को वेब ब्राउज़र पर पास कर सकता हूं। अद्यतन को तोड़ना और अपनी खुद की विधि कॉल में बाहर निकलना, कार्य को और अधिक कठिन बना दिया गया और दोनों विधियों को डिक्रिप्टर वर्ग से हटा दिया गया था (डेटा के हिस्सों में पढ़ने और इसे ब्राउज़र में आउटपुट करने के लिए एक ही समय लूप छोड़कर)। इस मामले में बाउंसी कैसल प्रदाता की भी आवश्यकता नहीं थी और पीकेसीएस 5 पैडिंग पर्याप्त था, जो सनजेसीई द्वारा दिया गया था।

3

मुझे इससे पहले इस समस्या का सामना करना पड़ा है।

जब मैं इस तरह एन्क्रिप्शन और डिक्रिप्शन करने के लिए कुछ कोड लिखा है:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sec, "AES"),new IvParameterSpec(new byte[cipher.getBlockSize()])); 
    byte[] encode = cipher.doFinal(data); 

    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sec, "AES"), new IvParameterSpec(new byte[cipher.getBlockSize()])); 
    byte[] decode = cipher.doFinal(encode); 

मैं भूल गया पहला IvParameterSpec(new byte[cipher.getBlockSize()]) जब डेटा को एन्क्रिप्ट, तो मैं एक अपवाद "पैड ब्लॉक भ्रष्ट" मिल गया है, तो हो सकता है आप आप की जाँच करनी चाहिए एन्क्रिप्शन कोड।

संबंधित मुद्दे