2014-06-27 6 views
6

के साथ स्ट्रिंग एन्क्रिप्ट और डिक्रिप्ट करें मैं C++ openssl और aes cbc के साथ स्ट्रिंग को एन्क्रिप्ट और डिक्रिप्ट करने का प्रयास कर रहा हूं।सी ++, ओपनेंस और एएस

इसके बारे में अजीब बात यह है कि एक पीसी पर यह काम करता है, और दूसरे पीसी पर यह नहीं होता है। वहां मेरे पास मूल स्ट्रिंग का केवल 3/4 है, इसलिए अंत गलत है।

अन्य अजीब बात यह है कि, जब मैं दूसरे पीसी पर exe फ़ाइल की निर्देशिका में "libeay32.dll" नामक एक डीएल जोड़ता हूं, तो यह काम करता है, लेकिन पहले पीसी पर नहीं।

संक्षेप में, पहला पीसी केवल डीएलएल के बिना काम करता है, दूसरा पीसी केवल डीएल के साथ काम करता है।

मेरा सवाल यह है कि, क्या यह कोड बेहतर हो सकता है, और यह कंप्यूटर एक कंप्यूटर पर क्यों आवश्यक है, लेकिन दूसरे पर नहीं।

यहाँ मैं पहले से लिखे गए:

#define KEY "abc" 
#define Iv "abc" 

एन्क्रिप्शन समारोह:

string aes_encrypt(string _InStr) 
{ 
    string EncKey, 
      EncIV; 

    AES_KEY enc_key; 

    unsigned char * aes_key = (unsigned char *) malloc (sizeof(unsigned char) * (32)), 
        * iv_enc = (unsigned char *) malloc (sizeof(unsigned char) * AES_BLOCK_SIZE), 
        * aes_input = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size()), 
        * enc_out = (unsigned char *) malloc (sizeof(unsigned char) * ((_InStr.size() + AES_BLOCK_SIZE)/AES_BLOCK_SIZE) * AES_BLOCK_SIZE); 



    memcpy ((char *) aes_input, _InStr.c_str(), _InStr.size()); 

    memset (aes_key, 0, 32); 

    EncKey = KEY; 
    EncIV = Iv; 

    for (int i = 0; i < 50; i++) 
     EncKey = md5 (EncKey.c_str()); 


    for (int i = 0; i < 305; i++) 
     EncIV = md5 (EncIV.c_str()); 

    EncIV.erase (16); 

    memcpy (aes_key, EncKey.c_str(), 32); 
    memcpy (iv_enc, EncIV.c_str (), 16); 


    AES_set_encrypt_key (aes_key, 128, &enc_key); 
    AES_cbc_encrypt  (aes_input, enc_out, _InStr.size(), &enc_key, iv_enc, AES_ENCRYPT); 


    free (aes_key); 
    free (aes_input); 
    free (iv_enc); 

    aes_key  = NULL; 
    aes_input = NULL; 
    iv_enc  = NULL; 

    return string ((char *) enc_out); 

} 

डिक्रिप्शन समारोह:

string aes_decrypt (string _InStr) 
{ 
    string EncKey, 
      EncIV; 

    AES_KEY dec_key; 

    unsigned char * aes_key = (unsigned char *) malloc (sizeof(unsigned char) * (32)), 
        * iv_dec = (unsigned char *) malloc (sizeof(unsigned char) * AES_BLOCK_SIZE), 
        * enc_out = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size()), 
        * dec_out = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size()); 


    memcpy (enc_out, _InStr.c_str(), _InStr.size()); 

    memset (aes_key, 0, 32); 

    EncKey = KEY; 
    EncIV = Iv; 

    for (int i = 0; i < 50; i++) 
     EncKey = md5 (EncKey.c_str()); 

    for (int i = 0; i < 305; i++) 
     EncIV = md5 (EncIV.c_str()); 

    EncIV.erase (16); 

    memcpy (aes_key, EncKey.c_str(), 32); 
    memcpy (iv_dec, EncIV.c_str (), 16); 

    AES_set_decrypt_key(aes_key, 128, &dec_key); 
    AES_cbc_encrypt(enc_out, dec_out, _InStr.size(), &dec_key, iv_dec, AES_DECRYPT); 

    free (aes_key); 
    free (iv_dec); 
    free (enc_out); 

    aes_key  = NULL; 
    iv_dec  = NULL; 
    enc_out  = NULL; 

    return string ((char *) dec_out); 

} 

आउटपुट

कुंजी और चतुर्थ परिभाषित कर रहे हैं पहले का पीसी:

इनपुट:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

एनक्रिप्टेड:

