2009-12-17 14 views
14

में स्ट्रिंग decrypting एन्क्रिप्शन के लिए के लिए एन्क्रिप्शन कुंजी को बहाल मैं कुछ इस तरह का उपयोग करें:आसान तरीका स्टोर करने के लिए/जावा

SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey(); 
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm()); 
String aesEncrypted= aesEncrypt.encrypt(StringContent); 

अगर मैं aesKey प्रिंट आउट मैं: "[email protected]" ।

तो एन्क्रिप्शन के लिए मैं कुंजी के लिए उपयोगकर्ता पूछना चाहता लेकिन जानते हैं कि कैसे और यह क्या प्रारूप होना चाहिए न होगा। मेरे योजना कुछ इस तरह था:

SecretKey aesKey = [email protected]; 
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm()); 
String aesDecrypt = aesEncrypt.decrypt(aesEncrypted); 

लेकिन इसके काम नहीं कर रहा है। एन्क्रिप्शन के बाद एन्क्रिप्शन के बाद कुंजी मुद्रित करने का कोई आसान तरीका है ताकि उपयोगकर्ता इसे सहेज सके (या याद रख सके) और फिर डिक्रिप्शन के लिए उपयोग करें?

पूरा कोड यहां है: Cannot decrypt cyphertext from text file, symmetric key implement. in java तो मुझे फिर से पोस्ट करने के लिए खेद है, लेकिन मुझे यकीन नहीं है कि कोड भी पठनीय है (मैं नौसिखिया हूं)।

+0

कृपया मेरे अद्यतन उत्तर देखें। – erickson

उत्तर

0

बस संदर्भ के लिए मदद मिल सकती है है, उत्पादन आप देख रहे हैं डिफ़ॉल्ट toString विधि का नतीजा है और अंत पर अजीब नंबर एक हैश कोड है। here देखें। हैश कोड डिज़ाइन द्वारा परिवर्तनीय नहीं हैं, और toString आपको मूल वस्तु को पुनर्निर्मित करने के लिए पर्याप्त जानकारी देने की गारंटी नहीं है (हालांकि यह कुछ कक्षाओं के लिए करता है)।

12

अधिकांश जावा Key उदाहरणों को getEncoded() विधि से उत्पन्न बाइट्स की एक स्ट्रिंग के रूप में दर्शाया जाता है। बाद में कुंजी को पुनर्निर्माण के लिए इसे संग्रहीत करने की आवश्यकता है।

हालांकि, इलेक्ट्रॉनिक रूप में सुरक्षित रूप से एक कुंजी संग्रहीत करने में, यह एन्क्रिप्टेड किया जाना चाहिए। बेशक, कुंजी को एन्क्रिप्ट करने के लिए एक और कुंजी (या पासवर्ड) और नरक की आवश्यकता होगी; और इसलिए आपके पास अनंत अनंत है। जावा KeyStore का उपयोग इस तरीके से SecretKey ऑब्जेक्ट्स को स्टोर करने के लिए किया जा सकता है, और यह उपयोगी है जब आपके पास कई गुप्त कुंजी हैं जो सभी एक "मास्टर" पासवर्ड से सुरक्षित हैं। लेकिन एक कुंजी की रक्षा के लिए, यह बहुत समझ में नहीं आता है।

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

एक और दृष्टिकोण PBKDF2 की तरह एक कलन विधि का उपयोग, उपयोगकर्ता एक यादगार पासवर्ड चुनने के लिए अनुमति देते हैं, और उस के साथ कुंजी उत्पन्न करने के लिए है। मुख्य व्युत्पन्न के लिए उपयोग किए जाने वाले नमक (और शायद पुनरावृत्ति गणना) को कहीं भी दर्ज किया जाना चाहिए। एक और कमी यह है कि लोग कुल उपलब्ध में से अपेक्षाकृत सीमित संख्या में पासवर्ड चुनते हैं। तो पासवर्ड से व्युत्पन्न कुंजी मुख्य आकार की तुलना में आसान अनुमान हो सकती है।


यहाँ बने और एक गुप्त कुंजी के पुनर्गठन के लिए बुनियादी तकनीक का एक उदाहरण है।

