2010-02-17 8 views
25

मैं उद्देश्य-सी में एक स्ट्रिंग एन्क्रिप्ट कर रहा हूं और एईएस का उपयोग कर जावा में एक ही स्ट्रिंग को एन्क्रिप्ट कर रहा हूं और कुछ अजीब मुद्दों को देख रहा हूं। परिणाम का पहला भाग एक निश्चित बिंदु तक मेल खाता है लेकिन फिर यह अलग है, इसलिए जब मैं जावा से परिणाम को डीकोड करने के लिए जाता हूं तो यह इसे डिक्रिप्ट नहीं कर सकता है।मैं जावा और ऑब्जेक्टिव-सी (आईफोन) के बीच अपने एईएस एन्क्रिप्शन को समान कैसे बना सकता हूं?

मैं अब "स्रोत के स्ट्रिंग का उपयोग कर रहा हूं और यह बकवास क्या है। क्या आप जानते हैं?" "123456789" की एक कुंजी का उपयोग करके

एन्क्रिप्ट करने के लिए उद्देश्य-सी कोड निम्न है: नोट: यह एक एनएसडीएटी श्रेणी है, इसलिए मान लें कि विधि को एनएसडीटा ऑब्जेक्ट पर कहा जाता है, इसलिए 'स्वयं' में बाइट डेटा होता है एन्क्रिप्ट।

- (NSData *)AESEncryptWithKey:(NSString *)key { 
char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused) 
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

// fetch key data 
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

NSUInteger dataLength = [self length]; 

//See the doc: For block ciphers, the output size will always be less than or 
//equal to the input size plus the size of one block. 
//That's why we need to add the size of one block here 
size_t bufferSize = dataLength + kCCBlockSizeAES128; 
void *buffer = malloc(bufferSize); 

size_t numBytesEncrypted = 0; 
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
      keyPtr, kCCKeySizeAES128, 
      NULL /* initialization vector (optional) */, 
      [self bytes], dataLength, /* input */ 
      buffer, bufferSize, /* output */ 
      &numBytesEncrypted); 
if (cryptStatus == kCCSuccess) { 
    //the returned NSData takes ownership of the buffer and will free it on deallocation 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
} 

free(buffer); //free the buffer; 
return nil; 
} 

और जावा एन्क्रिप्शन कोड है ...

public byte[] encryptData(byte[] data, String key) { 
    byte[] encrypted = null; 

    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    byte[] keyBytes = key.getBytes(); 

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

    try { 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); 
     cipher.init(Cipher.ENCRYPT_MODE, keySpec); 

     encrypted = new byte[cipher.getOutputSize(data.length)]; 
     int ctLength = cipher.update(data, 0, data.length, encrypted, 0); 
     ctLength += cipher.doFinal(encrypted, ctLength); 
    } catch (Exception e) { 
     logger.log(Level.SEVERE, e.getMessage()); 
    } finally { 
     return encrypted; 
    } 
} 

उद्देश्य-सी कोड की हेक्स उत्पादन होता है -

7a68ea36 8288c73d f7c45d8d 22432577 9693920a 4fae38b2 2e4bdcef 9aeb8afe 69394f3e 1eb62fa7 74da2b5c 8d7b3c89 a295d306 f1f90349 6899ac34 63a6efa0 

और जावा उत्पादन होता है -

7a68ea36 8288c73d f7c45d8d 22432577 e66b32f9 772b6679 d7c0cb69 037b8740 883f8211 748229f4 723984beb 50b5aea1 f17594c9 fad2d05e e0926805 572156d 

जैसा कि आप देख सकते हैं कि सब ठीक है -

7a68ea36 8288c73d f7c45d8d 22432577 

मैं अनुमान लगा रहा हूँ मैं सेटिंग्स अलग से कुछ है, लेकिन काम नहीं कर सकते हैं, मैं जावा तरफ ईसीबी और सीबीसी के बीच बदलते की कोशिश की और यह कोई प्रभाव नहीं पड़ा।

क्या कोई मदद कर सकता है ?? कृपया ....

+0

आप लोगों ने मुझे एक आत्मनिर्भर दुःस्वप्न से बचाया ... धन्यवाद! – Shade

उत्तर

18

