2011-12-29 21 views
36

मैं डेटाबेस में पासवर्ड सुरक्षित रूप से स्टोर करने की कोशिश कर रहा हूं और इसके लिए मैंने पीबीकेडीएफ 2 फ़ंक्शन का उपयोग करके उत्पन्न हैश को स्टोर करना चुना है। मैं उछाल वाली महल लाइब्रेरी का उपयोग करके ऐसा करना चाहता हूं लेकिन मुझे नहीं पता कि मैं इसे जेसीई इंटरफ़ेस का उपयोग करके क्यों काम नहीं कर सकता ... समस्या यह है कि हैश को 3 अलग-अलग मोड में उत्पन्न करना:
1. का उपयोग करना PBKDF2WithHmacSHA1 गुप्त कुंजी उछाल वाले महल एपीआई सीधे
3. JCE
के माध्यम से उछाल वाले महल का उपयोग कर परिणाम 2 अलग-अलग मान में उपयोग करते हुए सूरज
2. द्वारा प्रदान कारखाना: एक पहले दो और तीसरे के लिए एक के लिए आम। मुझे पता है कि PBKDF2 HMAC SHA1 का उपयोग कर तो यह है कि मैं क्यों एल्गोरिथ्म के रूप में पिछले विधि "PBEWITHHMACSHA1" जो मैं उछाल वाले महल जावा डॉक्स से ले लिया में चुना है कार्यान्वित किया जाता हैजावा में बाउंसीकैसल के साथ पीबीकेडीएफ 2

//Mode 1 

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    KeySpec keyspec = new PBEKeySpec("password".toCharArray(), salt, 1000, 128); 
    Key key = factory.generateSecret(keyspec); 
    System.out.println(key.getClass().getName()); 
    System.out.println(Arrays.toString(key.getEncoded())); 

    //Mode 2 

    PBEParametersGenerator generator = new PKCS5S2ParametersGenerator(); 
    generator.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(("password").toCharArray()), salt, 1000); 
    KeyParameter params = (KeyParameter)generator.generateDerivedParameters(128); 
    System.out.println(Arrays.toString(params.getKey())); 

    //Mode 3 

    SecretKeyFactory factorybc = SecretKeyFactory.getInstance("PBEWITHHMACSHA1", "BC"); 
    KeySpec keyspecbc = new PBEKeySpec("password".toCharArray(), salt, 1000, 128); 
    Key keybc = factorybc.generateSecret(keyspecbc); 
    System.out.println(keybc.getClass().getName()); 
    System.out.println(Arrays.toString(keybc.getEncoded())); 
    System.out.println(keybc.getAlgorithm()); 

:

यहाँ मेरी कोड है ।

com.sun.crypto.provider.SunJCE_ae 
[-53, 29, 113, -110, -25, 76, 115, -127, -64, 74, -63, 102, 75, 81, -21, 74] 
[-53, 29, 113, -110, -25, 76, 115, -127, -64, 74, -63, 102, 75, 81, -21, 74] 
org.bouncycastle.jce.provider.JCEPBEKey 
[14, -47, -87, -16, -117, -31, 91, -121, 90, -68, -82, -31, -27, 5, -93, -67, 30, -34, -64, -40] 
PBEwithHmacSHA 

कोई भी विचार:

उत्पादन पीछा कर रहा है?

+0

के संगत है मुझे यकीन है कि क्या "मोड 3" कर रही है नहीं कर रहा हूँ, लेकिन मैं इसे उपेक्षा होगी। यह आउटपुट 160 बिट्स है, 128 नहीं, जैसा आपने अनुरोध किया था। 160 बिट्स एसएचए -1 हैश का आकार है। पोर्टेबिलिटी के लिए, मैं "मोड 1." के साथ रहना चाहता हूं। – erickson

+0

मैं एरिक्सन से सहमत हूं - क्या आपके पास "मोड 3" का उपयोग करने के लिए वास्तविक आवश्यकता है या पासवर्ड को सुरक्षित रूप से संग्रहीत करने के लिए "मोड 1" स्वीकार्य होगा? रास्ते में अपने पहले प्रश्न के लिए अच्छा विस्तृत प्रश्न। –

+1

वास्तव में कोई ज़रूरत नहीं है। मैं बस यह समझने की कोशिश कर रहा हूं कि बाउंसीकास्टल से PBEWITHHMACSHA1 क्यों एक ही काम नहीं करता है। और मैं सहमत हूं, पोर्टेबिलिटी मुद्दों के कारण मैं दूसरी विधि का चयन नहीं करूंगा। –

उत्तर

28

संक्षेप में, अंतर का कारण यह है कि मोड # 1 और # 2 में पीबीकेडीएफ 2 एल्गोरिदम पुनरावृत्ति कुंजी पीढ़ी के लिए पीकेसीएस # 5 वी 2 योजना 2 (पीकेसीएस 5 एस 2) का उपयोग करता है, लेकिन मोड # 3 में "PBEWITHHMACSHA1" के लिए BouncyCastle प्रदाता इसके बजाए पीकेसीएस # 12 वी 1 (पीकेसीएस 12) एल्गोरिदम का उपयोग करता है। ये पूरी तरह से अलग-अलग कुंजी-पीढ़ी वाले एल्गोरिदम हैं, इसलिए आपको अलग-अलग परिणाम मिलते हैं।

