【问题标题】:SecureRandom: thread safe without contention and still cryptographically secure?SecureRandom:没有争用的线程安全并且仍然是加密安全的?
【发布时间】:2017-03-13 10:06:48
【问题描述】:

通过论坛阅读,似乎SecureRandom 是线程安全的,但由于争用,它在多线程系统中遇到了困难,请参阅Is SecureRandom thread safe? 。初始化一个新的SecureRandom也是一项昂贵的操作。提高性能的一个建议是使用ThreadLocalRandom

所以我改变了我的代码:

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");

到:

private final ThreadLocalRandom randomThreadLocal = ThreadLocalRandom.current();

我做了一些测试 - 100 次加密 10000 个字符串值,我可以看到明显的改进。

**With ThreadLocalRandom**
Thread #18New encryption service took on average: 66.44ms.
Thread #17New encryption service took on average: 64.79ms.
Thread #14New encryption service took on average: 70.77ms.
Thread #13New encryption service took on average: 72.33ms.
Thread #19New encryption service took on average: 73.42ms.
Thread #15New encryption service took on average: 74.21ms.
Thread #11New encryption service took on average: 76.79ms.
Thread #16New encryption service took on average: 78.72ms.
Thread #12New encryption service took on average: 78.95ms.
Thread #20New encryption service took on average: 78.99ms.

**With SecureRandom**
Thread #19New encryption service took on average: 87.26ms.
Thread #18New encryption service took on average: 93.65ms.
Thread #13New encryption service took on average: 93.1ms.
Thread #15New encryption service took on average: 95.81ms.
Thread #16New encryption service took on average: 96.9ms.
Thread #11New encryption service took on average: 97.0ms.
Thread #20New encryption service took on average: 94.93ms.
Thread #17New encryption service took on average: 96.63ms.
Thread #12New encryption service took on average: 97.41ms.
Thread #14New encryption service took on average: 99.08ms.

看来我确实提高了这里的速度,但是我降低了安全性,因为 ThreadLocalRandom 似乎不是加密安全的:

 * <p>Instances of {@code ThreadLocalRandom} are not cryptographically
 * secure.  Consider instead using {@link java.security.SecureRandom}
 * in security-sensitive applications

我的问题是 - 有没有办法创建加密安全的随机数,它是线程安全的并且在多线程系统中表现良好?

还有一个问题涉及这个主题,但答案是从SecureRandomThreadLocalRandom 的相同转换,这不是加密安全的,请参阅Minimizing SecureRandom performance problems in multithreaded environment?

【问题讨论】:

  • 随机需要多少个线程?我知道您说过创建SecureRandom 的成本很高,但您可能仍想衡量最终是否为每个线程创建一个会带来更快的结果,因为没有争用。
  • 还有其他产生随机值的方法,即通过使用硬件、听麦克风的噪声背景或使用外部磁力计,也可以从互联网上下载随机数据,但是这些方法非常在多线程环境中不太可能更快更有效。我建议坚持使用SecureRandom,并确保在多个线程中重用相同的实例实例,然后调用.nextBytes(..) 函数。最后,如果您想要加密的强值,您必须为性能付出代价。
  • 因此,您每次通话节省了大约 30 毫秒。这几乎没有什么大的变化,这对整体性能有影响吗?你想要安全的随机数还是只是随机数?
  • @john16384 我将使用这个随机数进行加密,所以我想根据我的需要,最好是安全的随机数。
  • 好吧,我想首先要测试的是两个线程是否真的比一个线程更快地生成数字。如果他们这样做了,那么为什么不让两个或更多线程都忙着让队列缓冲区充满随机数呢?我看不到任何其他更快的解决方案。当排队的数据变少时,让生成器进程添加更多线程甚至应该不是那么难。

标签: java multithreading security cryptography


【解决方案1】:

SecureRandom 的实现比ThreadLocalRandom 慢得多。这与线程安全无关。

ThreadLocalRandom的生成下一个随机数的算法涉及的数学运算很少,很容易破解。实际上,单个 nextLong 操作返回的结果足以确定该生成器生成的所有未来和过去的数字,如果您对细节感兴趣,请参阅https://jazzy.id.au/2010/09/20/cracking_random_number_generators_part_1.html

另一方面,SecureRandom 与您选择的提供程序一起使用 SHA1 生成随机数。 SHA1 计算量大,所以性能比ThreadLocalRandom 差。这是设计使然 - 计算复杂性是导致 SHA1 难以逆转且种子难以猜测的因素之一。

为了比较性能,我使用两个生成器在单个线程中生成了 100M 个随机数。 ThreadLocalRandom 用了 95 毫秒完成,SecureRandom 用了 41 秒。

编辑以解决线程性能问题:

您可以为每个线程创建一个SecureRandom 实例。它将在第一次使用时使用从静态(共享/同步)实例中获取的数据进行初始化,但后续操作将是线程本地的。我使用共享和专用SecureRandom 实例测量了 4 个线程的性能。每个线程产生100M个随机数;专用实例耗时 30 秒,共享实例耗时 1 分 54 秒。

【讨论】:

猜你喜欢
  • 2010-11-30
  • 1970-01-01
  • 2018-03-29
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
  • 2016-08-18
相关资源
最近更新 更多