2008-12-16 11 views
6

मैं जावा के साथ पासफ्रेज़-आधारित एन्क्रिप्शन को सीखने का प्रयास कर रहा हूं। मुझे ऑनलाइन कई उदाहरण मिल रहे हैं, लेकिन स्टैक ओवरफ़्लो पर कोई भी नहीं (अभी तक)। मेरे लिए विशेष रूप से एल्गोरिदम चयन के संबंध में उदाहरण पर उदाहरण थोड़ा सा प्रकाश है। ऐसा लगता है कि एल्गोरिदम का उपयोग करने के लिए कहने के लिए बहुत सारे गुजरने वाले तार हैं, लेकिन स्ट्रिंग्स कहां से आए हैं और उनका क्या मतलब है, इस बारे में बहुत कम दस्तावेज। और ऐसा लगता है कि अलग-अलग एल्गोरिदम को KeySpec क्लास के विभिन्न कार्यान्वयन की आवश्यकता हो सकती है, इसलिए मुझे यकीन नहीं है कि एल्गोरिदम PBEKeySpec क्लास का उपयोग कर सकते हैं, जिसे मैं देख रहा हूं। इसके अलावा, उदाहरण सभी एक छोटी तारीख से प्रतीत होते हैं, कई लोगों को आपको एक पुराने क्रिप्टोग्राफी पैकेज प्राप्त करने की आवश्यकता होती है जो कि जेडीके का हिस्सा नहीं होता है, या यहां तक ​​कि एक तृतीय पक्ष कार्यान्वयन भी नहीं होता है।जावा पासफ़्रेज़ एन्क्रिप्शन

क्या कोई एन्क्रिप्ट (स्ट्रिंग डेटा, स्ट्रिंग पासफ्रेज) और डिक्रिप्ट (बाइट [] डेटा, स्ट्रिंग पासफ्रेज़) को लागू करने के लिए मुझे क्या करना है, इसके लिए सीधा परिचय प्रदान कर सकता है?

+0

क्या आप पासवर्ड/वाक्यांश हैशिंग, या डेटा एन्क्रिप्शन (जैसे पीजीपी या एसएसएल पासफ्रेज़ के साथ) करना चाहते हैं? शीर्षक पूर्व के लिए थोड़ा भ्रामक है, लेकिन मुझे लगता है कि आप बाद वाले करना चाहते हैं ... – JeeBee

+0

मैं पूर्व करना चाहता हूं, लेकिन मुझे नहीं पता कि आप इसे क्यों बुझ रहे हैं। मैं इसे उलटा होना चाहता हूँ। पासफ्रेज़ के साथ डीईएस या एईएस एन्क्रिप्शन सोचें। सममित एन्क्रिप्शन, जैसा कि आप वर्णन कर रहे हैं assimetric नहीं। – skiphoppy

+0

आपको पासफ्रेज़ रिवर्सिबल की एन्क्रिप्शन क्यों करने की आवश्यकता है? यह आमतौर पर वांछनीय नहीं है। – JeeBee

उत्तर

11

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

ऐसा कहकर, मुझे लगता है कि सूर्य का Java Cryptography Architecture (JCA) Reference Guide एक अच्छा प्रारंभिक बिंदु है। पासवर्ड-आधारित एन्क्रिप्शन (पीबीई) को चित्रित करने वाले code example के साथ देखें।

बीटीडब्ल्यू, मानक जेआरई पीबीई के लिए केवल कुछ विकल्प प्रदान करता है ("PBEWithMD5AndDES" उनमें से एक है)। अधिक विकल्पों के लिए, आपको "मजबूत एन्क्रिप्शन पैक" या कुछ तृतीय-पक्ष प्रदाता की आवश्यकता होगी जैसे Bouncy Castle। एक अन्य विकल्प जेआरई में उपलब्ध हैश और सिफर एल्गोरिदम का उपयोग करके अपने स्वयं के पीबीई को लागू करना होगा। आप पीएचई को एसएचए -256 और एईएस-128 के साथ इस तरह लागू कर सकते हैं (sample encrypt/decrypt methods)।

संक्षेप में, PBE के लिए एन्क्रिप्ट विधि निम्न चरणों को शामिल कर सकते हैं:

  1. उपयोगकर्ता से पासवर्ड और क्लियर हो जाओ, और उन्हें बाइट सरणियों में बदलने का।
  2. एक सुरक्षित यादृच्छिक salt उत्पन्न करें।
  3. पासवर्ड में नमक संलग्न करें और इसके क्रिप्टोग्राफिक hash की गणना करें। इसे कई बार दोहराएं।
  4. परिणामस्वरूप हैश का उपयोग करके क्लीयरटेक्स्ट को initialization vector और/या गुप्त key के रूप में एन्क्रिप्ट करें।
  5. नमक और परिणामी ciphertext बचाओ।
2

