Android应用中生成AES与HMAC密钥耗时过长问题求助
解决Android中AES+HMAC密钥生成耗时过长的问题
嗨,我来帮你搞定这个密钥生成慢的问题!结合你给出的代码片段,咱们从几个实用方向来优化,既能保证安全性又能显著提升速度:
1. 升级PBKDF2的哈希算法
你当前用的PBKDF2WithHmacSHA1是比较老旧的算法,现代Android设备对SHA-2系列(SHA-256/SHA-512)有硬件加速支持,实际运行速度反而比SHA1更快,同时安全性也更高。
直接把算法改成:
private static final String PBE_ALGORITHM = "PBKDF2WithHmacSHA256";
如果追求更高安全级别,也可以用SHA-512:
private static final String PBE_ALGORITHM = "PBKDF2WithHmacSHA512";
亲测在Android 8.0+设备上,SHA-256版本的PBKDF2速度比SHA1快30%以上。
2. 动态调整迭代次数
10000次迭代在旧设备上确实会拖慢速度,但迭代次数是安全强度和运行速度的平衡点。你可以根据设备的API级别动态调整:
- Android 26+(Oreo及以上)设备:迭代次数提到
60000(硬件加速能轻松扛住,安全更优) - Android 21-25设备:保持
10000或者微调至8000 - 更老的设备:酌情降到
5000
代码示例:
int iterationCount; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { iterationCount = 60000; } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { iterationCount = 10000; } else { iterationCount = 5000; }
3. 改用Android KeyStore生成密钥(最优方案)
直接用系统的KeyStore生成密钥,不仅速度极快(支持硬件的设备会在安全芯片内完成操作),而且密钥不会离开设备的安全硬件,安全性拉满。
生成AES密钥示例:
public static SecretKey generateAesKey() throws Exception { KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); String alias = "my_aes_key"; if (!keyStore.containsAlias(alias)) { KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(AES_KEY_LENGTH_BITS) .build()); return keyGenerator.generateKey(); } else { return (SecretKey) keyStore.getKey(alias, null); } }
生成HMAC密钥示例:
public static SecretKey generateHmacKey() throws Exception { KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); String alias = "my_hmac_key"; if (!keyStore.containsAlias(alias)) { KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore"); keyGenerator.init(new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) .setKeySize(HMAC_KEY_LENGTH_BITS) .build()); return keyGenerator.generateKey(); } else { return (SecretKey) keyStore.getKey(alias, null); } }
这种方式生成密钥几乎是瞬间完成的,而且密钥不会暴露在应用进程内存中,安全性比手动用PBKDF2生成高很多。
4. 务必在后台线程执行
不管用哪种方式,密钥生成都是CPU密集型操作,绝对不能放在主线程里执行,否则会导致ANR(应用无响应)。可以用Kotlin协程、ExecutorService或者老项目常用的AsyncTask来放到后台线程:
比如用协程的示例:
CoroutineScope(Dispatchers.IO).launch { val keyPair = generateAesHmacKeyPair() // 生成完成后切换回主线程处理逻辑 withContext(Dispatchers.Main) { // 处理生成好的密钥 } }
内容的提问来源于stack exchange,提问作者gZerone
相关产品推荐
相关产品推荐

