कैसे जावा में स्ट्रिंग एन्क्रिप्ट करने के लिए


150

मुझे स्ट्रिंग को एन्क्रिप्ट करने की आवश्यकता है जो 2 डी बारकोड (पीडीएफ -417) में दिखाई देगा, जब किसी को स्कैन करने का विचार मिलेगा तो उसे पढ़ने योग्य कुछ भी नहीं मिलेगा।

अन्य आवश्यकताएं:

  • जटिल नहीं होना चाहिए
  • इसमें RSA, PKI इन्फ्रास्ट्रक्चर, प्रमुख जोड़े आदि शामिल नहीं होने चाहिए।

यह काफी सरल होना चाहिए ताकि आसपास के लोगों को छुटकारा मिले, और उस डेटा को पाने के इच्छुक अन्य कंपनियों के लिए डिक्रिप्ट करना आसान हो। वे हमें कॉल करते हैं, हम उन्हें मानक बताते हैं या उन्हें कुछ सरल कुंजी देते हैं जो तब डिक्रिप्शन के लिए उपयोग की जा सकती हैं।

संभवत: वे कंपनियां विभिन्न तकनीकों का उपयोग कर सकती हैं, इसलिए कुछ मानक से चिपकना अच्छा होगा जो कि किसी विशेष मंच या प्रौद्योगिकी से बंधा नहीं है।

आपकी क्या सलाह है? क्या उच्च सुरक्षा मानकों को प्राप्त करने में कुछ जावा क्लास कर रहा है encrypt()और decrypt()बहुत अधिक जटिलता के बिना है?



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

जवाबों:


156

यह पहला पृष्ठ है जो Google के माध्यम से दिखाता है और सभी कार्यान्वयनों में सुरक्षा कमजोरियां मुझे परेशान करती हैं इसलिए मैं इसे पोस्ट कर रहा हूं दूसरों के लिए एन्क्रिप्शन के बारे में जानकारी जोड़ने के लिए क्योंकि यह मूल पोस्ट से 7 साल हो गया है। मैं कंप्यूटर इंजीनियरिंग में मास्टर्स डिग्री रखता हूं और क्रिप्टोग्राफी का अध्ययन करने और सीखने में बहुत समय बिताता हूं इसलिए मैं इंटरनेट को सुरक्षित जगह बनाने के लिए अपने दो सेंट फेंक रहा हूं।

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

अद्यतन 4/5/18: मैंने उन्हें कुछ हिस्सों को समझने के लिए सरल बनाया और जस्सीट से Google की नई लाइब्रेरी टिंक तक अनुशंसित लाइब्रेरी को बदलने के लिए कहा , मैं जसीप्ट को मौजूदा सेटअप से पूरी तरह से हटाने की सिफारिश करूंगा

प्रस्तावना

मैं नीचे सुरक्षित सममित क्रिप्टोग्राफी की मूल बातें रेखांकित करूंगा और उन सामान्य गलतियों को इंगित करूंगा जो ऑनलाइन देखते हैं जब लोग मानक जावा लाइब्रेरी के साथ क्रिप्टो को अपने दम पर लागू करते हैं। यदि आप Google के नए पुस्तकालय पर चलने वाले सभी विवरणों को छोड़ना चाहते हैं, तो अपने प्रोजेक्ट में आयात करें और अपने सभी एन्क्रिप्ट के लिए AES-GCM मोड का उपयोग करें और आप सुरक्षित रहेंगे।

अब अगर आप जावा में पढ़े जाने के तरीके के बारे में जानना चाहते हैं

सिफर को ब्लॉक करें

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

अब ब्लॉक सिफर एल्गोरिथम उपलब्ध के बारे में आज करना सुनिश्चित करें कभी नहीं , मैं फिर कहता हूँ कभी नहीं का उपयोग डेस , मैं भी का उपयोग नेवर से होगा 3DES । केवल ब्लॉक सिफर जो स्नोडेन की एनएसए रिलीज भी सही मायने में छद्म-रैंडम के करीब होने की पुष्टि करने में सक्षम था, एईएस 256 है । एईएस 128 भी मौजूद है; अंतर एईएस 256 256-बिट ब्लॉक में काम करता है, जबकि एईएस 128 ब्लॉक में 128 काम करता है। सभी में, एईएस 128 सुरक्षित माना जाता है, हालांकि कुछ कमजोरियों की खोज की गई है, लेकिन 256 यह जितना ठोस होता है।

मजेदार तथ्य डेस को एनएसए ने वापस तोड़ दिया था जब इसे शुरू में स्थापित किया गया था और वास्तव में कुछ वर्षों के लिए एक रहस्य रखा गया था। हालाँकि कुछ लोग अभी भी 3DES के सुरक्षित होने का दावा करते हैं, फिर भी कुछ शोध पत्र ऐसे हैं जो 3DES में कमजोरियों का पता लगाते हैं और उनका विश्लेषण करते हैं ।

एन्क्रिप्शन मोड

एन्क्रिप्शन तब बनाया जाता है जब आप एक ब्लॉक सिफर लेते हैं और एक विशिष्ट योजना का उपयोग करते हैं ताकि यादृच्छिकता को कुंजी बनाने के लिए जोड़ा जाता है जो तब तक प्रतिवर्ती है जब तक आप कुंजी जानते हैं। इसे एक एन्क्रिप्शन मोड के रूप में संदर्भित किया जाता है।

यहाँ एक एन्क्रिप्शन मोड और ECB के रूप में जाना जाने वाला सबसे सरल मोड का एक उदाहरण है ताकि आप नेत्रहीन समझ सकें कि क्या हो रहा है:

ईसीबी मोड

एन्क्रिप्शन मोड आप सबसे अधिक ऑनलाइन देखेंगे निम्नलिखित हैं:

ईसीबी सीटीआर, सीबीसी, जीसीएम

सूचीबद्ध लोगों के बाहर अन्य मोड मौजूद हैं और मौजूदा समस्याओं को सुधारने के लिए शोधकर्ता हमेशा नए मोड की ओर काम कर रहे हैं।

अब चलो कार्यान्वयन पर चलते हैं और क्या सुरक्षित है। कभी भी ईसीबी का उपयोग न करें यह दोहराए जाने वाले डेटा को छिपाने के लिए बुरा है जैसा कि प्रसिद्ध लिनक्स पेंगुइन द्वारा दिखाया गया है ।लिनक्स पेंगुइन उदाहरण

जावा में लागू करते समय, ध्यान दें कि यदि आप निम्नलिखित कोड का उपयोग करते हैं, तो ईसीबी मोड डिफ़ॉल्ट रूप से सेट किया गया है:

Cipher cipher = Cipher.getInstance("AES");

... यह एक जीवंतता है! और दुर्भाग्य से, यह सब StackOverflow और ऑनलाइन ट्यूटोरियल और उदाहरणों में देखा जाता है।

Nonces और IVs

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

सामान्य मुद्दे जो मैं देखूंगा वह यह है कि लोग IV को एक स्थिर मूल्य के रूप में सेट करेंगे जो उनके कोड में समान निश्चित मूल्य के रूप में होगा। और यहाँ आईवीएस के लिए नुकसान है जिस क्षण आप दोहराते हैं कि आप वास्तव में अपने एन्क्रिप्शन की पूरी सुरक्षा से समझौता करते हैं।

एक यादृच्छिक IV उत्पन्न करना

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);

नोट: SHA1 टूट गया है, लेकिन मुझे पता नहीं है कि इस उपयोग के मामले में SHA256 को ठीक से कैसे लागू किया जाए, इसलिए यदि कोई इस पर एक दरार लेना चाहता है और इसे अपडेट करना चाहता है तो यह बहुत बढ़िया होगा! इसके अलावा SHA1 हमले अभी भी अपरंपरागत हैं क्योंकि यह दरार करने के लिए एक विशाल क्लस्टर पर कुछ साल लग सकते हैं। यहां विवरण देखें।

CTR कार्यान्वयन

सीटीआर मोड के लिए कोई पेडिंग आवश्यक नहीं है।

 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

CBC कार्यान्वयन

यदि आप CBC मोड को कार्यान्वित करना चुनते हैं तो PKCS7Padding इस प्रकार है:

 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

सीबीसी और सीटीआर भेद्यता और आपको जीसीएम का उपयोग क्यों करना चाहिए

हालाँकि कुछ अन्य मोड जैसे कि CBC और CTR सुरक्षित हैं, वे उस मुद्दे पर चलते हैं जहाँ एक हमलावर एन्क्रिप्टेड डेटा को फ्लिप कर सकता है, डिक्रिप्ट होने पर उसका मूल्य बदल सकता है। तो मान लें कि आप एक काल्पनिक बैंक संदेश "सेल 100" को एन्क्रिप्ट करते हैं, आपका एन्क्रिप्टेड संदेश इस तरह का दिखता है "eu23ng" हमलावर एक बिट को "eu53ng" में बदल देता है और अचानक जब आपके संदेश को डिक्रिप्ट किया जाता है, तो यह "900 नंबर" के रूप में पढ़ता है।

इससे बचने के लिए अधिकांश इंटरनेट GCM का उपयोग करता है, और हर बार जब आप HTTPS देखते हैं तो वे शायद GCM का उपयोग कर रहे हैं। GCM एन्क्रिप्टेड संदेश को हैश के साथ हस्ताक्षर करता है और यह सत्यापित करने के लिए जांचता है कि इस हस्ताक्षर का उपयोग करके संदेश को बदला नहीं गया है।

