2010-12-30 13 views
5

मेरे पास निम्न कोड है।डिक्रिप्शन त्रुटि: पैड ब्लॉक दूषित

byte[] input = etInput.getText().toString().getBytes(); 
    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
     0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; 

    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); 

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); 

    // encryption pass 
    cipher.init(Cipher.ENCRYPT_MODE, key); 

    byte[] cipherText = new byte[cipher.getOutputSize(input.length)]; 
    int ctLength = cipher.update(input, 0, input.length, cipherText, 0); 
    ctLength += cipher.doFinal(cipherText, ctLength); 

    cipher.init(Cipher.DECRYPT_MODE, key); 
    byte[] plainText = new byte[cipher.getOutputSize(ctLength)]; 
    int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0); 

    String strLength = new String(cipherText,"US-ASCII"); 
    byte[] byteCiphterText = strLength.getBytes("US-ASCII"); 
    Log.e("Decrypt", Integer.toString(byteCiphterText.length)); 

    etOutput.setText(new String(cipherText,"US-ASCII")); 

    cipherText = etOutput.getText().toString().getBytes("US-ASCII"); 
    Log.e("Decrypt", Integer.toString(cipherText.length)); 

    ptLength += cipher.doFinal(plainText, ptLength); 
    Log.e("Decrypt", new String(plainText)); 
    Log.e("Decrypt", Integer.toString(ptLength)); 

यह पूरी तरह से काम करता है। लेकिन एक बार जब मैं इसे कक्षा में बदल देता हूं। यह हमेशा इस लाइन में त्रुटि मारा।

ptLength += cipher.doFinal(plainText, ptLength); 

Error:Pad block corrupted 

मैंने जांच की है और दोनों कोड बिल्कुल वही हैं। यहां तक ​​कि रूपांतरण स्ट्रिंग में बाइट से गुजरने वाला मान भी ऊपर दिए गए कोड से अलग नहीं है। कोई विचार कोड के साथ क्या गलत है?

public String Encrypt(String strPlainText) throws Exception, NoSuchProviderException, 
     NoSuchPaddingException { 
    byte[] input = strPlainText.getBytes(); 
    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 
      0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; 

    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); 

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); 

    // encryption pass 
    cipher.init(Cipher.ENCRYPT_MODE, key); 

    byte[] cipherText = new byte[cipher.getOutputSize(input.length)]; 
    int ctLength = cipher.update(input, 0, input.length, cipherText, 0); 
    ctLength += cipher.doFinal(cipherText, ctLength); 

    return new String(cipherText, "US-ASCII"); 
} 

public String Decrypt(String strCipherText) throws Exception, 
     NoSuchProviderException, NoSuchPaddingException { 
    byte[] cipherText = strCipherText.getBytes("US-ASCII"); 
    int ctLength = cipherText.length; 
    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 
      0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; 

    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); 

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); 

    // decryption pass 
    cipher.init(Cipher.DECRYPT_MODE, key); 
    byte[] plainText = new byte[cipher.getOutputSize(ctLength)]; 
    int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0); 
    ptLength += cipher.doFinal(plainText, ptLength); 

    return new String(plainText); 
} 
+0

जब तक आप पूरी तरह से आश्वस्त हो जाते हैं, या केवल पर काम कर रहे:

संपादित

शायद सबसे सुरक्षित लंबाई मुद्दे से निपटने के रास्ते हमेशा कार्यान्वयन स्ट्रीमिंग (IMHO) उपयोग करने के लिए है एक समय में एक ब्लॉक, आपको ईसीबी मोड का कभी भी उपयोग नहीं करना चाहिए। कभी। –

+0

इसके बजाय सीबीसी का उपयोग करें – Codefor

उत्तर

1

आपने पीकेसीएस 7 पैडिंग निर्दिष्ट किया है। क्या आपकी स्ट्रिंग ऑब्जेक्ट में संग्रहीत होने पर आपका पैडिंग संरक्षित है? क्या आपकी स्ट्रिंग साइबर द्वारा बाइट आउटपुट के साथ 1: 1 मैच ऑब्जेक्ट करती है? आम तौर पर, स्ट्रिंग बाइनरी डेटा, जैसे कि सिफर आउटपुट पास करने के लिए अनुचित है।

+0

