2017-02-20 87 views
3

我用下面的代碼來生成AES密鑰:上SecretKey的調用.getEncoded()返回null

KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("db_enc_key", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT); 

     KeyGenParameterSpec keySpec = builder 
       .setKeySize(256) 
       .setBlockModes("CBC") 
       .setEncryptionPaddings("PKCS7Padding") 
       .setRandomizedEncryptionRequired(true) 
       .setUserAuthenticationRequired(true) 
       .setUserAuthenticationValidityDurationSeconds(5 * 60) 
       .build(); 

     KeyGenerator keyGen = KeyGenerator.getInstance("AES", "AndroidKeyStore"); 
     keyGen.init(keySpec); 

     SecretKey sk = keyGen.generateKey(); 

,但每次我試圖讓通過sk.getEncoded關鍵的字節[]版本() ,該方法返回null。文檔說它應該返回編碼密鑰,如果密鑰不支持編碼,則返回null,但我不認爲密鑰不支持編碼。

我需要的byte [],因爲我要加密一個境界數據庫(我需要2 AES-256按鍵組合成字節數組)https://realm.io/docs/java/latest/#encryption]

官方文檔使用SecureRandom的,但也規定這是做這件事的一種愚蠢的方式,並且鑰匙從不儲存。因此,我想使用KeyStore安全地存儲兩個獨立的AES-256密鑰。

P.S .:代碼只是一個測試代碼而不是最終產品,所以對編碼風格的任何評論都是無用的。我目前只是試圖讓一個工作版本。

編輯:所以,我試圖將下面的代碼,它成功地產生AES密鑰(雖然只有16字節長度的):

SecretKey sk1 = KeyGenerator.getInstance("AES").generateKey(); 

當我使用的getEncoded()方法就可以了,我會甚至得到字節數組,所以自然我繼續並使用以下代碼將其保存到KeyStore中:

KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(sk1); 
KeyStore.ProtectionParameter pp = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT).build(); 
keyStore.setEntry("db_enc_key_test", entry, pp); 

這也適用。所以我試圖通過KeyStore.Entry entry2 = keyStore.getEntry("db_enc_key_test", null);從密鑰庫中讀取密鑰,這也起作用。但是當我撥打entry2.getEncoded()時,該方法會再次返回空值。這是一個密鑰存儲問題嗎?

edit2:所以我剛剛發現,在密鑰庫中生成的對稱密鑰在Android M中是不可移植的,這似乎是有意的,這使我陷入了一個問題,因爲我需要密鑰本身用於加密領域數據庫。

一些領域開發人員在這裏推薦一個最佳實踐?

回答

2

您無法檢索編碼密鑰的設計是因爲Keystore應該是唯一知道它的人。但是,您可以使用雙層密鑰:

1)生成一個隨機密鑰並將其存儲在密鑰庫中。

2)生成Realm使用的「真實」密鑰,並使用Keystore中的密鑰對其進行加密。

3)現在你有一些完全隨機的文本,可以存儲在例如SharedPreferences或磁盤上的文件中。

4)每當人們想要打開領域時,請閱讀磁盤上的加密密鑰,使用密鑰庫對其進行解密,現在可以使用它打開領域。

這裏該回購使用相同的技術來保存用戶數據安全的方式:https://github.com/realm/realm-android-user-store

這可能是類,你是後:https://github.com/realm/realm-android-user-store/blob/master/app/src/main/java/io/realm/android/CipherClient.java它也處理過各種各樣的Android版本回退(密鑰庫有相當幾個怪癖)。

+0

是的,這聽起來像是目前最好的解決方法。謝謝。 – wickermoon