मैं इसकी जटिलता के कारण GCM को लागू करने से बचूंगा। आप Googles की नई लाइब्रेरी Tink का उपयोग करने से बेहतर हैं क्योंकि यहाँ पर यदि आप गलती से एक IV दोहराते हैं तो आप GCM के मामले में कुंजी से समझौता कर रहे हैं, जो कि अंतिम सुरक्षा दोष है। नए शोधकर्ता IV रिपीट प्रतिरोधी एन्क्रिप्शन मोड की दिशा में काम कर रहे हैं जहां आप IV को दोहराने पर भी खतरे में नहीं हैं, लेकिन इसके लिए मुख्यधारा में आना अभी बाकी है।

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

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

कुंजी बनाम पासवर्ड

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

तो आपके पास वास्तव में दो कार्यान्वयन हैं जो आप यहां कर सकते हैं, पहला यह है कि रैंडम चेंजेशन के लिए इस स्टैकऑवरफ्लो थ्रेड पर पाए गए कोड का उपयोग करें । यह समाधान खरोंच से एक कुंजी बनाने के लिए एक सुरक्षित यादृच्छिक संख्या जनरेटर का उपयोग करता है जिसे आप उपयोग कर सकते हैं।

अन्य कम सुरक्षित विकल्प का उपयोग करना है, उपयोगकर्ता इनपुट जैसे पासवर्ड। जैसा कि हमने चर्चा की है कि पासवर्ड पर्याप्त एन्ट्रापी नहीं है, इसलिए हमें PBKDF2 का उपयोग करना होगा , एक एल्गोरिदम जो पासवर्ड लेता है और इसे मजबूत करता है। यहाँ एक StackOverflow कार्यान्वयन है जो मुझे पसंद आया । हालाँकि Google Tink लाइब्रेरी में यह सब बनाया गया है और आपको इसका लाभ उठाना चाहिए।

Android डेवलपर्स

यहाँ इंगित करने के लिए एक महत्वपूर्ण बिंदु यह है कि आपका एंड्रॉइड कोड रिवर्स इंजीनियर है और अधिकांश मामलों में जावा कोड बहुत अधिक है। इसका मतलब है कि यदि आप अपने कोड में सादे पाठ में पासवर्ड संग्रहीत करते हैं। एक हैकर इसे आसानी से प्राप्त कर सकता है। आमतौर पर, इस प्रकार के एन्क्रिप्शन के लिए, आप असममित क्रिप्टोग्राफी और इतने पर उपयोग करना चाहते हैं। यह इस पद के दायरे से बाहर है इसलिए मैं इसमें गोता लगाने से बचूंगा।

2013 से एक दिलचस्प पढ़ना : इंगित करता है कि एंड्रॉइड में क्रिप्टो कार्यान्वयन के 88% अनुचित तरीके से किए गए थे।

अंतिम विचार

एक बार फिर मैं सुझाव दूंगा कि क्रिप्टो के लिए जावा लाइब्रेरी को सीधे लागू करने से बचें और Google टिंक का उपयोग करें , यह आपको सिरदर्द से बचाएगा क्योंकि उन्होंने सभी एल्गोरिदम को ठीक से लागू करने का वास्तव में अच्छा काम किया है। और फिर भी सुनिश्चित करें कि आप टिंकथ गीथब पर लाए गए मुद्दों की जांच करते हैं, कमजोरियों को यहां और वहां पॉपअप करते हैं।

यदि आपके पास कोई प्रश्न या प्रतिक्रिया है तो टिप्पणी करने के लिए स्वतंत्र महसूस करें! सुरक्षा हमेशा बदल रही है और आपको इसे बनाए रखने के लिए अपना सर्वश्रेष्ठ करने की आवश्यकता है :)


15
यह सबसे साफ चीज है जिसे मैंने कभी देखा है।
सेराफ जूल

1
@ साबिरखान यह चिंता का कारण हो सकता है, लेकिन कोर एल्गोरिदम अभी भी नहीं टूटे हैं, इसलिए मैं इसके बारे में बहुत चिंतित नहीं हूं। ऐसे मामले में जहां आप भरोसा नहीं करते हैं, यह भी github.com/google/keyczar की जाँच करें , यह googles सुरक्षा टीम द्वारा विकसित किया गया था।
कोन्स्टेंटिनो स्पार्किस

1
@KonstantinoSparakis: अगर मैंने Jasypt के BasicTextEncryptor और StrongTextEncryptor के लिए प्रलेखन की गलत व्याख्या नहीं की, तो वे कक्षाएं एन्क्रिप्ट करने के लिए DES और 3DES का उपयोग करती हैं, जो वास्तव में आप पाठकों को उपयोग नहीं करने के लिए कहते हैं। IMO आपको दिए गए कोड उदाहरणों को एक के साथ बदलना चाहिए जो कि Jasypt के StandardPBEStringEncryptor का उपयोग करता है और मैन्युअल रूप से उपयोग करने के लिए AES एल्गोरिथ्म को परिभाषित करता है।
xpages-noob

1
@ xpages-noob मैंने पोस्ट अपडेट की। मुझे वास्तव में Google टिंक मिला, जो क्रिप्टो के लिए नवीनतम समर्थित पुस्तकालय है, इसलिए आपको इसकी जांच करनी चाहिए!
कोन्स्टेंटिनो स्पार्किस

2
एईएस ब्लॉक का आकार 128 बिट्स है। एईएस 256 में, कुंजी का आकार 256 बिट्स है। इसी तरह, एईएस 192 और एईएस 128। इसके अलावा, जावा 8 के बाद से, getInstanceStrong()विधि CipherSHA1PRNG पर बेहतर है
सप्तर्षि बसु

110

मैं कुछ मानक सममित साइबर का उपयोग करने की सलाह दूंगा जो डीईएस , 3 डीईएस या एईएस की तरह व्यापक रूप से उपलब्ध है । हालांकि यह सबसे सुरक्षित एल्गोरिथ्म नहीं है, लेकिन कार्यान्वयन के भार हैं और आपको बस किसी को भी कुंजी देने की आवश्यकता होगी जिसे बारकोड में जानकारी को डिक्रिप्ट करना चाहिए। javax.crypto.Cipher जो आप यहाँ काम करना चाहते हैं।

मान लें कि बाइट्स इनक्रिप्ट करने के लिए हैं

byte[] input;

अगला, आपको कुंजी और आरंभीकरण वेक्टर बाइट्स की आवश्यकता होगी

byte[] keyBytes;
byte[] ivBytes;

अब आप उस एल्गोरिथ्म के लिए सिफर को इनिशियलाइज़ कर सकते हैं जिसे आप चुनते हैं:

// wrap key data in Key/IV specs to pass to cipher
SecretKeySpec key = new SecretKeySpec(keyBytes, "DES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
// create the cipher with the algorithm you choose
// see javadoc for Cipher class for more info, e.g.
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

एन्क्रिप्शन इस तरह होगा:

cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted= new byte[cipher.getOutputSize(input.length)];
int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);

और इस तरह डिक्रिप्शन:

cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0);
dec_len += cipher.doFinal(decrypted, dec_len);

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

javax.crypto.BadPaddingException साथ कुछ गलत: अंतिम ब्लॉक को देखते हुए ठीक से गद्देदार नहीं है, जबकि decript
curiousity

2
@ डंकन वास्तव में डेस कमजोर है, लेकिन मुझे लगता है कि एईएस डेसेड (उर्फ टीटीडीईएस) से अधिक बेहतर होगा: http://security.stackexchange.com/a/26181/69785
Piovezan 01

2
यह एईएस / जीसीएम / नोपैडिंग के लिए अद्यतन किया जाना चाहिए, डीईएस ब्रूटफोर्स हमलों के लिए असुरक्षित है, ट्रिपलडीज़ की सिफारिश नहीं की जाती है
कोन्स्टेंटिनो स्पार्किस

1
नीचे Konstantino Sparakis से जवाब तो इस एक से बहुत बेहतर है।
स्टीव

22

चेतावनी

इसे किसी प्रकार के सुरक्षा माप के रूप में उपयोग न करें।

इस पोस्ट में एन्क्रिप्शन तंत्र एक बार का पैड है, जिसका अर्थ है कि गुप्त कुंजी को 2 एन्क्रिप्टेड संदेशों का उपयोग करके एक हमलावर द्वारा आसानी से पुनर्प्राप्त किया जा सकता है। XOR 2 एन्क्रिप्टेड संदेश और आपको कुंजी मिलती है। यह सरल है!

मौसा ने इशारा किया


मैं Sun's Base64Encoder / Decoder का उपयोग कर रहा हूं जो कि Sun के JRE में पाया जाना है, क्योंकि अभी तक lib में एक और JAR से बचने के लिए। यह OpenJDK या कुछ अन्य JRE के उपयोग के बिंदु से खतरनाक है। इसके अलावा, वहाँ एक और कारण है कि मुझे एनकोडर / डिकोडर के साथ अपाचे कॉमन्स लिब का उपयोग करने पर विचार करना चाहिए?

public class EncryptUtils {
    public static final String DEFAULT_ENCODING = "UTF-8"; 
    static BASE64Encoder enc = new BASE64Encoder();
    static BASE64Decoder dec = new BASE64Decoder();

