2013-01-02 12 views
5

की init पर एक InvalidKeyException फेंक करता है ऐसा क्यों कामयाब होने की init:क्यों मेरी एईएस सिफर DECRYPT_MODE

Cipher AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
AESCipher.init(Cipher.ENCRYPT_MODE, secretKey, secRandom); 

जबकि इस विफल रहता है:

Cipher AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
AESCipher.init(Cipher.DECRYPT_MODE, secretKey, secRandom); 

धागा "मुख्य" जावा में एक अपवाद फेंकने। security.InvalidKeyException: एक यादृच्छिक सेंट के साथ पैरामीटर लापता

secretKey एक Keygenerator द्वारा उत्पन्न होता है, और SecureRandom.getInstance ("SHA1PRNG") द्वारा secureRandom एटिक बीज सेट।

धन्यवाद

+1

आप डिक्रिप्शन ऑपरेशन के लिए आरएनजी क्यों पास करते हैं? मुझे लगता है कि आरएनजी का उपयोग चतुर्थ उत्पन्न करने के लिए किया जाता है, इसलिए डिक्रिप्शन के लिए आपको शायद चतुर्थ में प्रवेश करना होगा और आरएनजी नहीं। – CodesInChaos

+0

धन्यवाद। तो init को पहली जगह में एक secRandom क्यों मिलता है? सेकेंडैंडम से पहले कुछ बाइट प्राप्त करने का सही तरीका है, उन्हें एक चतुर्थ के रूप में सहेजें और फिर उन्हें एक नया IvParameterSpec का उपयोग करने के रूप में उपयोग करें? बाद में चतुर्थई को उसी तरह से डिक्रिप्शन पर पास कर दिया गया? – user54000

+2

यह शायद आरएनजी लेता है ताकि यह आपको इसके साथ परेशान करने के बजाय IV IV बना सके। लेकिन मैं जावा क्रिप्टो एपीआई से परिचित नहीं हूं। – CodesInChaos

उत्तर

5

के रूप में सही ढंग से CodeInChaos द्वारा अनुमान लगाया, SecureRandom उदाहरण एक यादृच्छिक चतुर्थ प्राप्त करने के लिए जब AESCipher उदाहरण Cipher.ENCRYPT_MODE साथ बनाई गई है प्रयोग किया जाता है। हालांकि, आप डिक्रिप्ट मोड में एक सिफर उदाहरण बनाते समय इसे पैरामीटर के रूप में आपूर्ति करते हैं। यह छोटा व्यर्थ कोड खंड एक उदाहरण दिखाता है।

public static void main(String[] args) throws Exception { 
    SecureRandom secRandom = SecureRandom.getInstance("SHA1PRNG"); 
    KeyGenerator kg = KeyGenerator.getInstance("AES"); 
    kg.init(128, secRandom); 
    Key secretKey = kg.generateKey(); 
    Cipher AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    AESCipher.init(Cipher.ENCRYPT_MODE, secretKey, secRandom); 
    IvParameterSpec iv = new IvParameterSpec(AESCipher.getIV()); 
    AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    AESCipher.init(Cipher.DECRYPT_MODE, secretKey,iv, secRandom); 
} 

इसके अलावा, आपके दावा है कि आप एक स्थिर बीज के साथ अपने SecureRandom उदाहरण आरंभ कर रहे हैं उस वर्ग के एक गलतफहमी सुझाव देते हैं। SecureRandom यह गारंटी नहीं देता है कि जब आप एक ही बीज प्रदान करते हैं तो आपको वही आउटपुट मिल जाएगा। यदि आप Javadocs पर ध्यान से देखते हैं तो आप देखेंगे कि यदि संभव हो तो यह अन्य स्रोतों से कुछ वास्तविक एन्ट्रॉपी प्रदान करने का प्रयास करता है।

संपादित करें 1:

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

+0

एम, यह एक ओह है, मुझे लगता है कि, जावा के कार्यान्वयन के दौरान "SHA1PRNG" 'कार्यान्वयन एक ही बीज को खिलाया जाता है, * यदि बीज यादृच्छिक डेटा * को पुनर्प्राप्त करने वाली किसी भी विधि को कॉल करने से पहले सेट किया गया है, तो देखें [यहां] http://stackoverflow.com/questions/13923247/does-the-sha1prng-algorithm-for-securerandom-use-dev-random-for-entropy) और ['SecureRandom'] के JavaDoc (http: // docs .oracle.com/javase/7/docs/api/java/security/SecureRandom.html) वर्ग –

+0

ध्यान दें कि कुंजी उत्पन्न करने के लिए इस विधि का उपयोग करना बेहद मूर्ख है। आउटपुट को स्थिर कुंजी सामग्री से चाबियाँ या चतुर्थ बनाने के लिए इसका उपयोग करने के लिए पर्याप्त रूप से निर्दिष्ट नहीं किया गया है। तो उस अर्थ में टिप्पणी सही है; ** स्थिर कुंजी सामग्री ** से चाबियाँ या IV उत्पन्न करने के लिए 'SecureRandom' का उपयोग न करें। –

2

बस init method with SecureRandom की JavaDoc कि आप आवेदन कर रहे पढ़ें:

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

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

+1

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

+0

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

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