क्षमा करें, अपने प्रश्न पर भ्रमित रहें, क्या आपकी स्ट्रिंग ऑब्जेक्ट में संग्रहीत होने पर आपका पैडिंग संरक्षित है? -> मैं कैसे जांच सकता हूं? क्या आपकी स्ट्रिंग साइबर द्वारा बाइट आउटपुट के साथ 1: 1 मैच ऑब्जेक्ट करती है? -> आपका मतलब है कि एन्क्रिप्ट के लिए दर्ज स्ट्रिंग बाइट्स आउटपुट के साथ मेल खाना चाहिए? आम तौर पर, स्ट्रिंग बाइनरी डेटा को पास करने के लिए अनुचित है, जैसे कि सिफर आउटपुट .-> ऐसा क्यों कहते हैं? एक बार जब मुझे सिफर टेक्स्ट मिलता है तो मैंने इसे ASCII का उपयोग करके परिवर्तित कर दिया है। यहां तक ​​कि मैं इसे बाइट सरणी में वापस ले जाता हूं, यह बिल्कुल वैल्यू वापस मिलता है । – kangalert

+0

आप जांच सकते हैं कि स्ट्रिंग में बाइट्स आपके पहले बाइट [] सरणी से मेल खाते हैं या नहीं। मुझे गंभीरता से संदेह है कि वे करेंगे। "यूएस-एएससीआईआईआई"! = बाइनरी डेटा। –

0

आपके मामले में सिफर पैडिंग का उपयोग करता है, इसका मतलब है कि दूसरे शब्दों में इनपुट डेटा कुछ पूर्वनिर्धारित आकार (जो पैडिंग एल्गोरिदम पर निर्भर करता है) के साथ ब्लॉक में गद्देदार/गोल किया जाएगा। आइए मान लें कि आपने एन्क्रिप्ट करने के लिए 500 बाइट्स की आपूर्ति की है, पैडिंग ब्लॉक आकार 16 बाइट्स है, इसलिए एन्क्रिप्टेड डेटा में 512 बाइट्स (32 ब्लॉक) का आकार होगा - 12 बाइट्स गद्देदार होंगे।

अपने कोड में आप इनपुट सरणी के समान आकार की एन्क्रिप्टेड सरणी की अपेक्षा कर रहे हैं, जो अपवाद का कारण बनता है। आपको पैडिंग को ध्यान में रखते हुए आउटपुट सरणी आकार को पुन: गणना करने की आवश्यकता है।

+0

आपका मतलब है कि एन्क्रिप्टेड स्ट्रिंग मेरे पैडिंग ब्लॉक का एक ही आकार होना चाहिए? – kangalert

+0

नहीं, स्ट्रिंग (वास्तव में स्ट्रिंग नहीं है लेकिन बाइट [] सरणी) पैडिंग ब्लॉक आकार – barmaley

3

जैसा कि यान रामिन ने कहा, स्ट्रिंग का उपयोग सिफर/आउटपुट के लिए विफलता है। यह बाइनरी डेटा कि

  • 0x00
  • शामिल कर सकते हैं मूल्यों निर्धारण या प्रयुक्त एन्कोडिंग में अजीब स्थानों पर मैप नहीं कर रहे हैं समाहित कर सकता है

उपयोग सादे बाइट [] अपने पहले उदाहरण के रूप में या हेक्स एन्कोडिंग या बेस 64 एन्कोडिंग बाइट [] के लिए जाएं।

// this is a quick example - dont use sun.misc inproduction 
// - go for some open source implementation 
String encryptedString = new sun.misc.BASE64Encoder.encodeBuffer(encryptedBytes); 

यह स्ट्रिंग सुरक्षित रूप से परिवहन और बाइट्स पर मैप किया जा सकता है।

उदाहरण

static public byte[] decrypt(Cipher cipher, SecretKey key, byte[]... bytes) 
     throws GeneralSecurityException, IOException { 
    cipher.init(Cipher.DECRYPT_MODE, key); 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    for (int i = 0; i < bytes.length; i++) { 
     bos.write(cipher.update(bytes[i])); 
    } 
    bos.write(cipher.doFinal()); 
    return bos.toByteArray(); 
} 
+1

धन्यवाद के लिए गोल किया जाना चाहिए। लेकिन मुझे bos.write में एक त्रुटि है (cipher.update (बाइट्स [i])); cipher.update केवल बाइट सरणी स्वीकार करता है। – kangalert

+0

@ कंगलर्ट ने आपको विधि हस्ताक्षर नोटिस किया था? बाइट्स [i] ** ** एक बाइट सरणी है। हो सकता है कि आप अपनी जरूरतों के लिए हस्ताक्षर अनुकूलित करें, सरणी या सूची का सरणी का उपयोग करें ... – mtraut

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