    public static String base64encode(String text) {
        try {
            return enc.encode(text.getBytes(DEFAULT_ENCODING));
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }//base64encode

    public static String base64decode(String text) {
        try {
            return new String(dec.decodeBuffer(text), DEFAULT_ENCODING);
        } catch (IOException e) {
            return null;
        }
    }//base64decode

    public static void main(String[] args) {
        String txt = "some text to be encrypted";
        String key = "key phrase used for XOR-ing";
        System.out.println(txt + " XOR-ed to: " + (txt = xorMessage(txt, key)));

        String encoded = base64encode(txt);       
        System.out.println(" is encoded to: " + encoded + " and that is decoding to: " + (txt = base64decode(encoded)));
        System.out.print("XOR-ing back to original: " + xorMessage(txt, key));
    }

    public static String xorMessage(String message, String key) {
        try {
            if (message == null || key == null) return null;

            char[] keys = key.toCharArray();
            char[] mesg = message.toCharArray();

            int ml = mesg.length;
            int kl = keys.length;
            char[] newmsg = new char[ml];

            for (int i = 0; i < ml; i++) {
                newmsg[i] = (char)(mesg[i] ^ keys[i % kl]);
            }//for i

            return new String(newmsg);
        } catch (Exception e) {
            return null;
        }
    }//xorMessage
}//class

1
मैंने इस समाधान प्रस्ताव का उपयोग sun.misc.BASE64Encoder के माध्यम से भी किया था, लेकिन जब एन्कोड करने के लिए बड़े स्ट्रिंग्स का उपयोग कर रहे थे, तो एनकोडर ने चैंकिंग स्ट्रिंग्स (प्रत्येक 76 वर्ण) को वापस कर दिया। मैंने फिर Apache Commons Codec Base64 पर स्विच किया, जो नॉन-चंकिंग एन्कोडिंग मेथड प्रदान करता है!
बेसेरो

78
यदि आपके द्वारा वर्णित एन्क्रिप्शन तंत्र एक से अधिक बार उपयोग किया जाता है तो बहुत खतरनाक है। यही कारण है कि इसे वन-टाइम पैड कहा जाता है। गुप्त कुंजी को एक हमलावर द्वारा 2 एन्क्रिप्टेड संदेशों का उपयोग करके आसानी से पुनर्प्राप्त किया जा सकता है। xor 2 एन्क्रिप्टेड संदेश और आपको कुंजी मिलती है। यह सरल है!
xtrem

3
इसका विचार भारी होना नहीं है, बस लोगों को पीडीएफ -417 2 डी बारकोड में जो लिखा है उसे पढ़ने की कोशिश करने से रोकना है। और वैसे भी, केवल कुछ ही सूचकांक किसी के लिए महत्वपूर्ण नहीं हैं ...
ante.sabo

2
ठीक है। बस चिंता है कि कोई इसे एक एन्क्रिप्शन तंत्र के रूप में उपयोग करता है।
xtrem

एन्क्रिप्शन के लिए, एनकोडर (जैसे। BASE64Encoder) को क्रूर बल के हमलों से बचा जा सकता है।
जागृत दलवाड़ी

13

धन्यवाद ive ने आपके कोड का उपयोग करके इस वर्ग को बनाया, हो सकता है कि कोई इसे उपयोगकर्ता-योग्य पाता हो

वस्तु क्रिप्टकार्ट

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class ObjectCrypter {

private Cipher deCipher;
private Cipher enCipher;
private SecretKeySpec key;
private IvParameterSpec ivSpec;


public ObjectCrypter(byte[] keyBytes,   byte[] ivBytes) {
    // wrap key data in Key/IV specs to pass to cipher


     ivSpec = new IvParameterSpec(ivBytes);
    // create the cipher with the algorithm you choose
    // see javadoc for Cipher class for more info, e.g.
    try {
         DESKeySpec dkey = new  DESKeySpec(keyBytes);
          key = new SecretKeySpec(dkey.getKey(), "DES");
         deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
         enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public byte[] encrypt(Object obj) throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, IllegalBlockSizeException, ShortBufferException, BadPaddingException {
    byte[] input = convertToByteArray(obj);
    enCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

    return enCipher.doFinal(input);




//  cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
//  byte[] encypted = new byte[cipher.getOutputSize(input.length)];
//  int enc_len = cipher.update(input, 0, input.length, encypted, 0);
//  enc_len += cipher.doFinal(encypted, enc_len);
//  return encypted;


}
public Object decrypt( byte[]  encrypted) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException {
    deCipher.init(Cipher.DECRYPT_MODE, key, ivSpec);

    return convertFromByteArray(deCipher.doFinal(encrypted));

}



private Object convertFromByteArray(byte[] byteObject) throws IOException,
        ClassNotFoundException {
    ByteArrayInputStream bais;

    ObjectInputStream in;
    bais = new ByteArrayInputStream(byteObject);
    in = new ObjectInputStream(bais);
    Object o = in.readObject();
    in.close();
    return o;

}



private byte[] convertToByteArray(Object complexObject) throws IOException {
    ByteArrayOutputStream baos;

    ObjectOutputStream out;

    baos = new ByteArrayOutputStream();

    out = new ObjectOutputStream(baos);

    out.writeObject(complexObject);

    out.close();

    return baos.toByteArray();

}


}

एक संबंधित प्रश्न यहाँ पोस्ट किया !
user2023507

क्या यह ऐसा नहीं होना चाहिए कि एन्क्रिप्ट और डिक्रिप्ट के दौरान अलग-अलग रास्ते से गुजरना पाठ को वापस नहीं करना चाहिए? ऐसा लगता नहीं है कि यहाँ हो रहा है। पुनश्च: मैं इस परीक्षण को करने के लिए इस वर्ग की विभिन्न वस्तुओं का उपयोग कर रहा हूं।
instanceOfObject

6

12-DEC-2019 को अपडेट करें

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

IV के रूप में एक अनुक्रम या टाइमस्टैम्प का उपयोग करना भी संभव है, लेकिन यह उतना तुच्छ नहीं हो सकता है जितना कि यह ध्वनि हो सकता है। उदाहरण के लिए, यदि सिस्टम सही तरीके से पहले से ही IV के रूप में उपयोग किए गए अनुक्रमों का ट्रैक नहीं रखता है, तो एक मंगलाचरण सिस्टम रिबूट के बाद एक IV दोहरा सकता है। इसी तरह, कोई भी सही घड़ी नहीं है। कंप्यूटर की घड़ी की पठन सामग्री आदि।

इसके अलावा, कुंजी को हर 2 ^ 32 इनवोकेशन के बाद घुमाया जाना चाहिए। IV आवश्यकता पर अधिक जानकारी के लिए, इस उत्तर और NIST सिफारिशों का संदर्भ लें ।


यह एन्क्रिप्शन और डिक्रिप्शन कोड है जिसे मैंने निम्नलिखित बिंदुओं पर विचार करके जावा 8 में लिखा है। आशा है कि किसी को यह उपयोगी लगेगा:

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

  2. GCM के लिए एक आरंभीकरण वेक्टर (IV) आवश्यक है। IV एक गुप्त नहीं है। एकमात्र आवश्यकता इसके यादृच्छिक या अप्रत्याशित होने की है। जावा में, SecuredRandomवर्ग क्रिप्टोग्राफिक रूप से मजबूत छद्म यादृच्छिक संख्याओं का उत्पादन करने के लिए है। छद्म यादृच्छिक संख्या पीढ़ी एल्गोरिथ्म getInstance()विधि में निर्दिष्ट किया जा सकता है । हालांकि, जावा 8 के बाद से, अनुशंसित तरीका getInstanceStrong()विधि का उपयोग करना है जो कॉन्फ़िगर किए गए और प्रदान किए गए सबसे मजबूत एल्गोरिथ्म का उपयोग करेगाProvider

  3. NIST जीसीएम के लिए 96 बिट IV की सिफारिश करता है ताकि डिजाइन की अंतर, दक्षता और सादगी को बढ़ावा दिया जा सके

  4. अतिरिक्त सुरक्षा सुनिश्चित करने के लिए, निम्नलिखित कार्यान्वयन SecureRandomको छद्म यादृच्छिक बाइट पीढ़ी के हर 2 ^ 16 बाइट्स के उत्पादन के बाद फिर से बीज दिया जाता है

  5. प्राप्तकर्ता को IV जानने की आवश्यकता है जो सिफर पाठ को डिक्रिप्ट करने में सक्षम हो। इसलिए IV को सिफर टेक्स्ट के साथ स्थानांतरित किया जाना चाहिए। कुछ कार्यान्वयन IV को AD (एसोसिएटेड डेटा) के रूप में भेजते हैं जिसका अर्थ है कि प्रमाणीकरण टैग की गणना सिफर पाठ और IV दोनों पर की जाएगी। हालाँकि, यह आवश्यक नहीं है। IV को सिफर टेक्स्ट के साथ प्री-पेंडिंग किया जा सकता है क्योंकि अगर IV जानबूझकर हमले या नेटवर्क / फाइल सिस्टम त्रुटि के कारण ट्रांसमिशन के दौरान बदल जाता है, तो प्रमाणीकरण टैग सत्यापन वैसे भी विफल हो जाएगा

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

  7. सामान्य अनुशंसाओं के बाद किसी भी प्रदाता को कोड में हार्ड कोड नहीं दिया जाता है

  8. अंत में नेटवर्क या स्टोरेज पर ट्रांसमिशन के लिए, आधार या सिफर टेक्स्ट को Base64 एन्कोडिंग का उपयोग करके एन्कोड किया जाना चाहिए। Base64 का विवरण यहां पाया जा सकता है । जावा 8 दृष्टिकोण का पालन किया जाना चाहिए

बाइट सरणियों का उपयोग करके साफ किया जा सकता है:

Arrays.fill(clearTextMessageByteArray, Byte.MIN_VALUE);

हालांकि, जावा 8 के रूप में, वहाँ स्पष्ट करने के लिए कोई आसान तरीका है SecretKeyspecऔर SecretKeyइन दो इंटरफेस के कार्यान्वयन के रूप में विधि को लागू किया है प्रतीत नहीं destroy()इंटरफ़ेस की Destroyable। निम्नलिखित कोड में, प्रतिबिंब को साफ करने SecretKeySpecऔर SecretKeyउपयोग करने के लिए एक अलग विधि लिखी गई है ।

नीचे वर्णित दो दृष्टिकोणों में से एक का उपयोग करके कुंजी उत्पन्न की जानी चाहिए।

ध्यान दें कि चाबियाँ पासवर्ड की तरह रहस्य हैं, लेकिन पासवर्ड के विपरीत जो मानव उपयोग के लिए हैं, कुंजी का उपयोग क्रिप्टोग्राफिक एल्गोरिदम द्वारा किया जाता है और इसलिए केवल उपरोक्त तरीके का उपयोग करके उत्पन्न किया जाना चाहिए।

package com.sapbasu.javastudy;

import java.lang.reflect.Field;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Crypto {

  private static final int AUTH_TAG_SIZE = 128; // bits

  // NIST recommendation: "For IVs, it is recommended that implementations
  // restrict support to the length of 96 bits, to
  // promote interoperability, efficiency, and simplicity of design."
  private static final int IV_LEN = 12; // bytes

  // number of random number bytes generated before re-seeding
  private static final double PRNG_RESEED_INTERVAL = Math.pow(2, 16);

  private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";

  private static final List<Integer> ALLOWED_KEY_SIZES = Arrays
      .asList(new Integer[] {128, 192, 256}); // bits

  private static SecureRandom prng;

  // Used to keep track of random number bytes generated by PRNG
  // (for the purpose of re-seeding)
  private static int bytesGenerated = 0;

  public byte[] encrypt(byte[] input, SecretKeySpec key) throws Exception {

    Objects.requireNonNull(input, "Input message cannot be null");
    Objects.requireNonNull(key, "key cannot be null");

    if (input.length == 0) {
      throw new IllegalArgumentException("Length of message cannot be 0");
    }

    if (!ALLOWED_KEY_SIZES.contains(key.getEncoded().length * 8)) {
      throw new IllegalArgumentException("Size of key must be 128, 192 or 256");
    }

    Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);

    byte[] iv = getIV(IV_LEN);

    GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);

    cipher.init(Cipher.ENCRYPT_MODE, key, gcmParamSpec);
    byte[] messageCipher = cipher.doFinal(input);

    // Prepend the IV with the message cipher
    byte[] cipherText = new byte[messageCipher.length + IV_LEN];
    System.arraycopy(iv, 0, cipherText, 0, IV_LEN);
    System.arraycopy(messageCipher, 0, cipherText, IV_LEN,
        messageCipher.length);
    return cipherText;
  }

  public byte[] decrypt(byte[] input, SecretKeySpec key) throws Exception {
    Objects.requireNonNull(input, "Input message cannot be null");
    Objects.requireNonNull(key, "key cannot be null");

    if (input.length == 0) {
      throw new IllegalArgumentException("Input array cannot be empty");
    }

    byte[] iv = new byte[IV_LEN];
    System.arraycopy(input, 0, iv, 0, IV_LEN);

    byte[] messageCipher = new byte[input.length - IV_LEN];
    System.arraycopy(input, IV_LEN, messageCipher, 0, input.length - IV_LEN);

    GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);

    Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
    cipher.init(Cipher.DECRYPT_MODE, key, gcmParamSpec);

    return cipher.doFinal(messageCipher);
  }

