2011-03-15 19 views
9

मैं उच्च-समवर्ती अनुप्रयोग के लिए निम्न कोड का उपयोग करना चाहता हूं जहां कुछ डेटा एन्क्रिप्टेड और डिक्रिप्ट किया जाना चाहिए। तो मुझे पता होना चाहिए कि अप्रत्याशित मुद्दों से बचने के लिए, इस कोड का कौन सा हिस्सा सिंक्रनाइज़ किया जाना चाहिए, यदि कोई है।क्या यह जावा एन्क्रिप्शन कोड थ्रेड सुरक्षित है?

public class DesEncrypter { 
    Cipher ecipher; 
    Cipher dcipher; 

    // 8-byte Salt 
    byte[] salt = { 
     (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32, 
     (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03 
    }; 

    int iterationCount = 19; 

    DesEncrypter(String passPhrase) { 
     try { 
      // Create the key 
      KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); 

      SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec); 
      ecipher = Cipher.getInstance(key.getAlgorithm()); 
      dcipher = Cipher.getInstance(key.getAlgorithm()); 

      // Prepare the parameter to the ciphers 
      AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); 

      // Create the ciphers 
      ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); 
      dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); 
     } catch (...) 
    } 

    public String encrypt(String str) { 
     try { 
      // Encode the string into bytes using utf-8 
      byte[] utf8 = str.getBytes("UTF8"); 
      // Encrypt 
      byte[] enc = ecipher.doFinal(utf8); 
      // Encode bytes to base64 to get a string 
      return new sun.misc.BASE64Encoder().encode(enc); 

     } catch (...) 
    } 

    public String decrypt(String str) { 
     try { 
      // Decode base64 to get bytes 
      byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str); 
      // Decrypt 
      byte[] utf8 = dcipher.doFinal(dec); 
      // Decode using utf-8 
      return new String(utf8, "UTF8"); 
     } catch (...) 
    } 
} 

अगर मैं) एन्क्रिप्ट (में एक नया सिफर बना सकते हैं और प्रत्येक मंगलाचरण के लिए डिक्रिप्ट() पद्धतियों, तो मैं संगामिति समस्याओं से बचने कर सकते हैं, मैं सिर्फ यकीन नहीं है अगर वहाँ एक नया प्राप्त करने में भूमि के ऊपर का एक बहुत है प्रत्येक आमंत्रण के लिए एक सिफर का उदाहरण।

public String encrypt(String str) { 
     try { 
      // Encode the string into bytes using utf-8 
      byte[] utf8 = str.getBytes("UTF8"); 
      // Encrypt 
      //new cipher instance 
      ecipher = Cipher.getInstance(key.getAlgorithm()); 

      byte[] enc = ecipher.doFinal(utf8); 
      // Encode bytes to base64 to get a string 
      return new sun.misc.BASE64Encoder().encode(enc); 

     } catch (...) 

उत्तर

3

चीजें केवल थ्रेड-सुरक्षित होने की आवश्यकता होती है अगर उन्हें एक साथ कई धागे द्वारा उपयोग किया जाता है। चूंकि इस वर्ग के प्रत्येक उदाहरण का संभवतः केवल एक ही थ्रेड द्वारा उपयोग किया जाएगा, इस बारे में चिंता करने की आवश्यकता नहीं है कि यह थ्रेडसेफ है या नहीं।

एक असंबंधित नोट पर, हार्डकोडेड नमक, नॉन या IV होने पर कभी भी एक अच्छा विचार नहीं है।

+0

उसे नहीं पता था, धन्यवाद। मैं केवल आवेदन के लिए उपलब्ध सख्त ओएस अनुमतियों के तहत अलग-अलग फाइलों में नमक और पास-वाक्यांश को स्टोर करने की योजना बना रहा हूं। – user646584

+0

निरंतर नमक का उपयोग करना (भले ही यह संरक्षित है) पहले स्थान पर नमक का उपयोग करने के अधिकांश बिंदु को हरा देता है। –

+0

आप कह रहे हैं कि नमक रनटाइम पर यादृच्छिक रूप से प्राप्त किया जाना चाहिए? मैं उलझन में हूं, स्पष्ट रूप से पास-वाक्यांश बदल नहीं सकता है जब डेटा इसके साथ एन्क्रिप्ट किया गया है, तो एक सुरक्षित फ़ाइल, नमक और पासफ्रेज, बस पासफ्रेज इत्यादि के सामने आगे बढ़ने और संग्रहीत करने की आवश्यकता क्या है? – user646584

10

मानक नियम है - जब तक जावाडोक राज्यों स्पष्ट है कि जावा पुस्तकालयों में एक वर्ग के धागे की सुरक्षित है, तो आप मान लेना चाहिए कि ऐसा नहीं है।

इस विशेष उदाहरण में:

  • विभिन्न कक्षाओं धागा सुरक्षित के रूप में दस्तावेज नहीं हैं।
  • Cipher.getInstance(...) और SecretKeyFactory.getInstance(...) विधियों को नई वस्तुओं को वापस करने के रूप में दस्तावेज किया गया है; यानी मौजूदा वस्तुओं के संदर्भ नहीं हैं जिनके अन्य धागे के संदर्भ हो सकते हैं।

    "। एक नया SecretKeyFactory वस्तु पहले प्रदाता का समर्थन करता है कि निर्दिष्ट एल्गोरिथ्म दिया जाता है से SecretKeyFactorySpi कार्यान्वयन encapsulating": -

    अद्यतनjavadoc इस कहते हैं

    इसके अलावा, source code स्पष्ट रूप से पुष्टि की है कि एक नई वस्तु बनाया है और दिया जाता है।

संक्षेप में, इसका मतलब है कि आपके DesEncryptor वर्ग वर्तमान में धागे की सुरक्षित नहीं है, लेकिन आप प्रासंगिक आपरेशन (जैसे encode और decode) सिंक्रनाइज़ किया जा रहा है, और उजागर नहीं द्वारा यह धागा सुरक्षित बनाने के लिए सक्षम होना चाहिए दो सिफर वस्तुओं। यदि सिंक्रनाइज़ किए गए तरीकों को एक बाधा उत्पन्न करने की संभावना है, तो प्रत्येक थ्रेड के लिए DesEncryptor का एक अलग उदाहरण बनाएं।

+0

ऐसे पुराने विषय पर पोस्ट करने के लिए खेद है, लेकिन मुझे संदेह है कि SecretKeyFactory.getInstance() हर बार एक नई वस्तु देता है क्योंकि यह एक कारखाना है। इसके अलावा, मैं अभी इसका परीक्षण कर रहा हूं और पहली कॉल 2.5 एस लेती है जबकि प्रत्येक परिणामी कॉल 0s लेता है। – andrewktmeikle

+0

1) अद्यतन देखें।2) पहली कॉल शायद क्लास लोडिंग को ट्रिगर कर रही है, और प्रारंभिकरण जिसमें ओएस से "एन्ट्रॉपी" प्राप्त हो सकता है। कुछ परिस्थितियों में, यह वास्तविक समय की * महत्वपूर्ण * राशि ले सकता है। –