byte[] encoded = aesKey.getEncoded(); 
/* Now store "encoded" somewhere. For example, display the key and 
    ask the user to write it down. */ 
String output = Base64.getEncoder().withoutPadding().encodeToString(encoded); 
System.out.println("Keep it secret, keep it safe! " + output); 

... 

/* At some point, you need to reconstitute the key. Let's say the user 
    enters it as a base-64 number that you convert to bytes. */ 
String input = ... ; 
byte[] encoded = Base64.getDecoder().decode(input); 
SecretKey aesKey = new SecretKeySpec(encoded, "AES"); 
+0

स्पष्टीकरण के लिए धन्यवाद। लेकिन मैं एक (KeyGenerator.getInstance ("एईएस") जेनरेट करने की बजाय कुंजी कैसे कॉल कर सकता हूं। उत्पन्न करें();)? अब मैं getEncoded() के साथ कुंजी प्रिंट कर सकता हूं, उपयोगकर्ता इसे लिख देगा। लेकिन मैं कुंजी को वापस कैसे बुलाता हूं? – dave91

+0

मैं इस कोड के नए बिगइंटर (इनपुट, 16) .toByteArray() भाग के साथ असंगत पढ़ता देख रहा हूं। जब मैं इसका उपयोग करने की कोशिश करता हूं तो 17bytes में इसकी पढ़ाई और मुझे 'अमान्य एईएस कुंजी लंबाई: 17 बाइट्स' त्रुटि देने की तुलना में अधिक बार। इसका कारण क्या हो सकता है? – sapatos

+2

@sapatos अगर कुंजी का उच्च बिट सेट किया गया है, तो 'BigInteger' बाइट सरणी की शुरुआत में शून्य बाइट जोड़ देगा ताकि इसे नकारात्मक संख्या के रूप में व्याख्या करने से रोका जा सके। हो सकता है कि 'नया बिगइंटर (1, एन्कोडेड)' की बजाय, आपको स्ट्रिंग को ऋणात्मक संख्या होने की अनुमति देनी चाहिए: 'नया बिगइंटर (एन्कोडेड) ' – erickson

20

मुझे हाल ही में यह करना पड़ा है। और जबकि अन्य उत्तरों ने मुझे सही दिशा में ले जाया, यह आसान हो सकता था। तो यहां दिन के लिए मेरा "शेयर" है, सरल एईएस कुंजी हेरफेर के लिए कुछ सहायक तरीके।(Apache Commons और कोडेक पर निर्भरता पर ध्यान दें।)

यह सब अब एक Git रेपो में है: github.com/stuinzuri/SimpleJavaKeyStore

import static org.apache.commons.codec.binary.Hex.*; 
import static org.apache.commons.io.FileUtils.*; 
import java.io.*; 
import java.security.NoSuchAlgorithmException; 
import javax.crypto.*; 
import org.apache.commons.codec.DecoderException; 

public static SecretKey generateKey() throws NoSuchAlgorithmException 
{ 
    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); 
    keyGenerator.init(256); // 128 default; 192 and 256 also possible 
    return keyGenerator.generateKey(); 
} 

public static void saveKey(SecretKey key, File file) throws IOException 
{ 
    char[] hex = encodeHex(key.getEncoded()); 
    writeStringToFile(file, String.valueOf(hex)); 
} 

public static SecretKey loadKey(File file) throws IOException 
{ 
    String data = new String(readFileToByteArray(file)); 
    byte[] encoded; 
    try { 
     encoded = decodeHex(data.toCharArray()); 
    } catch (DecoderException e) { 
     e.printStackTrace(); 
     return null; 
    } 
    return new SecretKeySpec(encoded, "AES"); 
} 
+2

क्या यह विफल नहीं होगा यदि 'getEncoded()' द्वारा लौटाई गई सरणी नल बाइट्स का नेतृत्व कर रही है या यदि पहले बाइट में उच्चतम बिट सेट है? –

+0

@NiklasB। फिक्स्ड, इंगित करने के लिए धन्यवाद। –

+1

_ मैं स्थिर उपयोगिता कार्यों और स्थिर आयात _ के प्रशंसक हूँ :) –

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