  public byte[] getIV(int bytesNum) {

    if (bytesNum < 1) throw new IllegalArgumentException(
        "Number of bytes must be greater than 0");

    byte[] iv = new byte[bytesNum];

    prng = Optional.ofNullable(prng).orElseGet(() -> {
      try {
        prng = SecureRandom.getInstanceStrong();
      } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("Wrong algorithm name", e);
      }
      return prng;
    });

    if (bytesGenerated > PRNG_RESEED_INTERVAL || bytesGenerated == 0) {
      prng.setSeed(prng.generateSeed(bytesNum));
      bytesGenerated = 0;
    }

    prng.nextBytes(iv);
    bytesGenerated = bytesGenerated + bytesNum;

    return iv;
  }

  private static void clearSecret(Destroyable key)
      throws IllegalArgumentException, IllegalAccessException,
      NoSuchFieldException, SecurityException {
    Field keyField = key.getClass().getDeclaredField("key");
    keyField.setAccessible(true);
    byte[] encodedKey = (byte[]) keyField.get(key);
    Arrays.fill(encodedKey, Byte.MIN_VALUE);
  }
}

एन्क्रिप्शन कुंजी को मुख्य रूप से दो तरीकों से उत्पन्न किया जा सकता है:

  • बिना किसी पासवर्ड के

    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(KEY_LEN, SecureRandom.getInstanceStrong());
    SecretKey secretKey = keyGen.generateKey();
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
        "AES");
    Crypto.clearSecret(secretKey);
    // After encryption or decryption with key
    Crypto.clearSecret(secretKeySpec);
  • पासवर्ड के साथ

    SecureRandom random = SecureRandom.getInstanceStrong();
    byte[] salt = new byte[32];
    random.nextBytes(salt);
    PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations, 
       keyLength);
    SecretKeyFactory keyFactory = 
        SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    SecretKey secretKey = keyFactory.generateSecret(keySpec);
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
        "AES");
    Crypto.clearSecret(secretKey);
    // After encryption or decryption with key
    Crypto.clearSecret(secretKeySpec);

टिप्पणियों के आधार पर अद्यतन करें

जैसा कि @MaartenBodewes द्वारा बताया गया है, मेरे उत्तर को किसी भी Stringतरह से हैंडल नहीं किया गया है जैसा कि प्रश्न द्वारा आवश्यक है। इसलिए, मैं उस अंतर को भरने का प्रयास करूँगा जब कोई व्यक्ति इस उत्तर पर ठोकर खाएगा और हैंडलिंग के बारे में सोचकर छोड़ देगा String

जैसा कि पहले उत्तर में संकेत दिया गया Stringहै, एक में संवेदनशील जानकारी को संभालना , सामान्य रूप से, एक अच्छा विचार नहीं है क्योंकि Stringअपरिवर्तनीय है और इस प्रकार हम उपयोग के बाद इसे बंद नहीं कर सकते। और जैसा कि हम जानते हैं, यहां तक ​​कि जब एक Stringमजबूत संदर्भ नहीं होता है, तो कचरा उठाने वाला तुरंत इसे हटाने के लिए जल्दी नहीं करता है। इस प्रकार, Stringकिसी अज्ञात विंडो के लिए मेमोरी में आस-पास होना जारी रहता है , भले ही यह प्रोग्राम तक पहुंच योग्य न हो। इस मुद्दे के साथ, उस समय सीमा के दौरान एक ढेर डंप संवेदनशील जानकारी को प्रकट करेगा। इसलिए, बाइट सरणी या चार सरणी में सभी संवेदनशील जानकारी को संभालना बेहतर होता है और फिर उनका उद्देश्य पूरा होने पर सरणी को 0 से भरें।

हालांकि, उस सभी ज्ञान के साथ, अगर हम अभी भी ऐसी स्थिति में समाप्त हो जाते हैं जहां एन्क्रिप्ट की जाने वाली संवेदनशील जानकारी एक में है String, तो हमें सबसे पहले इसे एक बाइट सरणी में परिवर्तित करने encryptऔर decryptऊपर पेश किए गए कार्यों और आह्वान की आवश्यकता है। (ऊपर दी गई कोड स्निपेट का उपयोग करके अन्य इनपुट कुंजी उत्पन्न की जा सकती है)।

एक Stringनिम्नलिखित तरीके से बाइट्स में बदला जा सकता:

byte[] inputBytes = inputString.getBytes(StandardCharsets.UTF_8);

जावा 8 के रूप में, Stringआंतरिक रूप से UTF-16एन्कोडिंग के साथ ढेर में संग्रहीत किया जाता है । हालाँकि, हमने UTF-8यहाँ उपयोग किया है क्योंकि यह आमतौर पर UTF-16ASCII वर्णों की तुलना में कम जगह लेता है ।

इसी तरह, एन्क्रिप्टेड बाइट सरणी भी नीचे के रूप में एक स्ट्रिंग में परिवर्तित किया जा सकता है:

String encryptedString = new String(encryptedBytes, StandardCharsets.UTF_8);

1
जितना मैं इस उत्तर को उभारना चाहता हूं, क्योंकि यह वर्तमान क्रिप्टो प्रथाओं का पालन करने के लिए दिखता है, मैं किसी भी स्ट्रिंग को संभालना नहीं देखता हूं, यह केवल जीसीएम मोड का उपयोग करने के तरीके पर एक विवरण की तरह अधिक बनाता है। जैसे कि यह प्रश्न का उत्तर देने में विफल है ।
मार्टन बोडेवेस

1
@MaartenBodewes प्रतिक्रिया की समीक्षा करने और साझा करने के लिए समय निकालने के लिए बहुत बहुत धन्यवाद। मैंने इसे इस समझ के साथ लिखा है कि Stringऊपर बनाए गए कार्यों का उपयोग करके एन्क्रिप्ट करना तुच्छ होगा। हालांकि, आपकी टिप्पणी पढ़ने के बाद एक दूसरे नज़र में मैं समझता हूं कि यह स्पष्ट नहीं हो सकता है। मैं निश्चित रूप से उन विवरणों को जोड़ने के लिए संपादित करूंगा।
सप्तर्षि बसु

5

इस बारे में कैसा है:

private static byte[] xor(final byte[] input, final byte[] secret) {
    final byte[] output = new byte[input.length];
    if (secret.length == 0) {
        throw new IllegalArgumentException("empty security key");
    }
    int spos = 0;
    for (int pos = 0; pos < input.length; ++pos) {
        output[pos] = (byte) (input[pos] ^ secret[spos]);
        ++spos;
        if (spos >= secret.length) {
            spos = 0;
        }
    }
    return output;
}