चूंकि सीसीसीआरपीटी एक चौथाई लेता है, क्या यह एक चेनिंग ब्लॉक सिफर विधि (जैसे सीबीसी) का उपयोग नहीं करता है? यह आपके द्वारा देखे जाने वाले कार्यों के अनुरूप होगा: पहला ब्लॉक समान है, लेकिन दूसरे ब्लॉक में जावा संस्करण एन्क्रिप्ट करने के लिए मूल कुंजी लागू करता है, लेकिन ओएसएक्स संस्करण कुछ और उपयोग करने लगता है।

संपादित करें:

here से मैं एक उदाहरण देखा।

ccStatus = CCCrypt(encryptOrDecrypt, 
     kCCAlgorithm3DES, 
     kCCOptionECBMode, <-- this could help 
     vkey, //"123456789", //key 
     kCCKeySize3DES, 
     nil, //"init Vec", //iv, 
     vplainText, //"Your Name", //plainText, 
     plainTextBufferSize, 
     (void *)bufferPtr, 
     bufferPtrSize, 
     &movedBytes); 

संपादित करें 2:

मैं कुछ कमांड लाइन को देखने के लिए जो एक सही था के साथ चारों ओर खेला है जैसे आप CCCrypt को kCCOptionECBMode पास करनी होगी लगता है। मैंने सोचा कि मैं यह योगदान कर सकता है:

$ echo "Now then and what is this nonsense all about. Do you know?" | openssl enc -aes-128-ecb -K $(echo 123456789| xxd -p) -iv 0 | xxd 
0000000: 7a68 ea36 8288 c73d f7c4 5d8d 2243 2577 zh.6...=..]."C%w 
0000010: e66b 32f9 772b 6679 d7c0 cb69 037b 8740 .k2.w+fy...i.{[email protected] 
0000020: 883f 8211 7482 29f4 7239 84be b50b 5aea .?..t.).r9....Z. 
0000030: eaa7 519b 65e8 fa26 a1bb de52 083b 478f ..Q.e..&...R.;G. 
+0

मुझे लगता है कि सोच रहा था, लेकिन मैं करने के लिए निम्न ... Cipher.getInstance ("एईएस/सीबीसी/PKCS7Padding", "ईसा पूर्व") जावा कोड बदल दिया; ... लेकिन इससे कोई फर्क नहीं पड़ता। जावा कोड को सीबीसी का उपयोग करने के लिए मुझे कुछ और बदलने की ज़रूरत नहीं है? –

+1

बिल्कुल जगह पर! बहुत बहुत धन्यवाद। मैं अब दीवार के खिलाफ अपने सिर को टक्कर मारना बंद कर सकता हूं :) चीयर्स फिर से। –

+0

कोई समस्या नहीं, मदद की खुशी है। मैंने ओपनस्ल के साथ खेला कि यह पता लगाने की कोशिश कर रहा है कि जावा या मैक रिथ थे या नहीं। मैंने openssl कमांड लाइन जोड़ा जो मैंने साइफर उत्पन्न करने के लिए उपयोग किया था। मुझे उम्मीद है कि यह उपयोग किया जा सकता है। –

9

किसी और ने इस की जरूरत के लिए, अस्वीकार बिल्कुल स्थान पर रहा था ... इस प्रकार उद्देश्य-सी में तहखाने बनाने के लिए संशोधित कॉल है (ध्यान दें कि आप ईसीबी मोड की जरूरत है और गद्दी) ...

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode + kCCOptionPKCS7Padding, 
              keyPtr, kCCKeySizeAES128, 
              NULL /* initialization vector (optional) */, 
              [self bytes], dataLength, /* input */ 
              buffer, bufferSize, /* output */ 
              &numBytesEncrypted); 
+0

ध्यान दें कि सुरक्षा के लिए, सीबीसी मोड ईसीबी से काफी बेहतर माना जाता है। ईसीबी इस बारे में जानकारी लीक करता है कि कौन से इनपुट ब्लॉक एक-दूसरे के समान हैं, और ऐसे समान ब्लॉक अक्सर "सामान्य डेटा" में होते हैं। सीबीसी को एक प्रकार के डेटा यादृच्छिकरण के रूप में देखा जा सकता है, जो इस तरह के ब्लॉक की घटना को कम संभव बनाता है। –

+0

धन्यवाद! मैं इसे पूरा करने की कोशिश कर एक पूरे दिन बिताता। – ebi

+0