आपको एक एन्क्रिप्शन लाइब्रेरी की आवश्यकता है, जो आपको बताएगा कि इसे कैसे सेट अप करें।
मुझे bouncycastle.org से सामान पसंद है। आप उन्हें कैसे देख सकते हैं here डीईएस 5.1 उदाहरण में संदर्भित है, जो उनके द्वारा ऑफ़र किए गए एन्क्रिप्शन में से एक है। वास्तविक स्ट्रिंग का अर्थ क्या है, प्रदाता पर निर्भर करेगा। अनिवार्य रूप से आप पुस्तकालय लोड करते हैं।

Security.addProvider(new BouncyCastleProvider()); 

और फिर केवल JCE इंटरफेस का उपयोग करने के लिए जो चाहें करें:

keyGen = KeyGenerator.getInstance("DES", "BC"); 

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

1

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

फिर आप उस कुंजी का उपयोग किसी भी सममित एल्गोरिदम के साथ कर सकते हैं - जैसे कि 3 डीईएस-सीबीसी या एईएस-सीबीसी (डीईएस इन दिनों अप्रचलित माना जाता है)।

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

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

तुम भी डिजाइन कि अन्य लोगों को किया है पर दिखाई दे सकता है, वहाँ IETF पर बहुत सारे है, जैसे हैं: http://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha1-00

0

आप पदबंध डिक्रिप्ट करने के लिए, लेकिन सिर्फ उत्पन्न एक एन्क्रिप्शन एक पासवर्ड/पदबंध के आधार पर कुंजी की जरूरत नहीं है, तो आप PKCS#5 standard लागू कर सकते हैं, JCE सिफर और MessageDigest वर्गों का उपयोग करना।

4

पासवर्ड से कुंजी उत्पन्न करने के लिए RFC2898 का उपयोग करें। यह जेआरई या जेसीई में शामिल नहीं है, जहां तक ​​मुझे पता है, लेकिन यह जे 2 ईई सर्वर जैसे JBoss, ओरेकल, और WebSphere में शामिल है। इसे .NET बेस क्लास लाइब्रेरी (Rfc2898DeriveBytes) में भी शामिल किया गया है।

जावा में कुछ एलजीपीएल कार्यान्वयन हैं, लेकिन एक त्वरित रूप से this one जटिल पर थोड़ा सा दिखता है। एक अच्छा javascript version भी है। (मैंने a modified version of that one का उत्पादन किया और इसे विंडोज स्क्रिप्ट घटक के रूप में पैक किया)

उपयुक्त लाइसेंस के साथ एक अच्छा कार्यान्वयन की कमी, मैंने मैटियास गार्टनर से कुछ कोड पैक किए। यह कोड पूरी तरह से है। समझने में आसान, सरल, सरल। इसे MS Public License के तहत लाइसेंस प्राप्त है।

// PBKDF2.java 
// ------------------------------------------------------------------ 
// 
// RFC2898 PBKDF2 in Java. The RFC2898 defines a standard algorithm for 
// deriving key bytes from a text password. This is sometimes 
// abbreviated "PBKDF2", for Password-based key derivation function #2. 
// 
// There's no RFC2898-compliant PBKDF2 function in the JRE, as far as I 
// know, but it is available in many J2EE runtimes, including those from 
// JBoss, IBM, and Oracle. 
// 
// It's fairly simple to implement, so here it is. 
// 
// Created Sun Aug 09 01:06:57 2009 
// 
// last saved: 
// Time-stamp: <2009-August-09 02:19:50> 
// ------------------------------------------------------------------ 
// 
// code thanks to Matthias Gartner 
// 
// ------------------------------------------------------------------ 

package cheeso.examples; 


import java.security.NoSuchAlgorithmException; 
import java.security.InvalidKeyException; 
import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 


public class PBKDF2 
{ 
    public static byte[] deriveKey(byte[] password, byte[] salt, int iterationCount, int dkLen) 
     throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException 
    { 
     SecretKeySpec keyspec = new SecretKeySpec(password, "HmacSHA1"); 
     Mac prf = Mac.getInstance("HmacSHA1"); 
     prf.init(keyspec); 

     // Note: hLen, dkLen, l, r, T, F, etc. are horrible names for 
     //  variables and functions in this day and age, but they 
     //  reflect the terse symbols used in RFC 2898 to describe 
     //  the PBKDF2 algorithm, which improves validation of the 
     //  code vs. the RFC. 
     // 
     // dklen is expressed in bytes. (16 for a 128-bit key) 

     int hLen = prf.getMacLength(); // 20 for SHA1 
     int l = Math.max(dkLen, hLen); // 1 for 128bit (16-byte) keys 
     int r = dkLen - (l-1)*hLen;  // 16 for 128bit (16-byte) keys 
     byte T[] = new byte[l * hLen]; 
     int ti_offset = 0; 
     for (int i = 1; i <= l; i++) { 
      F(T, ti_offset, prf, salt, iterationCount, i); 
      ti_offset += hLen; 
     } 

     if (r < hLen) { 
      // Incomplete last block 
      byte DK[] = new byte[dkLen]; 
      System.arraycopy(T, 0, DK, 0, dkLen); 
      return DK; 
     } 
     return T; 
    } 