इस बारे में अधिक जानकारी क्यों है और आप विभिन्न आकार के परिणाम क्यों प्राप्त करते हैं नीचे बताया गया है।

सबसे पहले, जब आप एक जेसीई कीस्पेक बना रहे हैं, तो मुख्य तरंगदैर्ध्य पैरामीटर केवल प्रदाता को "वरीयता" व्यक्त करता है जो आप चाहते हैं कि आप किस महत्वपूर्ण आकार को चाहते हैं। the API docs से:

नोट: यह चर-कुंजी-आकार सिफर के लिए मुख्य लंबाई पर वरीयता को इंगित करने के लिए उपयोग किया जाता है। वास्तविक कुंजी आकार प्रत्येक प्रदाता के कार्यान्वयन पर निर्भर करता है।

Bouncy कैसल प्रदाताओं इस पैरामीटर का सम्मान करना, the source of JCEPBEKey से पहचानने दिखाई नहीं देते हैं, तो आप एक 160 बिट कुंजी किसी भी ईसा पूर्व प्रदाता जो SHA-1 का उपयोग करता है जब JCE एपीआई का उपयोग कर से वापस पाने के लिए उम्मीद करनी चाहिए।

आप प्रोग्राम के रूप में अपने परीक्षण कोड में लौटे keybc चर पर getKeySize() विधि तक पहुंच कर इस बात की पुष्टि कर सकते हैं: अब

Key keybc = factorybc.generateSecret(keyspecbc); 
// ... 
Method getKeySize = JCEPBEKey.class.getDeclaredMethod("getKeySize"); 
getKeySize.setAccessible(true); 
System.out.println(getKeySize.invoke(keybc)); // prints '160' 

, समझने के लिए "PBEWITHHMACSHA1" प्रदाता से मेल खाती है, तो आप में निम्नलिखित पा सकते हैं the source for BouncyCastleProvider:

put("SecretKeyFactory.PBEWITHHMACSHA1", 
    "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBEWithSHA"); 

और JCESecretKeyFactory.PBEWithSHA के कार्यान्वयन इस तरह दिखता है:

+०१२३५१६४१०
public static class PBEWithSHA 
    extends PBEKeyFactory 
{ 
    public PBEWithSHA() 
    { 
     super("PBEwithHmacSHA", null, false, PKCS12, SHA1, 160, 0); 
    } 
} 

आप ऊपर देख सकते हैं कि यह मुख्य कारखाना पुन: सक्रिय पीढ़ी के लिए पीकेसीएस # 12 v1 (PKCS12) एल्गोरिदम का उपयोग करता है। लेकिन पीबीकेडीएफ 2 एल्गोरिदम जिसे आप पासवर्ड हैशिंग के लिए उपयोग करना चाहते हैं, इसके बजाय पीकेसीएस # 5 वी 2 योजना 2 (PKCS5S2) का उपयोग करता है। यही कारण है कि आप अलग-अलग परिणाम प्राप्त कर रहे हैं।

मैं BouncyCastleProvider में पंजीकृत JCE प्रदाताओं पर एक संक्षिप्त दृष्टि थी, लेकिन किसी भी कुंजी पीढ़ी एल्गोरिदम कि PKCS5S2 इस्तेमाल किया सब पर, अकेले एक जो भी HMAC-SHA-1 के साथ इसे इस्तेमाल करता है चलो देखते हैं नहीं कर सका।

तो मुझे लगता है कि आप या तो सूर्य कार्यान्वयन का उपयोग (मोड # 1 ऊपर) और अन्य JVMs पर पोर्टेबिलिटी खोने, या सीधे Bouncy कैसल वर्गों का उपयोग करना (मोड # 2 ऊपर) और रनटाइम पर ईसा पूर्व पुस्तकालय की आवश्यकता होती है के साथ फंस रहे हैं ।

किसी भी तरह से, आपको शायद 160-बिट कुंजी पर स्विच करना चाहिए, इसलिए आप जेनरेट किए गए SHA-1 हैश को अनावश्यक रूप से छोटा नहीं कर रहे हैं।

2

मुझे बीसी क्रिप्टो-केवल विधि (वास्तव में बीसी के सीएमएस पैकेज से) मिली जो यूटीएफ -8 आधारित पासवर्ड एन्कोडिंग का उत्पादन करने के लिए काम करता है। इस तरह से मैं KDF उत्पादन उत्पन्न कर सकते हैं जो

http://packages.python.org/passlib/lib/passlib.hash.cta_pbkdf2_sha1.html#passlib.hash.cta_pbkdf2_sha1

private byte[] calculatePasswordDigest(char[] pass, byte[] salt, int iterations) 
    throws PasswordProtectionException 
{ 
    try 
    { 
     /* JCE Version (does not work as BC uses PKCS12 encoding) 
     SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWITHHMACSHA1","BC"); 
     PBEKeySpec ks = new PBEKeySpec(pass, salt, iterations,160); 
     SecretKey digest = kf.generateSecret(ks); 
     return digest.getEncoded(); 
     */ 
     PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); 
     gen.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(pass), salt, iterations); 
     byte[] derivedKey = ((KeyParameter)gen.generateDerivedParameters(160)).getKey(); 
     return derivedKey; 
    } 
    catch(Exception e) 
    { 
     LOG.error("Failed to strengthen the password with PBKDF2.",e); 
     throw new PasswordProtectionException(); 
    } 
} 
संबंधित मुद्दे