मेरे लिए ठीक काम करता है और बल्कि कॉम्पैक्ट है।


प्रविष्टि पैरामीटर गुप्त == अशक्त या इनपुट == अशक्त होने पर क्या होगा? बल्कि बाइट्स के साथ काम करना तब स्ट्रिंग्स के साथ ठीक है, लेकिन मेरे मामले में अप्रासंगिक था। केवल एक चीज जो मायने रखती है वह यह है कि किसी भी डिवाइस को किसी भी वर्ण में एन्कोडिंग के साथ पठनीय और डिकोडेबल होना चाहिए ...
ante.sabo

@ ante.sabo जाहिरा तौर पर, यह एक NPE फेंक देगा। यह केवल NULLs के साथ करने वाली चीज़ है।
Miha_x64

जब तक input.length <= secret.lengthधारण किया जाता है और secretकभी नहीं फिर से उपयोग किया जाता है तब तक यह सुरक्षित है और इसे कहा जाता है one-time-pad। इस के मामलों में विगेनेयर सिफरinput.length > secret.length का एक प्रकार है और बहुत कमजोर माना जाता है।
ट्रिचनर

5

आप Jasypt का उपयोग कर सकते हैं

Jasypt के साथ, पासवर्ड को एन्क्रिप्ट करना और जांचना जितना आसान हो सकता है ...

StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
textEncryptor.setPassword(myEncryptionPassword);

एन्क्रिप्शन:

String myEncryptedText = textEncryptor.encrypt(myText);

डिक्रिप्शन:

String plainText = textEncryptor.decrypt(myEncryptedText);

Gradle:

compile group: 'org.jasypt', name: 'jasypt', version: '1.9.2'

विशेषताएं:

Jasypt आपको आसान यूनिडायरेक्शनल (डाइजेस्ट) और बिडायरेक्शनल एन्क्रिप्शन तकनीक प्रदान करता है।

किसी भी JCE प्रदाता के साथ उपयोग के लिए ओपन एपीआई, और न केवल डिफ़ॉल्ट जावा वीएम एक। बाउंसी कैसल जैसे जाने-माने प्रदाताओं के साथ जस्सीट का उपयोग आसानी से किया जा सकता है। और अधिक जानें।

आपके उपयोगकर्ताओं के पासवर्ड के लिए उच्च सुरक्षा। और अधिक जानें।

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

संख्या एन्क्रिप्शन समर्थन। ग्रंथों और बायनेरिज़ के अलावा, यह संख्यात्मक मानों के पाचन और एन्क्रिप्शन की अनुमति देता है (BigInteger और BigDecimal, जब हाइबरनेट दृढ़ता के लिए एन्क्रिप्ट किया जाता है तो अन्य संख्यात्मक प्रकार समर्थित होते हैं)। और अधिक जानें।

पूरी तरह से धागा-सुरक्षित।

मल्टी-प्रोसेसर / मल्टी-कोर सिस्टम में उच्च प्रदर्शन प्राप्त करने के लिए, एनक्रिप्ट / डाइजेस्टर पूलिंग के लिए समर्थन।

मोबाइल प्लेटफार्मों जैसे आकार-प्रतिबंधात्मक वातावरणों में बेहतर प्रबंधन के लिए पुस्तकालय का एक हल्का ("लाइट") संस्करण शामिल है।

उपयोगकर्ताओं के लिए नए एन्क्रिप्शन के लिए आसान, नो-कॉन्फ़िगरेशन एन्क्रिप्शन उपकरण प्रदान करता है, और पावर-उपयोगकर्ताओं के लिए अत्यधिक कॉन्फ़िगर करने योग्य मानक एन्क्रिप्शन उपकरण भी प्रदान करता है।

एन्क्रिप्टेड तरीके से अपने मैप किए गए क्षेत्रों के क्षेत्रों को बनाए रखने के लिए हाइबरनेट 3 और 4 वैकल्पिक एकीकरण। हाइबरनेट मैपिंग फ़ाइलों में फ़ील्ड्स का एन्क्रिप्शन परिभाषित किया गया है, और यह बाकी एप्लिकेशन (संवेदनशील व्यक्तिगत डेटा के लिए उपयोगी, कई रीड-सक्षम उपयोगकर्ताओं के साथ डेटाबेस ...) के लिए पारदर्शी रहता है। ग्रंथों, बायनेरिज़, संख्याओं, बूलियन्स, तिथियों को एन्क्रिप्ट करें ... और जानें।

स्प्रिंग 2, स्प्रिंग 3.0 और स्प्रिंग 3.1 के लिए विशिष्ट एकीकरण सुविधाओं के साथ, एक स्प्रिंग एप्लीकेशन में सहज रूप से पूर्णांक। Jasypt में सभी डाइजेस्टर और एनक्रिप्टर्स आसानी से स्प्रिंग से (तात्कालिक, निर्भरता-इंजेक्शन ...) उपयोग करने के लिए डिज़ाइन किए गए हैं। और, उनके थ्रेड-सुरक्षित होने के कारण, उन्हें स्प्रिंग जैसे एकल-उन्मुख वातावरण में सिंक्रोनाइज़ेशन चिंताओं के बिना उपयोग किया जा सकता है। और जानें: स्प्रिंग 2, स्प्रिंग 3.0, स्प्रिंग 3.1।

स्प्रिंग सुरक्षा (पूर्व में Acegi Security) पासवर्ड एन्क्रिप्शन का प्रदर्शन करने और सुरक्षा ढांचे के लिए मिलान कार्यों के लिए वैकल्पिक एकीकरण, सुरक्षित पासवर्ड एन्क्रिप्शन तंत्र का उपयोग करके अपने उपयोगकर्ताओं के पासवर्ड की सुरक्षा में सुधार और आपको उच्च स्तर की कॉन्फ़िगरेशन और नियंत्रण प्रदान करता है। और अधिक जानें।

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

डेवलपर्स को उनके एन्क्रिप्ट किए गए डेटा को इनिशियलाइज़ करने और रखरखाव कार्यों या स्क्रिप्ट में एन्क्रिप्शन / डिक्रिप्शन / डाइजेस्ट ऑपरेशंस को शामिल करने की अनुमति देने के लिए CLI (कमांड लाइन इंटरफ़ेस) टूल्स का उपयोग करना आसान है। और अधिक जानें।

आपके सुरक्षित अनुप्रयोगों में URL के अधिक मजबूत एन्क्रिप्शन के लिए, Apache Wit में एकीकृत करता है।

व्यापक गाइड और javadoc प्रलेखन, डेवलपर्स को बेहतर समझने की अनुमति देने के लिए कि वे वास्तव में अपने डेटा पर क्या कर रहे हैं।

मजबूत चारसेट का समर्थन, जिसे मूल वर्णक्रम जो भी हो, ग्रंथों को पर्याप्त रूप से एन्क्रिप्ट और डाइजेस्ट करने के लिए डिज़ाइन किया गया है। जापानी, कोरियाई, अरबी जैसी भाषाओं के लिए पूर्ण समर्थन ... कोई एन्कोडिंग या प्लेटफ़ॉर्म मुद्दों के साथ नहीं।

बहुत उच्च स्तर की कॉन्फ़िगरेशन क्षमताएं: डेवलपर पासवर्ड के लिए एन्क्रिप्शन के लिए उपयोग किए जाने वाले रिमोट HTTPS सर्वर, उदाहरण के लिए, पूछने के लिए "एनक्रिप्ट" जैसे निर्देश लागू कर सकता है। यह आपको अपनी सुरक्षा जरूरतों को पूरा करने देता है।


1
लेकिन क्या सुरक्षा Jasyptप्रदान करता है ? मैं उनकी वेबसाइट से इसका पता नहीं लगा सकता। क्या चुना-सादा हमलों के तहत यह अविभाज्य है? अखंडता? गोपनीयता?
ट्रायकनर

4

यहाँ मेरा कार्यान्वयन Meta64.com से स्प्रिंग सिंगलटन के रूप में किया गया है। यदि आप प्रत्येक कॉल के लिए एक साइपर उदाहरण बनाना चाहते हैं जो काम भी करेगा, और फिर आप 'सिंक्रनाइज़' कॉल को निकाल सकते हैं, लेकिन सावधान रहें 'सिफर' थ्रेड-सुरक्षित नहीं है।

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class Encryptor {

    @Value("${aeskey}")
    private String keyStr;

    private Key aesKey = null;
    private Cipher cipher = null;

    synchronized private void init() throws Exception {
        if (keyStr == null || keyStr.length() != 16) {
            throw new Exception("bad aes key configured");
        }
        if (aesKey == null) {
            aesKey = new SecretKeySpec(keyStr.getBytes(), "AES");
            cipher = Cipher.getInstance("AES");
        }
    }

    synchronized public String encrypt(String text) throws Exception {
        init();
        cipher.init(Cipher.ENCRYPT_MODE, aesKey);
        return toHexString(cipher.doFinal(text.getBytes()));
    }

    synchronized public String decrypt(String text) throws Exception {
        init();
        cipher.init(Cipher.DECRYPT_MODE, aesKey);
        return new String(cipher.doFinal(toByteArray(text)));
    }

    public static String toHexString(byte[] array) {
        return DatatypeConverter.printHexBinary(array);
    }

    public static byte[] toByteArray(String s) {
        return DatatypeConverter.parseHexBinary(s);
    }

    /*
     * DO NOT DELETE
     * 
     * Use this commented code if you don't like using DatatypeConverter dependency
     */
    // public static String toHexStringOld(byte[] bytes) {
    // StringBuilder sb = new StringBuilder();
    // for (byte b : bytes) {
    // sb.append(String.format("%02X", b));
    // }
    // return sb.toString();
    // }
    //
    // public static byte[] toByteArrayOld(String s) {
    // int len = s.length();
    // byte[] data = new byte[len / 2];
    // for (int i = 0; i < len; i += 2) {
    // data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i +
    // 1), 16));
    // }
    // return data;
    // }
}