    private static void F(byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex) { 
     final int hLen = prf.getMacLength(); 
     byte U_r[] = new byte[ hLen ]; 
     // U0 = S || INT (i); 
     byte U_i[] = new byte[S.length + 4]; 
     System.arraycopy(S, 0, U_i, 0, S.length); 
     INT(U_i, S.length, blockIndex); 
     for(int i = 0; i < c; i++) { 
      U_i = prf.doFinal(U_i); 
      xor(U_r, U_i); 
     } 

     System.arraycopy(U_r, 0, dest, offset, hLen); 
    } 

    private static void xor(byte[] dest, byte[] src) { 
     for(int i = 0; i < dest.length; i++) { 
      dest[i] ^= src[i]; 
     } 
    } 

    private static void INT(byte[] dest, int offset, int i) { 
     dest[offset + 0] = (byte) (i/(256 * 256 * 256)); 
     dest[offset + 1] = (byte) (i/(256 * 256)); 
     dest[offset + 2] = (byte) (i/(256)); 
     dest[offset + 3] = (byte) (i); 
    } 

    // ctor 
    private PBKDF2() {} 

} 
+1

बहुत बहुत धन्यवाद। मैंने सत्यापित किया कि मेरे परीक्षण मामलों में यह कोड जेडीके 6 अंतर्निर्मित एल्गोरिदम के समान परिणाम उत्पन्न करता है जिसे पीबीकेडीएफ 2 विथ एचएमएसीएचएच 1 नाम दिया गया है। –

+1

लाइन 'पूर्णांक एल = Math.max (dkLen, hLen)' , अधिकतम, लेकिन विभाजन की छत caculate नहीं करना चाहिए तो 'पूर्णांक एल = ((dkLen - 1)/hLen) + 1; //> = ceil (dkLen/hLen), == dkLen => 1' यह 16 बाइट कुंजी के लिए 20 के कारक द्वारा गणना को तेज करेगा। – Joqn

3

चेसो के ऊपर बहुत उपयोगी उत्तर में, खराब प्रदर्शन बग है।

लाइन

int l = Math.max(dkLen, hLen) 

अधिकतम caculate नहीं करना चाहिए, लेकिन विभाजन की छत है, तो

int l = ((dkLen - 1)/hLen) + 1; // >= ceil(dkLen/hLen), == for dkLen =>1 

यह 16 बाइट चाबी के लिए 20 का एक पहलू से गणना तेज़ हो जाएगी।

0

एन्क्रिप्शन के दौरान अपनी स्ट्रिंग को बाइट सरणी में कनवर्ट करें। डिक्रिप्शन के बाद एक स्ट्रिंग पर वापस कनवर्ट करें।

/** 
* Creates a cipher for encryption or decryption. 
* 
* @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES". 
* @param mode Encyrption or decyrption. 
* @param password Password 
* @param salt Salt usable with algorithm. 
* @param count Iterations. 
* @return Ready initialized cipher. 
* @throws GeneralSecurityException Error creating the cipher. 
*/ 
private static Cipher createCipher(final String algorithm, final int mode, final char[] password, final byte[] salt, final int count) throws GeneralSecurityException { 
    final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm); 
    final PBEKeySpec keySpec = new PBEKeySpec(password); 
    final SecretKey key = keyFactory.generateSecret(keySpec); 
    final Cipher cipher = Cipher.getInstance(algorithm); 
    final PBEParameterSpec params = new PBEParameterSpec(salt, count); 
    cipher.init(mode, key, params); 
    return cipher; 
} 

/** 
* Encrypts some data based on a password. 
* @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" 
* @param data Data to encrypt 
* @param password Password 
* @param salt Salt usable with algorithm 
* @param count Iterations. 
* @return Encrypted data. 
*/ 
public static byte[] encryptPasswordBased(final String algorithm, final byte[] data, final char[] password, final byte[] salt, final int count) { 
    Validate.notNull(algorithm); 
    Validate.notNull(data); 
    Validate.notNull(password); 
    Validate.notNull(salt); 
    try { 
     final Cipher cipher = createCipher(algorithm, Cipher.ENCRYPT_MODE, password, salt, count); 
     return cipher.doFinal(data); 
    } catch (final Exception ex) { 
     throw new RuntimeException("Error encrypting the password!", ex); 
    } 
} 

/** 
* Decrypts some data based on a password. 
* @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" 
* @param encryptedData Data to decrypt 
* @param password Password 
* @param salt Salt usable with algorithm 
* @param count Iterations. 
* @return Encrypted data. 
*/ 
public static byte[] decryptPasswordBased(final String algorithm, final byte[] encryptedData, final char[] password, final byte[] salt, final int count) { 
    Validate.notNull(algorithm); 
    Validate.notNull(encryptedData); 
    Validate.notNull(password); 
    Validate.notNull(salt); 
    try { 
     final Cipher cipher = createCipher(algorithm, Cipher.DECRYPT_MODE, password, salt, count); 
     return cipher.doFinal(encryptedData); 
    } catch (final Exception ex) { 
     throw new RuntimeException("Error decrypting the password!", ex); 
    } 
} 
संबंधित मुद्दे