为什么我的pbkdf2实现如此缓慢(与SQLCipher相比)?

Gan*_*nic 7 java android pbkdf2

我在Xoom平板电脑上编写了一个简单的Android应用程序,它只是将一些字符串注释存储在SQLCipher数据库中.

系统会提示用户输入一个密码,该密码将由SQLCipher lib用于数据库.这个工作到目前为止很顺利.

现在我还实现了一个小的PBKDF2算法用于身份验证(事实上,我希望将来加密一些其他文件,不能存储在数据库中).但就目前而言,我只是来检查我的pbkdf2算法是否正确.我只使用了javax.crypto和java.security库.

代码段如下:

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();    
Run Code Online (Sandbox Code Playgroud)

salt是一个16字节的随机数,由SecureRandom生成.

所以我硬编码了密钥和盐,并比较了derivedKey进行身份验证(只是一个测试用例!)

我现在的问题是,在我的Xoom上它持续大约5秒直到派生函数完成,尽管迭代只设置为500.

AFAIK SQLCipher默认使用4000的迭代次数,如果密钥错误或正确,它会立即响应.(如果我将迭代设置为4000,则至少需要15秒)

问题是,我实现了效率低下还是因为SQLCipher性能良好(原生NDK函数等)?

提前谢谢ps:对不起,我的英语不是很棒!

编辑:

对不起,我不够清楚:-)

我知道PBKDF2应该是慢的(特定的迭代量,减慢暴力攻击),这正是我要求的原因!我想将迭代次数设置为5000(这是不可接受的,超过15秒)

我只是想知道因为,就像我说的那样,SQLCipher也使用PBKDF2(Iteration = 4k,而我使用的是500)从给定密码中获取密钥.我最后并没有谈论使用AES进行加密,而只是关于导出密钥的差异.

当然,SQLCipher的速度似乎比自制的keyderiving功能更快,但我不认为这会有太大的区别,因为SCLCipher的PBKDF2确实可以立即工作!

问候!

mr.*_*tic 8

OK,那(见下文),不完全是你的问题,PBKDF2是缓慢的,但应该是无处慢,与在该硬件上这些参数描述.这里有关于Android PBE/KDF性能的一些统计信息(和提示):http://nelenkov.blogspot.com/2012/04/using-password-based-encryption-on.html.SecretKeyFactory性能问题并不为人知:使用LVL和AESObfuscator可以解决可怕的SecretKeyFactory性能问题吗?.

SecretKeyFactory可能使用纯Java实现.SQLCipher有两个相关的功能:

  • 它使用OpenSSL,编译后的本机代码(在我的桌面上, OpenSSL的PBKDF2比JVM6 SecretKeyFactory版本快2000 倍,比2000次迭代快,不包括JVM启动时间.我还没有比较AES速度,看来其他人发现它在Android上也很慢)
  • 4000迭代PBKDF2只在数据库中完成开,后有最多2次迭代的页面HMAC秘密(假设默认配置,如记录)

您的代码似乎是正确的,当您增加迭代时,不应该有如此大的(线性?)性能下降.该Xoom的应运行非古JVM与JIT,你可以验证与性能问题的其他代码?


PBKDF2 设计缓慢(请参阅此问题的答案https://security.stackexchange.com/questions/7689/clarification-needed-for-nists-whitepaper-recommendation-for-password-based-ke)预定的关键拉伸操作.迭代计数器可让您以安全性换取速度.

AES总是预期要快而快(速度比较PDF,所选择的AES的候补由它原始的名字称为Rijndael算法在纸).

我假设您正在将PBKDF2计算时间直接与在SQLCipher数据库上执行SQL操作所花费的时间进行比较,这几乎肯定会被设计得很快.

您正在有效地比较具有不同要求的两种不同操作,因此速度差异.

  • 好的,陷阱,会更新答案.我做了一些快速测试,我可以看到Java(1.6.x)实现似乎比我的x86桌面上的OpenSSL的`PKCS5_PBKDF2_HMAC_SHA1()`慢〜100倍. (2认同)

Gan*_*nic 2

好吧,我知道问题出在哪里了。

如果我将设备与电脑断开连接,它会立即运行。另外,如果我在那之后重新连接它。

现在,即使迭代量达到 5000 次及以上,求导函数也只需要不到一秒!这太棒了,因为我的 Xoom 不是所有设备中最新的!

可能是因为调试模式什么的,我真的不知道!

不管怎样,谢谢spuratic先生。希望这对将来的人有帮助:-)