[英]how to securely store encryption keys in android?
我想知道如何在 Android 中安全地存儲加密密鑰? 保護加密和秘密密鑰的最佳方案是什么?
根據您的評論,您需要使用當前 Android 版本和舊版本的本地密鑰加密數據
Android Keystore旨在生成和保護您的密鑰。 但是它不適用於低於 18 的 API 級別,並且在 API 級別 23 之前它有一些限制。
您將需要一個隨機對稱加密密鑰,例如 AES。 AES 密鑰用於加密和解密您的數據。 我將總結您根據 Android API 級別安全生成和存儲它的選項。
API 級別 < 18:Android 密鑰庫不存在。 向用戶請求密碼,從密碼推導出加密密鑰,缺點是需要在應用程序啟動時提示輸入密碼。 加密密鑰不存儲在設備中。 每次啟動應用程序時使用密碼計算
API 級別 >=18 <23:Android Keystore 可用,無需 AES 支持。 使用默認加密提供程序(不使用 AndroidKeystore)生成隨機 AES 密鑰。 生成 RSA 密鑰對到 Android Keystore 中,並使用 RSA 公鑰加密 AES 密鑰。 將加密的 AES 密鑰存儲到 Android SharedPreferences 中。 應用程序啟動時,使用 RSA 私鑰解密 AES 密鑰
API 級別 >=23:支持 AES 的 Android 密鑰庫。 使用到 Android Keystore 生成隨機 AES 密鑰。 您可以直接使用它。
加密可以使用AES/CBC/PKCS7Padding
算法。 它還需要一個隨機初始化向量 (IV) 來加密您的數據,但它可以是公開的。
替代品:
API 級別 >14:Android Key Chain :KeyChain 是系統范圍的憑證存儲。 您可以使用可由應用程序使用的私鑰安裝證書。 使用預先安裝的密鑰來加密/解密您的 AES 密鑰,如上面的第二種情況所示。
外部令牌:受保護的密鑰不存儲在設備中。 您可以使用包含私鑰/公鑰對的外部令牌來加密 AES 密鑰。 可以使用藍牙或 NFC 訪問令牌
您不能將加密密鑰放在您的 apk 文件中。 您可能希望將其保存在遠程服務器中並使用服務器解密。 或者,您可能會通過對密鑰進行編碼並將其保存在不明顯的地方而讓其他人感到困難。 但是對此沒有防彈解決方案。
沒有辦法將您的私有 api 密鑰安全地保存到代碼中。 但是您可以使用 NDK 來安全地保存私鑰。 從 NDK 獲取密鑰並非易事。 使用 NDK 示例保護密鑰
聽起來您想要EncryptedSharedPreferences或EncryptedFile 。 這兩個都使用AndroidKeyStore 。 下面的代碼片段實際上回答了“如何使用 AndroidKeystore 加密文件或存儲加密密鑰?”的問題。
確保在您的應用build.gradle
文件中包含implementation "androidx.security:security-crypto:1.0.0-rc02"
。
來自EncryptedSharedPreferences :
加密密鑰和值的SharedPreferences的實現。
String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
"secret_shared_prefs",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
// use the shared preferences and editor as you normally would
SharedPreferences.Editor editor = sharedPreferences.edit();
您可以像這樣存儲加密密鑰:
// generate random symmetric key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey symkey = keyGen.generateKey();
String alias = "your encryption key";
// store symmetric key
byte[] encodedSymmetricKey = symkey.getEncoded();
SharedPreferences.Editor edit = sharedPreferences.edit();
String base64EncodedSymmetricKey = new String(Base64.getEncoder().encode(encodedSymmetricKey));
edit.putString(alias, base64EncodedSymmetricKey);
edit.commit();
// retrieve symmetric key
String raw = sharedPreferences.getString(alias, null);
byte[] symKey = Base64.getDecoder().decode(raw);
SecretKeySpec spec = new SecretKeySpec(symKey, "AES");
assert(spec.equals(symkey));
// use your encryption key
雖然使用EncryptedFile會好得多。
來自EncryptedFile :
用於創建和讀取加密文件的類。
String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
File file = new File(context.getFilesDir(), "secret_data");
EncryptedFile encryptedFile = EncryptedFile.Builder(
file,
context,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();
// write to the encrypted file
FileOutputStream encryptedOutputStream = encryptedFile.openFileOutput();
// read the encrypted file
FileInputStream encryptedInputStream = encryptedFile.openFileInput();
注意:
主密鑰一旦創建,就是恆定的。 因此,即使在手機重啟后,您的應用程序仍然能夠加密/解密文件。
您可以使用 Android Keystore 系統來存儲和檢索敏感信息。 閱讀這篇 5 分鍾的文章,了解它是如何工作的。 使用 Android Keystore 系統存儲和檢索敏感信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.