+0

पर्याप्त मेला, यह एक सिंगलटन टीबी होने के बारे में ज्यादा समझ में नहीं आया। यह पहली बार एंट्रॉपी क्यों इकट्ठा करेगा? निश्चित रूप से जब भी आप getInstance कहलाते हैं तो इसे करने की आवश्यकता होगी? – andrewktmeikle

1

Cipher ऑब्जेक्ट थ्रेड-सुरक्षित नहीं होने वाला है, क्योंकि यह एन्क्रिप्शन प्रक्रिया के बारे में आंतरिक स्थिति को बरकरार रखता है। यह आपके DesEncrypter वर्ग पर भी लागू होता है - प्रत्येक थ्रेड को DesEncrypter के अपने उदाहरण का उपयोग करने की आवश्यकता होगी, जब तक कि आप encode और decode विधियों को सिंकोननाइज़ न करें।

+0

ऊपर मेरा उदाहरण देखें ... क्यों न केवल एन्क्रिप्ट()/decrypt() के प्रत्येक आमंत्रण के लिए एक नया सिफर उदाहरण बनाते हैं? – user646584

+2

हां, लेकिन आपके उदाहरण में आप सिफर उदाहरणों को संग्रहीत करने के लिए आवृत्ति चर 'ecipher' और' dcipher' का उपयोग कर रहे हैं, इसलिए यदि 2 थ्रेड एक ही 'DesEncrypter' उदाहरण पर एक साथ एन्क्रिप्ट() को कॉल करते हैं, तो वे एक-दूसरे को घुमाएंगे (जब तक आप 'एन्क्रिप्ट()' कॉल सिंक्रनाइज़ नहीं करते)। इससे बचने के लिए, आप आवृत्ति चर के बजाय 'ecipher' और' dcipher' स्थानीय चर (एन्क्रिप्ट() फ़ंक्शन के भीतर) बना सकते हैं, इस तरह एन्क्रिप्ट() के प्रत्येक आमंत्रण का अपना मूल्य होगा। –

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