2014-07-09 127 views
4

我想使用PBKDF2WithHmacSHA1生成密鑰,但在android上計算需要很長的時間。我在iOS上使用與普通加密相同數量的迭代,並且它需要大約6秒鐘,因爲在android上它需要100秒。PBKDF2WithHmacSHA1密鑰生成在Android上花費太長時間

下面是代碼:

public static String generateStorngPasswordHash(String password) 
{ 
    try 
    { 
     char[] chars = password.toCharArray(); 
     byte[] salt = getSalt(); 

     PBEKeySpec spec = new PBEKeySpec(chars, salt, 1010101, 32 * 8); 
     SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
     byte[] hash = skf.generateSecret(spec).getEncoded(); 

     return toHex(salt) + ":" + toHex(hash); 
    } catch (Exception e) 
    { 
     Logger.e("Exception: Error in generating password" + e.toString()); 
    } 
    return ""; 
} 

private static byte[] getSalt() throws NoSuchAlgorithmException 
{ 
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
    byte[] salt = new byte[32]; 
    sr.nextBytes(salt); 
    return salt; 
} 

請讓我知道是否有這個代碼的任何問題嗎?

編輯

還有一兩件事,我也是在我的應用程序中使用sqlCipher。他們使用openssl來計算PKDF2,並且我在某處讀到openssl實現比java實現要快得多來找到PKDF2。所以我的問題是:

  1. 這是真的,openssl可以給我更好的android性能嗎?
  2. 我可以使用sqlCipherg中使用的openssl實現嗎?
  3. 如果是的話我該如何使用openssl使用caclulate PKDF2?
  4. 如果沒有,那麼我怎樣才能使用openssl在Android中查找PBKDF2WithHmacSHA1。我通過網絡搜索了
    但沒有找到任何示例。
+1

有與該代碼沒有問題。這是關於緩慢的android加密一小時內的第二個問題,請檢查[第一個和問題鏈接到它](http://stackoverflow.com/questions/24650619/image-encryption-decryption-between-php-and-android )。 –

+0

您使用哪種Android手機進行測試?希望你不是在談論模擬器... – Robert

+0

你確定iOS代碼是相同的嗎?在3.6GHz Core i5上執行J2SE中的generateStorngPasswordHash()大約需要2.2秒... – Robert

回答

3

是的,對於在循環中執行SHA,Java顯然比(Objective)C慢。與編譯語言相比,Java對加密並不是特別快。另一方面它允許相對安全的代碼。所以你的結果不會讓我感到震驚。除非您可以使用另一個使用本機代碼的更快的提供程序,否則您應該期待這樣的結果。

然而,有一些方法可以緩解正在發生的事情。你可以例如減少你的迭代次數。數字越高越安全,但它們只能幫助您線性增加攻擊者的工作量。採取其他措施,例如嘗試次數有限,更安全的數據庫或需要更好的密碼短語可能會提供更好的安全性,而不僅僅是增加迭代次數。如果可能的話,不要過度依賴PBKDF2提供的關鍵強化。

此外,您正在從PBKDF2請求32個字節。由於PBKDF2內循環的單次運行輸出僅產生20個字節的輸出(SHA-1創建160位哈希),該循環爲,運行兩次,一次爲最初的20個字節,然後再爲12個字節剩下。如果攻擊者只需要最初的16個字節來驗證密碼,那麼攻擊者就有兩倍的工作量。如果您只是將它用作密碼哈希,那麼只需要輸出20個字節。如果您需要32個字節的密鑰或IV,則在PBKDF的輸出上使用KBKDF。或者,如果您想要快捷方式,請在輸出上執行SHA-256。

代碼低於最後一部分:

/** 
* Same security, twice the speed. 
*/ 
public static String generateStorngPasswordHashWithSHA256(String password) { 
    try { 
     char[] chars = password.toCharArray(); 
     byte[] salt = getSalt(); 

     PBEKeySpec spec = new PBEKeySpec(chars, salt, 1010101, 
       20 * Byte.SIZE); 
     SecretKeyFactory skf = SecretKeyFactory 
       .getInstance("PBKDF2WithHmacSHA1"); 
     byte[] hash = skf.generateSecret(spec).getEncoded(); 

     MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); 
     hash = sha256.digest(); 

     return toHex(salt) + ":" + toHex(hash); 
    } catch (Exception e) { 
     System.out.println("Exception: Error in generating password" 
       + e.toString()); 
    } 
    return ""; 
} 
+0

'「PBKDF2WithHmacSHA1」'是我認爲應該使用本地代碼進行優化的功能的主要示例。 –