एस^Wo◄┘ "एक ▼ ~ ¼ \ é╣ $ ╨L╡`aC ♠ · ñZ½h╠∟≥ä ° ╪╥ = αp╙IφoCYN ° ☺§) ↨XwY + ☼▀╤M▓ ÷ √NÉk┼≡ < ák◄Ä┬ ÷ ∙ z ¼üt @ ¥ ≈╟ ∙ ¶√Ñù ° 7å²²²²½½½½½½½½ε ■ ε ■

Decrypted:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

दूसरे पीसी के आउटपुट :

इनपुट:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

एनक्रिप्टेड???

एस^Wo + "एक ~ ¼ \ $ ðLÁ`aC é| · ñZ½h| = एक ° IE = ÓpËIÝoCYN °? §)? XwY + ¯¯ÐM| ÷ ¹NÉk + < ák? Ä- ÷ ¨zð + BANFb YÙ]?रों

Decrypted:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa वाई »एच + ²²²²||||||w $ ओ ओ:

+0

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

+0

ईमानदारी से, * anes_encrypt() 'के प्रारंभिक इनपुट * के संभावित अपवाद के साथ, और' aes_decrypt' के अंतिम आउटपुट * के साथ, 'std :: string' इस में * कहीं भी नहीं होना चाहिए। और यदि आप स्वयं को सी ++ में सी-सीटी-कास्टिंग पाते हैं, तो बाधाएं आप कुछ गलत कर रहे हैं। दोनों कार्य रिसाव स्मृति, बीटीडब्ल्यू। – WhozCraig

+0

आपको * AES_encrypt' और दोस्तों का उपयोग नहीं करना चाहिए।आपको 'EVP_ *' फ़ंक्शंस का उपयोग करना चाहिए। 'EVP_ *' फ़ंक्शन हार्डवेयर का उपयोग करते हैं, जैसे एईएस-एनआई (यदि उपलब्ध हो)। ओपनएसएसएल विकी पर [ईवीपी सममित एन्क्रिप्शन और डिक्रिप्शन] देखें (https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption)। वास्तव में, आपको शायद प्रमाणित एन्क्रिप्शन का उपयोग करना चाहिए क्योंकि यह * दोनों * गोपनीयता और प्रामाणिकता प्रदान करता है। ओपनएसएसएल विकी पर [ईवीपी प्रमाणीकृत एन्क्रिप्शन और डिक्रिप्शन] देखें (https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption)। – jww

उत्तर

3

इन दो यकीन है कि के लिए टूट रहे हैं .. ..

for (int i = 0; i < 50; i++) 
    EncKey = md5 (EncKey.c_str()); 

for (int i = 0; i < 305; i++) 
    EncIV = md5 (EncIV.c_str()); 

EncKey = string(md5 (EncKey.c_str()), 16); 

अन्यथा, स्ट्रिंग MD5 द्वारा उत्पादित string निर्माता मुठभेड़ों 0x00 पहली बार में काट दिया गया है: आप की तरह कुछ की आवश्यकता होगी।

memcpy (aes_key, EncKey.c_str(), 32); 
memcpy (iv_enc, EncIV.c_str (), 16); 

पर सबसे अच्छा, MD5 16 बाइट्स के एक स्ट्रिंग का उत्पादन:


ये मुसीबत कर रहे हैं। आप 0 बाइट स्ट्रिंग से 32 बाइट्स को EncKey में खींच नहीं सकते हैं।

और यदि आप EncKey या EncIV में एक एम्बेडेड शून्य है तो आप परेशानी में हैं। यदि कोई है तो, तो वह स्ट्रिंग 16 बाइट्स भी नहीं है।

string aes_encrypt(string _InStr) 
{ 
    ... 
    return string ((char *) dec_out, <some size>); 
} 

और के आपके उपयोग:

return string ((char *) dec_out); 

यह के समान होने की जरूरत है:


और के रूप में जिम नीचे टिप्पणी में बताया, यह भी मुसीबत है AES_cbc_encrypt गलत दिखता है। आपको EVP_* इंटरफ़ेस से चिपकना चाहिए। उदाहरण के लिए, ओपनएसएसएल विकी पर EVP Symmetric Encryption and Decryption देखें।

बेहतर, जीसीएम जैसे प्रमाणीकृत एन्क्रिप्शन मोड का उपयोग करें ताकि आपको प्रामाणिकता/अखंडता आश्वासन भी मिल सके। उदाहरण के लिए, ओपनएसएसएल विकी पर EVP Authenticated Encryption and Decryption देखें।


अंत में, SHA256 या SHA512 की तरह एक बड़ा हैश का उपयोग करें। एमडी 5 अब पिछड़ा संगतता के अलावा किसी अन्य चीज़ के लिए वांछित नहीं है।

+1

यह भी मुसीबत है: वापसी स्ट्रिंग ((char *) enc_out); - enc_out शून्य-समाप्त नहीं किया गया है, और, गलती से शून्य बाइट्स द्वारा शून्य-समाप्त हो सकता है। –