2013-08-14 5 views
41

मानक जेडीके का उपयोग कर जावा में एक सुरक्षित, यादृच्छिक एईएस कुंजी उत्पन्न करने का अनुशंसित तरीका क्या है?जावा में एक सुरक्षित यादृच्छिक एईएस कुंजी कैसे बनाएं?

अन्य पोस्ट में, मैं इस पाया है, लेकिन एक SecretKeyFactory का उपयोग कर एक बेहतर विचार हो सकता है:

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
SecureRandom random = new SecureRandom(); // cryptograph. secure random 
keyGen.init(random); 
SecretKey secretKey = keyGen.generateKey(); 

यह अगर जवाब क्यों यह पैदा करने का एक अच्छा तरीका है की एक विवरण शामिल बहुत अच्छा होगा यादृच्छिक कुंजी धन्यवाद!

+0

यह mighth मदद http://stackoverflow.com/questions साथ रैंड की जगह: यह मैं क्या उपयोग है/10252449/is-aes-key-random – Tala

+0

@ टाला वह जगह है जहां मुझे [उद्धृत कोड] (http://stackoverflow.com/a/10252662/1005481) मिला। लेकिन उस पोस्ट से, मैं यादृच्छिक कुंजी बनाने के तरीके पर सर्वसम्मति निर्धारित नहीं कर सका, और यह एक सुरक्षित तरीका क्यों था। –

उत्तर

53

मैं आपके द्वारा सुझाए गए कोड का प्रयोग करेंगे, लेकिन एक मामूली सरलीकरण के साथ:

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
keyGen.init(256); // for example 
SecretKey secretKey = keyGen.generateKey(); 

प्रदाता का चयन कैसे यह अनियमितता प्राप्त करने के लिए योजना बना रही है चलो - कुछ है कि क्या प्रदाता के रूप में रूप में अच्छा नहीं हो सकता है परिभाषित नहीं करते पहले ही चुना गया है

यह कोड उदाहरण मानता है (as Maarten points out below) कि आपने अपनी java.security फ़ाइल को सूची के शीर्ष पर अपने पसंदीदा प्रदाता को शामिल करने के लिए कॉन्फ़िगर किया है। यदि आप प्रदाता को मैन्युअल रूप से निर्दिष्ट करना चाहते हैं, तो बस KeyGenerator.getInstance("AES", "providerName"); पर कॉल करें।

वास्तव में सुरक्षित कुंजी के लिए, आपको कुंजी उत्पन्न करने और संरक्षित करने के लिए hardware security module (HSM) का उपयोग करने की आवश्यकता है। एचएसएम निर्माता आमतौर पर एक जेसीई प्रदाता की आपूर्ति करेंगे जो ऊपर दिए गए कोड का उपयोग करके आपके लिए सभी प्रमुख पीढ़ी करेगा।

+1

आम तौर पर मैं प्रदाता नाम भी छोड़ दूंगा। प्लेटफॉर्म को कॉन्फ़िगर करें (उदा। 'Java.security' फ़ाइल का उपयोग करके या 'Security.addProvider()' और इसी प्रकार 'का उपयोग करके' प्रदाता 'प्रोग्रामेटिक रूप से कॉन्फ़िगर करके। अन्यथा कोड कम पोर्टेबल होगा, और यह उपयोगकर्ता को उदा। आवेदन कोड बदलने के बिना एक एचएसएम। –

+0

मुझे प्रदाता निर्दिष्ट करने की आवश्यकता क्यों होगी? डिफ़ॉल्ट व्यवहार उच्च प्राथमिकता वाले स्थापित प्रदाता का उपयोग करना है जो एल्गोरिदम का समर्थन करता है, जो मेरे लिए पर्याप्त लगता है। –

+2

सभी प्रमुख पीढ़ी के तरीकों को बराबर नहीं बनाया गया है, और आप स्पष्ट रूप से चुनना चाहते हैं उदा। एक प्रदाता की कुंजी पीढ़ी विधि। यह सुरक्षा टोकन के लिए प्रदाताओं के लिए विशेष रूप से उपयोग किया जाता है। हालांकि एईएस के लिए, यादृच्छिक संख्या जनरेटर अधिक महत्व का हो सकता है - उदाहरण के लिए आप डिफ़ॉल्ट के बजाय धीमे, अधिक सुरक्षित, FIPS प्रमाणित यादृच्छिक संख्या जनरेटर का उपयोग करना चाहते हैं। –

19

KeyGenerator का उपयोग करना पसंदीदा तरीका होगा। जैसा कि डंकन ने इंगित किया था, मैं निश्चित रूप से प्रारंभिकरण के दौरान मुख्य आकार देता हूं। KeyFactory एक ऐसी विधि है जिसका उपयोग पूर्व-मौजूदा कुंजी के लिए किया जाना चाहिए।

ठीक है, तो चलिए इस के बारे में बताते हैं। सिद्धांत रूप में एईएस कुंजी का कोई मूल्य हो सकता है। (3) डीईएस में कोई "कमजोर चाबियाँ" नहीं हैं। न ही कोई बिट्स हैं जिनके पास विशिष्ट अर्थ है (3) डीईएस समानता बिट्स। तो एक कुंजी उत्पन्न करना यादृच्छिक मानों के साथ बाइट सरणी उत्पन्न करने और इसके आसपास SecretKeySpec बनाने के समान सरल हो सकता है।

लेकिन आपके द्वारा उपयोग की जा रही विधि के फायदे अभी भी हैं: KeyGenerator विशेष रूप से कुंजी उत्पन्न करने के लिए बनाया गया है। इसका मतलब है कि इस पीढ़ी के लिए कोड अनुकूलित किया जा सकता है। यह में दक्षता और सुरक्षा लाभ हो सकते हैं। उदाहरण के लिए कुंजी को बेनकाब करने वाले टाइम साइड चैनल हमलों से बचने के लिए इसे प्रोग्राम किया जा सकता है। ध्यान दें कि byte[] को साफ़ करने के लिए पहले से ही एक अच्छा विचार हो सकता है, जिसमें महत्वपूर्ण जानकारी है क्योंकि उन्हें एक स्वैप फ़ाइल में लीक किया जा सकता है (हालांकि यह मामला हो सकता है)।

इसके अलावा, जैसा कि कहा गया है, सभी एल्गोरिदम पूरी तरह यादृच्छिक कुंजी का उपयोग नहीं कर रहे हैं। तो KeyGenerator का उपयोग करके अन्य एल्गोरिदम पर स्विच करना आसान हो जाएगा। अधिक आधुनिक सिफर हालांकि पूरी तरह से यादृच्छिक कुंजी स्वीकार करेंगे; इसे उदाहरण पर एक बड़ा लाभ माना जाता है। डेस।

अंत में, और मेरे मामले में सबसे महत्वपूर्ण कारण यह है कि KeyGenerator विधि एक सुरक्षित टोकन (स्मार्ट कार्ड, टीपीएम, यूएसबी टोकन या एचएसएम) के भीतर एईएस कुंजी को संभालने का एकमात्र वैध तरीका है। यदि आप byte[] को SecretKeySpec के साथ बनाते हैं तो कुंजी मेमोरी से आनी चाहिए। इसका मतलब है कि कुंजी को सुरक्षित टोकन में रखा जा सकता है, लेकिन कुंजी को स्मृति में उजागर किया गया है। आम तौर पर, सुरक्षित टोकन केवल उन चाबियों के साथ काम करते हैं जो या तो सुरक्षित टोकन में उत्पन्न होते हैं या उदा। एक स्मार्ट कार्ड या एक महत्वपूर्ण समारोह। एक KeyGenerator एक प्रदाता के साथ आपूर्ति की जा सकती है ताकि कुंजी सुरक्षित टोकन के भीतर सीधे उत्पन्न हो।

जैसा कि Duncan's answer में इंगित किया गया है: हमेशा कुंजी आकार (और कोई अन्य पैरामीटर) निर्दिष्ट करें। प्रदाता डिफ़ॉल्ट पर भरोसा न करें क्योंकि यह स्पष्ट नहीं करेगा कि आपका एप्लिकेशन क्या कर रहा है, और प्रत्येक प्रदाता के पास अपना स्वयं का डिफ़ॉल्ट हो सकता है।

+0

इस उत्कृष्ट पृष्ठभूमि जानकारी के लिए धन्यवाद! –

+0

अधिक मेरियर। सामान्य के रूप में एक उत्कृष्ट उत्तर :-) –

2

अन्य पदों में बहुत अच्छे सलाहकार हैं।

Key key; 
SecureRandom rand = new SecureRandom(); 
KeyGenerator generator = KeyGenerator.getInstance("AES"); 
generator.init(256, rand); 
key = generator.generateKey(); 

यदि आप किसी अन्य अनियमितता प्रदाता है, जो मैं कुछ समय परीक्षण प्रयोजनों के लिए करना चाहिए, तो बस

MySecureRandom rand = new MySecureRandom(); 
+0

पहली बार जब मैं यादृच्छिक जनरेटर निर्दिष्ट करता हूं, दूसरी बार उपयोग करने के लिए एईएस कुंजी की लंबाई (256)। वे अलग init तरीकों हैं। – Andy

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