我在我的 Xoom 平板电脑上编写了一个简单的 Android 应用程序,它只是在 SQLCipher 数据库中存储一些字符串注释。
系统会提示用户输入 SQLCipher 库将用于数据库的密码。到目前为止,这工作正常并且非常顺利。
现在我还实现了一个用于身份验证的小型 PBKDF2 算法
(实际上,我将来希望对其他一些文件进行加密,但不能存储在数据库中)。
但至于现在,我只是来检查我的 pbkdf2 算法是否正确。
我只使用了 javax.crypto 和 java.security 库。
代码 fragment 如下:
int derivedKeyLength = 128;
int iterations = 500;
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, iterations, derivedKeyLength);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] derivedKey = f.generateSecret(spec).getEncoded();
salt 是一个 16 字节的随机数,由 SecureRandom 生成。
所以我对 key 和盐进行了硬编码,并比较了用于身份验证的衍生 key (只是一个测试用例!)
我现在的问题是,尽管迭代仅设置为 500,但在我的 Xoom 上,它持续了大约 5 秒,直到派生函数完成。
AFAIK SQLCipher 默认使用 4000 的迭代次数,如果 key 错误或正确,它会立即响应。
(如果我将迭代设置为 4000,则至少需要 15 秒)
问题是,我实现的效率低下还是因为 SQLCipher 的性能(原生 NDK 函数等)那么好?
先感谢您
ps:对不起,我的英语还没有那么好!
编辑:
对不起,我不够清楚:-)
我知道 PBKDF2 应该很慢(特别是迭代量,以减缓蛮力攻击),这正是我要问的原因!我想将迭代次数设置为 5000(这是 Not Acceptable ,超过 15 秒)
我只是想知道,因为就像我说的,SQLCipher 也使用 PBKDF2(迭代 = 4k,而我使用 500 )来从给定的密码派生 key 。最后我不是在谈论 AES 加密,它只是关于派生 key 的不同。
当然,SQLCipher 比自制的 key 派生函数快得多似乎是合法的,但我不认为会有这么大的差异,因为 SLCipher 的 PBKDF2 真的可以立即工作!
问候!
最佳答案
好的,那(见下文)不完全是你的问题,PBKDF2 很慢,但应该没有硬件上那些参数描述的那么慢。
关于Android PBE/KDF性能,这里有一些统计信息(和提示):http://nelenkov.blogspot.com/2012/04/using-password-based-encryption-on.html。 SecretKeyFactory
性能问题并非未知: Any way around awful SecretKeyFactory performance with LVL and AESObfuscator? 。SecretKeyFactory
很可能使用纯 Java 实现。 SQLCipher 有两个相关的特性:
2000 次迭代的 JVM6
SecretKeyFactory
版本,不包括 JVM 启动时间。我没有比较 AES 速度,似乎其他人也发现它在 Android 上也很慢)
页面 HMAC secret (假设默认配置,如文档所述)
您的代码似乎是正确的,当您增加迭代次数时,不应出现如此大的(线性?)性能下降。 Xoom 应该是用 JIT 运行一个非古老的 JVM,你能用 other code 验证性能问题吗?
由于预期的 https://security.stackexchange.com/questions/7689/clarification-needed-for-nists-whitepaper-recommendation-for-password-based-ke 操作,PBKDF2 被设计为很慢(请参阅此问题 key stretching 的答案)。迭代计数器可让您权衡速度以换取安全性。
AES 总是 intended to be fast 并且是
快速(speed comparison PDF,所选的AES候选者在该论文中以其原始名称Rijndael命名)。
我假设您将 PBKDF2 计算时间直接与在您的 SQLCipher 数据库上执行 SQL 操作所花费的时间进行比较,这几乎肯定会设计得很快。
您正在有效地比较具有不同要求的两种不同操作,因此速度差异。