2012-03-11 18 views
5

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

// encode the SecretKeySpec 
private byte[] EncryptSecretKey() 
{ 
    Cipher cipher = null; 
    byte[] key = null; 

    try 
    { 
     cipher = Cipher.getInstance("RSA/ECB/NOPADDING"); 
     // contact.getPublicKey returns a public key of type Key 
     cipher.init(Cipher.ENCRYPT_MODE, contact.getPublicKey()); 
     // skey is the SecretKey used to encrypt the AES data 
     key = cipher.doFinal(skey.getEncoded()); 
    } 
    catch(Exception e) 
    { 
     System.out.println ("exception encoding key: " + e.getMessage()); 
     e.printStackTrace(); 
    } 
    return key; 
} 

मैं तो रिसीवर के लिए महत्वपूर्ण मूल्य को लिखने, और इतना है कि यह डिक्रिप्ट:

private SecretKey decryptAESKey(byte[] data) 
{ 
    SecretKey key = null; 
    PrivateKey privKey = null; 
    Cipher cipher = null; 

    System.out.println ("Data as hex: " + utility.asHex(data)); 
    System.out.println ("data length: " + data.length); 
    try 
    { 
     // assume this loads our private key 
     privKey = (PrivateKey)utility.loadLocalKey("private.key", false); 

     cipher = Cipher.getInstance("RSA/ECB/NOPADDING"); 
     cipher.init(Cipher.DECRYPT_MODE, privKey); 
     key = new SecretKeySpec(cipher.doFinal(data), "AES"); 

     System.out.println ("Key decrypted, length is " + key.getEncoded().length); 
     System.out.println ("data: " + utility.asHex(key.getEncoded())); 
    } 
    catch(Exception e) 
    { 
     System.out.println ("exception decrypting the aes key: " + e.getMessage()); 
     e.printStackTrace(); 
     return null; 
    } 

    return key; 
} 

कंसोल में , दूसरी तरफ, मैं इस आउटपुट के रूप में मिलती है: इसके अलावा

read_bytes for key: 16 
data length: 16 
Data as hex: <hex string> 
Key decrypted, length is 256 
java.security.InvalidKeyException: Invalid AES key length: 256 bytes 

, अगर मैं आकार 16 वर्ष की एक बाइट सरणी बना सकते हैं और इसे में cipher.doFinal (डेटा) उत्पादन में कहें, सरणी प्रतीत होता है 256 का आकार बदलकर बाइट्स (.leng वें कहते हैं, कम से कम)। यह क्यों होगा, और आगे, मैं गलत तरीके से क्या कर रहा हूं?

संपादित
मैं इस हल, और मैं इस मुद्दे के मामले में किसी को इस में चलाता पोस्ट था सोचा। समस्या, यह पता चला, आरएसए/ईसीबी/एनओपीएडीडीडी था। कुछ अजीब कारणों से जब मैंने इसे क्लाइंट में स्थानांतरित कर दिया तो यह गुप्तकी के निर्माण को खराब कर रहा था। यह हो सकता है कैसे मैं keypairs पैदा कर रहा हूँ (मैं getInstance (उस के लिए "आरएसए") का उपयोग कर रहा हूँ) के साथ कुछ है, लेकिन मैं पूरी तरह यकीन नहीं है।

+1

हाय टोपी, पोस्ट कृपया अपने ** पूरा ** बजाय अपने प्रश्न में यह संपादन के एक जवाब के रूप जवाब (आप हमें बताएं कि क्या समस्या थी, उत्तर नहीं)। फिर आप थोड़ी देर बाद अपना जवाब स्वीकार कर सकते हैं। या मेरा स्वीकार करें, जो बताता है कि आपको आरएसए/ईसीबी/नोपैडिंग के बजाय '" आरएसए/ईसीबी/पीकेसीएस 1 पैडिंग "का उपयोग क्यों करना चाहिए ... –

+0

ध्यान दें कि जब आप एक बनाते हैं तो आपको अखंडता संरक्षण (उदाहरण के लिए एक हस्ताक्षर) का उपयोग करना चाहिए ऑनलाइन प्रोटोकॉल जो एन्क्रिप्शन करता है। यहां तक ​​कि आरएसए एन्क्रिप्टीम भी उदाहरण के लिए स्वीकार्य हो सकता है पैडिंग ओरेकल हमले। अखंडता सुरक्षा नहीं है एक आम गलती है, हालांकि यदि आप पीकेसीएस # 1 v1.5 ("आरएसए/ईसीबी/पीकेसीएस 1 पैडिंग" ') द्वारा निहित हैं तो यह समस्या सीमित है। –