इससे मदद मिली !! स्वीकार्य उत्तर आपको "कॉल कॉल में अधिक पैरामीटर" जैसी त्रुटि देगा। यह उत्तर होना चाहिए। – abhi1992

11

मैं कुछ हफ़्तों तक एक बेस 64 इनकोडिंग, AES256 एन्क्रिप्टेड स्ट्रिंग decrypting। आईपैड पर सीसीसीआरपीटी (उद्देश्य-सी) द्वारा एन्क्रिप्शन किया गया था। जावा में डिक्रिप्शन किया जाना था (बाउंसी कैसल का उपयोग करना)।

अंततः मैं प्रक्रिया में काफी सफल हुआ और सीखा। एन्क्रिप्शन कोड बिल्कुल ऊपर जैसा ही था (मुझे लगता है कि इसे आईफोन डेवलपर दस्तावेज़ में उद्देश्य-सी नमूना से लिया गया है)।

क्या CCCrypt() प्रलेखन का उल्लेख नहीं है यह डिफ़ॉल्ट रूप से सीबीसी मोड का उपयोग करता है (यदि आप kCCOptionECBMode जैसा कोई विकल्प निर्दिष्ट नहीं करते हैं) है। यह उल्लेख करता है कि IV, यदि निर्दिष्ट नहीं है, तो सभी शून्यों के लिए डिफ़ॉल्ट (इसलिए IV 0x00 का बाइट सरणी होगा, लंबाई में 16 सदस्य)।

जानकारी के इन दो टुकड़े का उपयोग करके आप एक कार्यात्मक रूप से समान एन्क्रिप्शन सीबीसी का उपयोग कर मॉड्यूल बनाने (और ईसीबी जो कम सुरक्षित है उपयोग करने से बचें) दोनों जावा और OSx/iPhone/iPad (CCCrypt) पर कर सकते हैं।

सिफर init समारोह एक तिहाई तर्क के रूप में चतुर्थ बाइट सरणी ले जाएगा:

cipher.init(Cipher.ENCRYPT_MODE, keySpec, IV). 
+0

इसके लिए धन्यवाद, आपने मेरा दिन बचाया। – Esko

+0

सीसीसीआरपीटी दस्तावेज डिफ़ॉल्ट रूप से सीबीसी का उपयोग करने के बारे में बात करता है - कम से कम मुझे यकीन है कि मैंने कहीं कहीं देखा है। मैंने जो किया * नहीं * कहीं भी देखा गया था IV को डिफ़ॉल्ट करने का कोई उल्लेख था। वह गायब घटक था - धन्यवाद! – David

+0

किसी और के लिए इसे पढ़ने के लिए ... अब आप IV को 'Cipher.init() 'पास नहीं कर सकते हैं। आपको क्या करना है (1) 'एल्गोरिदम पैरामीटर' ऑब्जेक्ट प्राप्त करें ('getInstance()' वर्ग फैक्ट्री विधि का उपयोग करके, (2) पैरामीटर ऑब्जेक्ट में IV को स्टोर करें: 'params.init (नया IvParameterSpec (iv)) ; 'और (3)' params 'ऑब्जेक्ट को 'cipher.init()' के तीसरे तर्क के रूप में पास करें। – David

2

बस पहली पोस्ट में जोड़ने के लिए: अपने उद्देश्य सी/कोको कोड में आप सीबीसी मोड का उपयोग करें और अपने जावा कोड में आपने ईबीसी का उपयोग किया और एक चौथाई प्रारंभिक वेक्टर का उपयोग किसी भी रूप में नहीं किया गया था। ईबीसी सिफर ब्लॉक और सीबीसी चेन द्वारा पिछले ब्लॉक पर अवरुद्ध है, इसलिए यदि आपका टेक्स्ट 1 ब्लॉक से छोटा है (= आपके उदाहरण में 16 बाइट्स), दोनों द्वारा उत्पादित सिफर टेक्स्ट दूसरे (उसी) द्वारा डिक्रिप्टेबल है।

आप देख रहे हैं एक तरह से सिफर के आपके उपयोग का मानकीकरण करने के लिए, NIST विशेष प्रकाशन 800-38A, 2001 संस्करण परीक्षण वेक्टर है। मैं एईएस सीबीसी और ईबीसी वैक्टर के लिए कोड पोस्ट कर सकता हूं अगर यह किसी के लिए सहायक हो।