3
यह ईसीबी मोड के साथ एन्क्रिप्ट करेगा जो भयानक है। आपको कम से कम CBC मोड या GCM मोड
Konstantino Sparakis

सुझाव के लिए धन्यवाद कॉन्स्टेंटिन्टो, मैंने गुगली की और पाया कि कुछ कोड जो "एईएस / सीबीसी / पीकेसीएस 5 कोडिंग" का उपयोग करता है, सिफर के लिए इनिट स्ट्रिंग के रूप में, केवल "एईएस" के बजाय, लेकिन मैं इसमें और अधिक देखूंगा। या यदि आप चाहते हैं कि आप वास्तविक सुधार प्रदान कर सकें, तो अन्य बेहतर तरीके से देख सकते हैं। हालांकि, सीबीसी विस्तार से अलग मेरा मानना ​​है कि मेरा समाधान सबसे सरल और सुरक्षित है, और बाकी सभी से ऊपर उठने के योग्य है।

हाँ, कोई चिंता नहीं है, क्रिप्टो एक जटिल विषय है। अफसोस की बात है कि इस पृष्ठ पर हर कार्यान्वयन टूटा हुआ है और दुख की बात है कि यह पहला पृष्ठ है जो Google का उपयोग करने के लिए पॉप अप करता है "जावा एन्क्रिप्शन कैसे करें"। जब मुझे मौका मिलेगा मैं उन सभी को ठीक करने की कोशिश करूंगा।
कोन्स्टेंटिनो स्पार्किस

मेरा उदाहरण इस तरह से है: docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/… सिवाय इसके कि मुझे सिफर.गेट इनस्टेंस ("एईएस / ईसीबी / PKCS5Padding") की आवश्यकता है; मेरा कोड मानता है कि पूरी तरह से 16 बाइट लंबी एन्क्रिप्शन कुंजी के साथ कुछ प्रॉपर्टीज़ फ़ाइल हैं, लेकिन 'यूजर सप्लाई' पासवर्ड से एक स्ट्रिंग को एन्क्रिप्ट करने के लिए ओरेकल पेज (ऊपर लिंक किया गया) वह भी करने का तरीका दिखाता है।

1
तो ईसीबी के साथ समस्या यह है कि यह आवृत्ति विश्लेषण के लिए बेहद कमजोर है। लिनक्स पेंगुइन का प्रसिद्ध उदाहरण है, blog.filippo.io/the-ecb-penguin देखें कि कैसे छवि एन्क्रिप्ट की गई है आप अभी भी बता सकते हैं कि यह एक पेंगुइन है। मैं आगे चला गया और नीचे :) विषय नीचे पर अपने विचारों को लिखा stackoverflow.com/a/43779197/2607972
Konstantino Sparakis

4

यहाँ बाइट्स के एन्क्रिप्शन के लिए केवल java.*और javax.crypto.*निर्भरता के साथ एक सरल समाधान गोपनीयता और अखंडता प्रदान करता है । यह किलोबाइट के क्रम में छोटे संदेशों के लिए एक चुना सादे संदर्भ के तहत अप्रभेद्य होगा ।

यह बिना पैडिंग AESवाले GCMमोड में उपयोग करता है , 128 बिट कुंजी PBKDF2कई पुनरावृत्तियों और प्रदान किए गए पासवर्ड से एक स्थिर नमक द्वारा ली गई है। यह सुनिश्चित करता है कि ब्रूट फोर्सिंग पासवर्ड कठिन है और संपूर्ण कुंजी पर एन्ट्रापी वितरित करता है।

एक यादृच्छिक आरंभीकरण वेक्टर (IV) उत्पन्न होता है और इसे सिफरटेक्स्ट के लिए तैयार किया जाएगा। इसके अलावा, स्टैटिक बाइट 0x01को 'वर्जन' के रूप में पहले बाइट के रूप में प्रस्तुत किया जाता है।

संपूर्ण संदेश द्वारा उत्पन्न संदेश प्रमाणीकरण कोड (मैक) में चला जाता है AES/GCM

यहाँ यह शून्य बाह्य निर्भरता एन्क्रिप्शन वर्ग गोपनीयता और अखंडता प्रदान करता है :

package ch.n1b.tcrypt.utils;

import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * This class implements AES-GCM symmetric key encryption with a PBKDF2 derived password.
 * It provides confidentiality and integrity of the plaintext.
 *
 * @author Thomas Richner
 * @created 2018-12-07
 */
public class AesGcmCryptor {

    // /crypto/26783/ciphertext-and-tag-size-and-iv-transmission-with-aes-in-gcm-mode
    private static final byte VERSION_BYTE = 0x01;
    private static final int VERSION_BYTE_LENGTH = 1;
    private static final int AES_KEY_BITS_LENGTH = 128;


    // fixed AES-GCM constants
    private static final String GCM_CRYPTO_NAME = "AES/GCM/NoPadding";
    private static final int GCM_IV_BYTES_LENGTH = 12;
    private static final int GCM_TAG_BYTES_LENGTH = 16;

    // can be tweaked, more iterations = more compute intensive to brute-force password
    private static final int PBKDF2_ITERATIONS = 1024;

    // protects against rainbow tables
    private static final byte[] PBKDF2_SALT = hexStringToByteArray("4d3fe0d71d2abd2828e7a3196ea450d4");

    public String encryptString(char[] password, String plaintext) throws CryptoException {

        byte[] encrypted = null;
        try {
            encrypted = encrypt(password, plaintext.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException //
                | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException //
                | InvalidKeySpecException e) {
            throw new CryptoException(e);
        }
        return byteArrayToHexString(encrypted);
    }

    public String decryptString(char[] password, String ciphertext)
            throws CryptoException {

        byte[] ct = hexStringToByteArray(ciphertext);
        byte[] plaintext = null;
        try {
            plaintext = decrypt(password, ct);
        } catch (AEADBadTagException e) {
            throw new CryptoException(e);
        } catch ( //
                NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException //
                        | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException //
                        | BadPaddingException e) {
            throw new CryptoException(e);
        }
        return new String(plaintext, StandardCharsets.UTF_8);
    }

    /**
     * Decrypts an AES-GCM encrypted ciphertext and is
     * the reverse operation of {@link AesGcmCryptor#encrypt(char[], byte[])}
     *
     * @param password   passphrase for decryption
     * @param ciphertext encrypted bytes
     * @return plaintext bytes
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws InvalidKeySpecException
     * @throws InvalidAlgorithmParameterException
     * @throws InvalidKeyException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws IllegalArgumentException           if the length or format of the ciphertext is bad
     * @throws CryptoException
     */
    public byte[] decrypt(char[] password, byte[] ciphertext)
            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException,
            InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {

        // input validation
        if (ciphertext == null) {
            throw new IllegalArgumentException("ciphertext cannot be null");
        }

        if (ciphertext.length <= VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH + GCM_TAG_BYTES_LENGTH) {
            throw new IllegalArgumentException("ciphertext too short");
        }

        // the version must match, we don't decrypt other versions
        if (ciphertext[0] != VERSION_BYTE) {
            throw new IllegalArgumentException("wrong version: " + ciphertext[0]);
        }

        // input seems legit, lets decrypt and check integrity

        // derive key from password
        SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH);

        // init cipher
        Cipher cipher = Cipher.getInstance(GCM_CRYPTO_NAME);
        GCMParameterSpec params = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8,
                ciphertext,
                VERSION_BYTE_LENGTH,
                GCM_IV_BYTES_LENGTH
        );
        cipher.init(Cipher.DECRYPT_MODE, key, params);

        final int ciphertextOffset = VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH;

        // add version and IV to MAC
        cipher.updateAAD(ciphertext, 0, ciphertextOffset);

