【问题标题】:How to produce a "securely random" string token in Haskell?如何在 Haskell 中生成“安全随机”字符串令牌?
【发布时间】:2016-11-03 08:19:44
【问题描述】:

我想生成字符串令牌来实现 Web 应用程序的密码重置功能。它们可以是v4 UUIDs,但不是必需的。

我希望每个令牌在this SO question 的意义上都是“安全随机的”。应该为每个生成的令牌对系统的熵池进行采样。

我找到了生成 v4 UUID 的 uuid 包。文档提到

我们使用 System.Random StdGen 作为我们的随机源。

但我不清楚这是否足够。

我应该使用其他库吗?

【问题讨论】:

  • 如果您查看nextRandom 的源代码(单击右侧的Source),您会发现它只是为每个号码调用Crypto.Random.Entropy.getEntropy,并根据documentation for Crypto.Random"该模块用于实例化加密强确定性随机位生成器“所以我相信你应该是安全的。
  • 如果您存储在数据库中并使用像持久化这样的库,那么您可以通过内部 postgres 方法本身来完成。
  • @Sibi 我正在使用 MySQL,其 UUID 函数不是“安全随机”,从文档来看:dev.mysql.com/doc/refman/5.7/en/…

标签: security haskell random cryptography


【解决方案1】:

应在每个生成的令牌上对系统熵池进行采样的要求听起来很可疑。熵通常是一种稀缺资源。

让我们同意/dev/random 肯定出局了。其他进程可能需要它,它可能导致潜在的拒绝服务等。但首先,当它认为熵池不足时,/dev/random blocks 会在读取时被读取,因此它是绝对不可用的。另一方面,/dev/urandom 应该很好。有人说它在一些奇怪的情况下会出现问题(例如在无盘机器上启动之后),但我们不要去那里。

请注意,在大多数系统上/dev/[u]random 都使用相同的算法。不同之处在于/dev/urandom 从不阻塞,但也不一定在每次读取时使用任何新熵。因此,如果使用/dev/urandom 算作“对系统熵池进行采样”,那么无论您拥有正确使用的任何解决方案都可能没问题。

但是,它的代价是不纯洁。阅读/dev/urandom 迫使我们进入IO。作为haskellers,我们至少必须考虑替代方案,如果我们放弃熵样本的要求,我们就很幸运,这开始时似乎很奇怪。

相反,我们可以使用加密安全的确定性 RNG,并且只能从 /dev/random 中播种它。来自cryptonite 的ChaChaDRG 是DJB 的ChaCha 的一个实现,将是一个不错的选择。由于它是确定性的,我们只需要IO 即可获得初始种子。之后的一切都是纯净的。

Cryptonite 提供getRandomBytes,因此您可以调整令牌的长度以满足您的需求。

【讨论】:

  • “系统熵池应该对每个生成的令牌进行采样的要求听起来很可疑”我同意。问题是我正在尝试实现一个没有空间来维护状态的类型类接口,除非我尝试一些unsafePerformIO 技巧来初始化全局引用...
  • 嗯...确定性RNG确实需要将其状态存储在某处。如果我们不允许这样做并且我们不想要明确的IO,那么您唯一的选择可能确实是阅读/dev/urandomunsafePerformIO。不过,这似乎是最后的手段。
  • 我可以执行显式的IO,但是我必须每次都对/dev/urandom 进行采样,或者使用'unsafePerformIO` 来跟踪全局状态。
猜你喜欢
  • 2015-11-07
  • 2012-08-19
  • 2012-02-12
  • 2012-08-24
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多