jBcrypt 是一个 Java 实现。Android 应用程序几乎是用 Java 编写的,用于一个名为Dalvik的几乎是 Java 的虚拟机。
对于计算密集型任务,尤其是加密算法,与同等优化的 C 代码相比,Java 的速度通常会降低 3 倍:好的 Java 虚拟机运行JIT 编译器,代码的性能将受到 JVM 必须运行的约束的限制in (从字节码到本机代码的转换必须快速且增量,方法在每次调用的基础上进行转换;并且结果必须仍然适合垃圾收集器)。在本机代码可以从 CPU 提供的额外操作码中受益的某些特定情况下,可以观察到进一步的减速,典型情况是对大整数的计算(例如,对于 RSA),因为 CPU 可能提供“扩展”乘法(64x64- >128) Java 代码无法使用,因为 Java 中缺少 128 位整数类型。
有关散列函数上下文中相当彻底的实验(不是“密码散列”,只是“散列”),请参阅sphlib :一个在 C和Java中实现大量散列函数的库,“在优化方面做出了类似的努力”(整个批次的相同开发人员),并包括针对各种平台类型的措施。
现在,Android 应用程序可能会出现额外的减速:
智能手机的 CPU 速度不如 PC 快。智能手机 CPU 可以达到千兆赫兹范围,但每个周期的工作量仍比 x86 CPU 少——因为智能手机 CPU 的主要目标之一是节省电池。智能手机必须在进行无线电活动的同时使用一整天,而笔记本电脑的电池容量更大,只需启动几个小时。现代智能手机效率很高,但与台式电脑相比仍有差距。假设一个额外的 3 倍因子。
Dalvik 不一定是最好的 JIT 编译器。相对缺乏原始肌肉意味着 JIT 无法应用最复杂的优化策略,因为它会使方法的 JIT 转换成本过高。
直到 Android 2.1(包括在内),Dalvik 没有 JIT。这是其他答案所暗示的最严重的放缓。在 Android 2.1(及之前)中,Java 字节码是被解释的,而不是被翻译成本机代码,这会产生巨大的额外成本(比 JIT 代码慢 10 到 20 倍)。Android 2.2 及更高版本具有 JIT。
切换到 PBKDF2 不会改变太多。如果您使用PBKDF2,请务必使用 SHA-256(或 SHA-1),而不是 SHA-512,因为智能手机 CPU 是基于 ARM 的,并且对于 SHA-512 严重依赖的 64 位算术运算会非常不舒服,从而减慢您的代码速度——而攻击者有一台 PC,早餐吃 64 位操作,并且不会导致同样的减慢。
总结: bcrypt 在 Android 2.1(和之前的版本)上会很慢。它在 Android 2.2 上会有点快,尽管不如 PC 快(比如慢 5 到 10 倍)。PBKDF2, scrypt...不要以显着方式改变这张图片。
所有这些都是关于 bcrypt 的性能的。我没有以任何方式评论正确使用 bcrypt 派生的秘密进行加密和密码验证。实际上,当您存储“某物”来验证密码时,您不会因为该“某物”太接近用于加密的密码派生密钥。
一种“密码学上合理的方法”是使用 bcrypt 或 PBKDF2(使用盐和迭代等)计算密码哈希,然后获取输出并使用密钥派生函数将其扩展为足够的密钥材料以满足您的需要。在您的上下文中,获取 bcrypt 输出,然后使用 SHA-256 对其进行哈希处理。这产生 256 位。将数据库中的前 128 位存储为“密码验证令牌”。将另一半用作加密密钥。
PBKDF2 使这个过程稍微简单一些,因为它是一个 KDF,所以你可以立即请求 256 位的密码派生输出,而不需要额外的散列;而 bcrypt 的输出大小固定为 192 位,这可能不足以满足您的需求。