        // decipher and check MAC
        return cipher.doFinal(ciphertext, ciphertextOffset, ciphertext.length - ciphertextOffset);
    }

    /**
     * Encrypts a plaintext with a password.
     * <p>
     * The encryption provides the following security properties:
     * Confidentiality + Integrity
     * <p>
     * This is achieved my using the AES-GCM AEAD blockmode with a randomized IV.
     * <p>
     * The tag is calculated over the version byte, the IV as well as the ciphertext.
     * <p>
     * Finally the encrypted bytes have the following structure:
     * <pre>
     *          +-------------------------------------------------------------------+
     *          |         |               |                             |           |
     *          | version | IV bytes      | ciphertext bytes            |    tag    |
     *          |         |               |                             |           |
     *          +-------------------------------------------------------------------+
     * Length:     1B        12B            len(plaintext) bytes            16B
     * </pre>
     * Note: There is no padding required for AES-GCM, but this also implies that
     * the exact plaintext length is revealed.
     *
     * @param password  password to use for encryption
     * @param plaintext plaintext to encrypt
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws NoSuchPaddingException
     * @throws InvalidAlgorithmParameterException
     * @throws InvalidKeyException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws InvalidKeySpecException
     */
    public byte[] encrypt(char[] password, byte[] plaintext)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException,
            InvalidKeySpecException {

        // initialise random and generate IV (initialisation vector)
        SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH);
        final byte[] iv = new byte[GCM_IV_BYTES_LENGTH];
        SecureRandom random = SecureRandom.getInstanceStrong();
        random.nextBytes(iv);

        // encrypt
        Cipher cipher = Cipher.getInstance(GCM_CRYPTO_NAME);
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);

        // add IV to MAC
        final byte[] versionBytes = new byte[]{VERSION_BYTE};
        cipher.updateAAD(versionBytes);
        cipher.updateAAD(iv);

        // encrypt and MAC plaintext
        byte[] ciphertext = cipher.doFinal(plaintext);

        // prepend VERSION and IV to ciphertext
        byte[] encrypted = new byte[1 + GCM_IV_BYTES_LENGTH + ciphertext.length];
        int pos = 0;
        System.arraycopy(versionBytes, 0, encrypted, 0, VERSION_BYTE_LENGTH);
        pos += VERSION_BYTE_LENGTH;
        System.arraycopy(iv, 0, encrypted, pos, iv.length);
        pos += iv.length;
        System.arraycopy(ciphertext, 0, encrypted, pos, ciphertext.length);

        return encrypted;
    }

    /**
     * We derive a fixed length AES key with uniform entropy from a provided
     * passphrase. This is done with PBKDF2/HMAC256 with a fixed count
     * of iterations and a provided salt.
     *
     * @param password passphrase to derive key from
     * @param salt     salt for PBKDF2 if possible use a per-key salt, alternatively
     *                 a random constant salt is better than no salt.
     * @param keyLen   number of key bits to output
     * @return a SecretKey for AES derived from a passphrase
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private SecretKey deriveAesKey(char[] password, byte[] salt, int keyLen)
            throws NoSuchAlgorithmException, InvalidKeySpecException {

        if (password == null || salt == null || keyLen <= 0) {
            throw new IllegalArgumentException();
        }
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(password, salt, PBKDF2_ITERATIONS, keyLen);
        SecretKey pbeKey = factory.generateSecret(spec);

        return new SecretKeySpec(pbeKey.getEncoded(), "AES");
    }

    /**
     * Helper to convert hex strings to bytes.
     * <p>
     * May be used to read bytes from constants.
     */
    private static byte[] hexStringToByteArray(String s) {

        if (s == null) {
            throw new IllegalArgumentException("Provided `null` string.");
        }

        int len = s.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("Invalid length: " + len);
        }

        byte[] data = new byte[len / 2];
        for (int i = 0; i < len - 1; i += 2) {
            byte b = (byte) toHexDigit(s, i);
            b <<= 4;
            b |= toHexDigit(s, i + 1);
            data[i / 2] = b;
        }
        return data;
    }

    private static int toHexDigit(String s, int pos) {
        int d = Character.digit(s.charAt(pos), 16);
        if (d < 0) {
            throw new IllegalArgumentException("Cannot parse hex digit: " + s + " at " + pos);
        }
        return d;
    }

    private static String byteArrayToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    public class CryptoException extends Exception {

        public CryptoException(Throwable cause) {
            super(cause);
        }
    }
}

यहाँ एक अच्छा CLI: https://github.com/trichner/tcrypt के साथ पूरा प्रोजेक्ट

संपादित करें: अब उपयुक्त encryptStringऔर के साथdecryptString


बहुत शानदार। धन्यवाद! मैंने आपके कोड से बहुत कुछ सीखा है और BadVersionException Exception क्लास बनाने के बाद, आपके कोड ने पहली बार पूरी तरह से काम किया है। अति उत्कृष्ट!!
मॉर्कस

मुझे यह प्रयास पसंद है। उस ने कहा ... नमक यादृच्छिक होना चाहिए, स्थिर नहीं। Iterations शायद स्थिर भी नहीं होना चाहिए। जीसीएम में पहले से ही टैग की गणना में IV शामिल है। हालांकि इसमें वर्जन नंबर नहीं है। आपको पोर्टेबिलिटी के लिए प्रदाता को निर्दिष्ट नहीं करना चाहिए, "सनजेसीई" उन प्लेटफार्मों पर डिफ़ॉल्ट होगा जो इसका समर्थन करते हैं। इस कोड में कोई संदेश स्ट्रिंग हैंडलिंग नहीं है, जो इस विशेष प्रश्न के लिए आवश्यक है ।
मार्टन बॉड्यूज

ठीक है, मैंने इसे थोड़ा और साफ किया encryptStringऔर अनुरोध को जोड़ा और decryptString:)
ट्रिकनर डिक

इसने बहुत अच्छा काम किया; कोड के लिए ty। यह ध्यान दिया जाना चाहिए कि इस कोड को ठीक से काम करने के लिए एपीआई 19 (किट कैट) या उससे ऊपर की आवश्यकता है।
PGMacDesign

3

मैं https: //www.b Councilycastle.org/ जैसी किसी चीज़ का उपयोग करने पर विचार करूंगा। यह एक प्रीबिल्ट लाइब्रेरी है, जो आपको कई सिफर के साथ जो कुछ भी पसंद है उसे एन्क्रिप्ट करने की अनुमति देता है। मैं समझता हूं कि आप केवल स्नूपिंग से बचाना चाहते हैं, लेकिन अगर आप वास्तव में चाहते हैं जानकारी की रक्षा करना चाहते हैं, बेस 64 का उपयोग करना वास्तव में आपकी रक्षा नहीं करेगा।


1
बस सिफर के साथ एक यादृच्छिक क्रिप्टो लाइब्रेरी की सिफारिश करना सवाल का जवाब नहीं है। इसके अलावा, बिल्ड-इन सिफर्स का उपयोग क्यों नहीं करें?
मार्टन बॉडवेज

2

यहां कुछ लिंक दिए गए हैं जिन्हें आप पढ़ सकते हैं कि जावा क्या समर्थन करता है

किसी डेटा स्ट्रीम को एन्क्रिप्ट / डिक्रिप्ट करना।