+0

एक साइडेनोट के रूप में, ईसीबी शायद ही कभी एक अवरोधक के लिए एक अच्छा तरीका है। – CodesInChaos

उत्तर

4

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

private byte[] EncryptSecretKey() 
{ 
    Cipher cipher = null; 
    byte[] key = null; 

    try 
    { 
     // initialize the cipher with the user's public key 
     cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, contact.getPublicKey()); 
     key = cipher.doFinal(skey.getEncoded()); 
    } 
    catch(Exception e) 
    { 
     System.out.println ("exception encoding key: " + e.getMessage()); 
     e.printStackTrace(); 
    } 
    return key; 
} 

डिक्रिप्शन:

private SecretKey decryptAESKey(byte[] data) 
{ 
    SecretKey key = null; 
    PrivateKey privKey = null; 
    Cipher cipher = null; 

    try 
    { 
     // this is OUR private key 
     privKey = (PrivateKey)utility.loadLocalKey(
           ConfigFrame.privateKeyLocation, false); 

     // initialize the cipher... 
     cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, privKey); 

     // generate the aes key! 
     key = new SecretKeySpec (cipher.doFinal(data), "AES"); 
    } 
    catch(Exception e) 
    { 
     System.out.println ("exception decrypting the aes key: " 
               + e.getMessage()); 
     return null; 
    } 

    return key; 
} 
+1

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

+0

मदद/स्पष्टीकरण के लिए धन्यवाद, उल्लू! – hat

0

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

Comment Source

प्राप्त करने के लिए सही कुंजी आकार आप कुंजी (SHA) है, जो आप एक निश्चित उत्पादन आकार दे देंगे पर एक HashAlgorithm उपयोग कर सकते हैं। अन्यथा आप पहले 16 बाइट्स को कुंजी के रूप में उपयोग कर सकते हैं और बाकी को अनदेखा कर सकते हैं? सौभाग्य।

+0

आप सही हैं, ऐसा लगता है कि यह कुंजी लंबाई (2048 बिट कुंजी, मेरे मामले में) के लिए पैडिंग की तरह दिखता है। मुझे जावा 7 के सिफर ऑब्जेक्ट के साथ एनओपीएडीडीडी के लिए समर्थन भी नहीं दिख रहा है, लेकिन यह मुझ पर अपवाद नहीं फेंक रहा है। मुझे लगता है कि मैं आवश्यक वास्तविक डेटा को पार्सिंग की जांच करूँगा। धन्यवाद! – hat

4

तुम बस "कच्चे" आरएसए उपयोग नहीं कर सकते किसी भी गद्दी के बिना डेटा एन्क्रिप्ट करने के। केवल सुरक्षा कारणों से, आपको किसी प्रकार की पैडिंग योजना की आवश्यकता है। आम तौर पर "आरएसए/ईसीबी/पीकेसीएस 1 पैडिंग" का उपयोग किया जाता है। यह कुंजी आकार से कम 11 बाइट तक डेटा एन्क्रिप्ट कर सकता है। यह सुनिश्चित करता है कि डेटा मॉड्यूलस में फिट बैठता है, और यह सुनिश्चित करने के लिए यादृच्छिक डेटा के कम से कम 8 बाइट जोड़ता है कि एन्क्रिप्ट करना उदा। दो बार "हां" शब्द का परिणाम दो समान सिफर ग्रंथों में नहीं होता है। अंत में, यह सुनिश्चित करता है कि आप एन्क्रिप्टेड डेटा के ऑक्टेट्स में आकार का पता लगा सकें, ताकि आप एईएस कुंजी बनाने वाले 16, 24 या 32 बाइट्स को एन्क्रिप्ट कर सकें।

+1

बेशक, आप उत्तराधिकारी, ओएईपी का भी उपयोग कर सकते हैं, लेकिन यह वास्तव में आवश्यक नहीं है और डिफ़ॉल्ट पीकेसीएस # 1 v1.5 पैडिंग योजना से कम संगत हो सकता है। –

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