यह उदाहरण प्रदर्शित करता है कि बड़ी मात्रा में डेटा को एन्क्रिप्ट करने के लिए कैसे (एईएस, ब्लोफिश, आरसी 2, 3 डीईएस आदि जैसे सममित एन्क्रिप्शन एल्गोरिथ्म का उपयोग करके)। डेटा को एन्क्रिप्ट तरीकों में से एक में विखंडन में पारित किया जाता है: EncryptBytes, EncryptString, EncryptBytesENC, या EncryptStringENC। (विधि का नाम इनपुट के प्रकार (स्ट्रिंग या बाइट सरणी) और रिटर्न प्रकार (एन्कोडेड स्ट्रिंग या बाइट सरणी) को इंगित करता है। FirstChunk और LastChunk गुणों का उपयोग यह इंगित करने के लिए किया जाता है कि क्या एक चंक एक स्ट्रीम में पहला, मध्य या अंतिम है या नहीं। एन्क्रिप्ट किया जाना है। डिफ़ॉल्ट रूप से, FirstChunk और LastChunk दोनों समान सत्य हैं - जिसका अर्थ है कि पास किया गया डेटा पूरी राशि है।

JCERefGuide

जावा एन्क्रिप्शन उदाहरण


हां, जावा द्वारा समर्थित क्रिप्टोग्राफी है। एक स्ट्रीम का एन्क्रिप्शन वह नहीं है जो या तो पूछा गया था।
मार्टन बॉड्यूज

2

जैसे कि बहुत से लोगों ने पहले ही बता दिया है, आपको एक मानक साइफ़र का उपयोग करना चाहिए जो कि डीईएस या एईएस की तरह अत्यधिक उपयोग किया जाता है।

एईएस का उपयोग करके आप जावा में स्ट्रिंग को कैसे एन्क्रिप्ट और डिक्रिप्ट कर सकते हैं, इसका एक सरल उदाहरण है ।

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class EncryptorDemo {

    public static String encrypt(String key, String randomVector, String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(randomVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println("encrypted text: "  + Base64.encodeBase64String(encrypted));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String key, String randomVector, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(randomVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] originalText = cipher.doFinal(Base64.decodeBase64(encrypted));
            System.out.println("decrypted text: "  + new String(originalText));
            return new String(originalText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String key = "JavasEncryptDemo"; // 128 bit key
        String randomVector = "RandomJavaVector"; // 16 bytes IV
        decrypt(key, randomVector, encrypt(key, randomVector, "Anything you want to encrypt!"));

    }
}

CBC अब एक सुरक्षित मोड नहीं है। पेडिंग ओरेकल हमलों को गद्दी के लिए असुरक्षित है। इसके अलावा, स्ट्रिंग में कुंजी और संदेशों को संभालना सुरक्षित नहीं है। वे स्ट्रिंग पूल में घूमेंगे और ढेर में दिखाई देंगे
सप्तर्षि बसु

2
टिप्पणी की सराहना करें। यह जावा के एन्क्रिप्ट और डिक्रिप्ट विधियों का एक सरल उदाहरण था जैसा उपयोगकर्ता पूछ रहा था। सवाल कुछ 9 साल पहले पूछा गया था और उसी के आधार पर जवाब दिया गया था। धन्यवाद।
विवेकास्कर

2
हां यह एन्क्रिप्ट / डिक्रिप्ट को शुरू करने का एक सरल तरीका लगता है। मेरे लिए एक आकर्षण की तरह काम किया .... धन्यवाद।
कोडवेपर

0

यहाँ एक कॉपी / पेस्ट समाधान है। मैं @ कॉन्स्टेंटिनो के जवाब को पढ़ने और मतदान करने की भी सलाह देता हूं , हालांकि यह किसी भी कोड को प्रदान नहीं करता है। आरंभीकरण वेक्टर (IV) नमक की तरह है - इसे गुप्त रखने की आवश्यकता नहीं है। मैं GCM के लिए नया हूँ और जाहिरा तौर पर AAD वैकल्पिक है और केवल कुछ विशेष परिस्थितियों में उपयोग किया जाता है। पर्यावरण चर में कुंजी सेट करें SECRET_KEY_BASE। 32 कैरेक्टर का पासवर्ड जनरेट करने के लिए KeePass जैसी किसी चीज़ का इस्तेमाल करें । यह समाधान मेरे रूबी समाधान के बाद तैयार किया गया है।

    public static String encrypt(String s) {
        try {
            byte[] input = s.getBytes("UTF-8");
            String keyString = System.getProperty("SECRET_KEY_BASE", System.getenv("SECRET_KEY_BASE"));
            if (keyString == null || keyString.length() == 0) {
                Logger.error(Utils.class, "encrypt()", "$SECRET_KEY_BASE is not set.");
                return null;
            }
            byte[] keyBytes = keyString.getBytes("UTF-8");
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
            // generate IV
            SecureRandom secureRandom = SecureRandom.getInstanceStrong();
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            byte[] ivBytes = new byte[cipher.getBlockSize()];
            secureRandom.nextBytes(ivBytes);
            GCMParameterSpec gcmSpec = new GCMParameterSpec(96, ivBytes); // 96 bit tag length
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
            // generate AAD
//          byte[] aadBytes = new byte[cipher.getBlockSize()];
//          secureRandom.nextBytes(aadBytes);
//          cipher.updateAAD(aadBytes);
            // encrypt
            byte[] encrypted = cipher.doFinal(input);
            byte[] returnBytes = new byte[ivBytes.length + encrypted.length];
//          byte[] returnBytes = new byte[ivBytes.length + aadBytes.length + encrypted.length];
            System.arraycopy(ivBytes, 0, returnBytes, 0, ivBytes.length);
//          System.arraycopy(aadBytes, 0, returnBytes, ivBytes.length, aadBytes.length);
            System.arraycopy(encrypted, 0, returnBytes, ivBytes.length, encrypted.length);
//          System.arraycopy(encrypted, 0, returnBytes, ivBytes.length+aadBytes.length, encrypted.length);
            String encryptedString = Base64.getEncoder().encodeToString(returnBytes);
            return encryptedString;
        } catch (UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | 
                InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            Logger.error(Utils.class, "encrypt()", "Could not encrypt string: " + e.getMessage());
            return null;
        }
    }

    public static String decrypt(String s) {
        if (s == null || s.length() == 0) return "";
        try {
            byte[] encrypted = Base64.getDecoder().decode(s);
            String keyString = System.getProperty("SECRET_KEY_BASE", System.getenv("SECRET_KEY_BASE"));
            if (keyString == null || keyString.length() == 0) {
                Logger.error(Utils.class, "encrypt()", "$SECRET_KEY_BASE is not set.");
                return null;
            }
            byte[] keyBytes = keyString.getBytes("UTF-8");
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            byte[] ivBytes = new byte[cipher.getBlockSize()];
            System.arraycopy(encrypted, 0, ivBytes, 0, ivBytes.length);
            GCMParameterSpec gcmSpec = new GCMParameterSpec(96, ivBytes);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
//          cipher.updateAAD(encrypted, ivBytes.length, cipher.getBlockSize());
            byte[] decrypted = cipher.doFinal(encrypted, cipher.getBlockSize(), encrypted.length - cipher.getBlockSize());
//          byte[] decrypted = cipher.doFinal(encrypted, cipher.getBlockSize()*2, encrypted.length - cipher.getBlockSize()*2);
            String decryptedString = new String(decrypted, "UTF-8");
            return decryptedString;
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedEncodingException | InvalidKeyException | 
                InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            Logger.error(Utils.class, "decrypt()", "Could not decrypt string: " + e.getMessage());
            return null;
        }
    }

यहाँ एक उदाहरण है:

    String s = "This is a test.";
    String enc = Utils.encrypt(s);
    System.out.println(enc);
    // fQHfYjbD+xAuN5XzH2ojk/EWNeKXUrKRSfx8LU+5dpuKkM/pueCMBjKCZw==
    String dec = Utils.decrypt(enc);
    System.out.println(dec);
    // This is a test.

-4

आप एन्क्रिप्शन / डिक्रिप्शन कोड पीढ़ी जैसे करने के लिए कुछ स्वचालित टूल पर विचार करना चाह सकते हैं। https://www.stringencrypt.com/java-encryption/

यह स्ट्रिंग या फ़ाइल एन्क्रिप्शन के लिए हर बार अलग-अलग एन्क्रिप्शन और डिक्रिप्शन कोड उत्पन्न कर सकता है।

जब आरएसए, एईएस आदि का उपयोग किए बिना तेज स्ट्रिंग एन्क्रिप्शन की बात आती है तो यह बहुत आसान है।

नमूना परिणाम:

// encrypted with https://www.stringencrypt.com (v1.1.0) [Java]
// szTest = "Encryption in Java!"
String szTest = "\u9E3F\uA60F\uAE07\uB61B\uBE1F\uC62B\uCE2D\uD611" +
                "\uDE03\uE5FF\uEEED\uF699\uFE3D\u071C\u0ED2\u1692" +
                "\u1E06\u26AE\u2EDC";

for (int iatwS = 0, qUJQG = 0; iatwS < 19; iatwS++)
{
        qUJQG = szTest.charAt(iatwS);
        qUJQG ++;
        qUJQG = ((qUJQG << 5) | ( (qUJQG & 0xFFFF) >> 11)) & 0xFFFF;
        qUJQG -= iatwS;
        qUJQG = (((qUJQG & 0xFFFF) >> 6) | (qUJQG << 10)) & 0xFFFF;
        qUJQG ^= iatwS;
        qUJQG -= iatwS;
        qUJQG = (((qUJQG & 0xFFFF) >> 3) | (qUJQG << 13)) & 0xFFFF;
        qUJQG ^= 0xFFFF;
        qUJQG ^= 0xB6EC;
        qUJQG = ((qUJQG << 8) | ( (qUJQG & 0xFFFF) >> 8)) & 0xFFFF;
        qUJQG --;
        qUJQG = (((qUJQG & 0xFFFF) >> 5) | (qUJQG << 11)) & 0xFFFF;
        qUJQG ++;
        qUJQG ^= 0xFFFF;
        qUJQG += iatwS;
        szTest = szTest.substring(0, iatwS) + (char)(qUJQG & 0xFFFF) + szTest.substring(iatwS + 1);
}

System.out.println(szTest);

हम अपनी कंपनी में हर समय इसका इस्तेमाल करते हैं।


यह अस्पष्टता के माध्यम से सुरक्षा है और वास्तव में सुरक्षित नहीं है।
क्लो

यह प्रश्न एईएस जैसे वास्तविक आधुनिक क्रिप्टोग्राफ़िक-शक्ति एन्क्रिप्शन के लिए पूछ रहा है, न कि केवल स्टैफ़िक्स निकालने के लिए स्ट्रिंग्स को कठिन बनाने के लिए आक्षेप। यह वर्णों के बीच किसी भी स्थिति को रखने के लिए भी प्रकट नहीं होता है इसलिए इसकी आवृत्ति विश्लेषण के लिए अतिसंवेदनशील है। ( लैटिन वर्णमाला के बजाय UTF-16 कोडपॉइंट्स को छोड़कर (एकल-वर्णानुक्रम प्रतिस्थापन सिफर । लेकिन यदि आप इसे अंग्रेजी ASCII पाठ पर उपयोग करते हैं, तो आपको केवल कुछ अद्वितीय 16-बिट वर्ण मान मिलते हैं, जब तक कि मैं यह गलत नहीं कर रहा हूं)
पीटर कोर्ड्स

-4
String s1="arshad"; 
char[] s2=s1.toCharArray(); 
int s3= s2.length; 

  System.out.println(s3);
 int i=0; 

// for(int j=0;j<s3;j++) 
// System.out.println(s2[j]); 

for(i=0;i<((s3)/2);i++) { 

char z,f=10; 
z=(char) (s2[i] * f); 
s2[i]=s2[(s3-1)-i]; 
s2[(s3-1)-i]=z; 

String b=new String(s2);

 print(b);  }

औपचारिक रूप से यह डेटा को अपठनीय प्रारूप में एन्क्रिप्ट करता है। एक ही कोड का उपयोग डिक्रिप्ट करने के लिए। और s [i] * f को s [I] / f में बदलें।
अरशद शैक

यह अस्पष्टता के माध्यम से सुरक्षा है और वास्तव में सुरक्षित नहीं है।
च्लोए

-5
public static String encryptParams(String myTextInput) {

        String myKey = "40674244454045cb9a70040a30e1c007";
        String myVector = "@1B2c3D4e5F6g7H8";

        String encData = "";

        try{
            JavaEncryprtionUtil encUtil = new JavaEncryprtionUtil();
            encData = Base64.encodeToString(encUtil.encrypt(myTextInput.getBytes("UTF-8"), myKey.getBytes("UTF-8"), myVector.getBytes("UTF-8")),Base64.DEFAULT);
            System.out.println(encData);
        }catch(NoSuchAlgorithmException ex){
            ex.printStackTrace();
        }catch(NoSuchPaddingException ex){
            ex.printStackTrace();
        }catch(InvalidKeyException ex){
            ex.printStackTrace();
        }catch(InvalidAlgorithmParameterException ex){
            ex.printStackTrace();
        }catch(IllegalBlockSizeException ex){
            ex.printStackTrace();
        }catch(BadPaddingException ex){
            ex.printStackTrace();
        }catch(UnsupportedEncodingException ex){
            ex.printStackTrace();
        }

        return encData;
    }

1
JavaEncryprtionUtil JDK API का हिस्सा है? यदि आपको पुस्तकालय का नाम नहीं बताना चाहिए।
फ़र्मेटस लिटिल स्टूडेंट

4
उस वर्ग को नहीं खोज सकते। लगता है जैसे जवाब बना है।
james.garriss
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.