如何在haskell中正确生成随机字节串

时间:2014-01-02 18:51:04

标签: haskell random cryptography

我是haskell的新手,想写一个函数来生成随机字节串。 从我的角度来看Crypto.Random(来自crypto-api v0.3.1)似乎是最好用的模块,但我无法弄明白。

我想做以下事情:

let size = 2048
let bytestring = randomByteString size

3 个答案:

答案 0 :(得分:8)

  1. 您可以使用CryptoRandomGen的任何实例,如Ganesh所示
  2. 您可以将System.Random用于非安全随机值(请参阅jamshidh的回答)
  3. 您可以获得平台基础生成器提供的熵(这是SystemRandom所涵盖的内容。)
  4. 选项3:从您的平台获取熵

    最后一种技术是最简单的,但在没有RDRAND指令的系统上有更高的开销 - 它必须打开文件,读取和关闭文件。这是使用entropy包:

    import System.Entropy
    
    someFunc = do
        randBytes <- getEntropy 2048
        ....
    

    选项1:使用CryptoRandomGen实例

    如果你想要一个纯粹的生成器但是用高熵种子播种,那么你可以使用DRBG包中的任何CryptoRandomGen实例化值:

    import Crypto.Random.DRBG
    

    然后就是Ganesh的例子(此处转载),newGenIO上有不同的签名:

    do
      g <- newGenIO :: IO CtrDRBG
      case genBytes size g of
        Left err -> error $ show err
        Right (result, g2) -> return result
    

    对于好奇的人,我reviewed a few of the available secure RNGs on my blog - 他们中的大多数人都不符合任何标准(这不是很好,他们似乎完全脱离了程序员的袖口发明) RDRANDHashDRBGHmacDRBG的例外情况。

答案 1 :(得分:5)

您需要在IO monad中执行此操作以初始化生成器的熵。像这个片段这样的东西可以用来做一个简单的例子,虽然在更复杂的代码中你应该保留生成器g2并稍后重新使用它。

do
    g <- newGenIO :: IO SystemRandom
    case genBytes size of
        Left err -> error $ show err
        Right (result, g2) -> return result

答案 2 :(得分:4)

这里有很多部分,所以我将在下面描述这一切是如何工作的......但是现在,这里是代码

import Data.ByteString
import Data.Word8
import System.Random


randomBytes::Int->StdGen->[Word8]
randomBytes 0 _ = []
randomBytes count g = fromIntegral value:randomBytes (count - 1) nextG
                      where (value, nextG) = next g

randomByteString::Int->StdGen->ByteString
randomByteString count g = pack $ randomBytes count g

main = do
  g <- getStdGen
  let bytestring = randomByteString 2048 g
  print bytestring

首先,请注意您需要提供随机生成器。所有生成伪随机数的计算机程序都需要一个随机数生成器,但大多数使用副作用隐藏在幕后。由于Haskell没有副作用,你需要自己管理状态(有一个随机数生成器monad可以为你做这个,如果你想回去隐藏一些细节,但因为这是一个学习练习,我会明确地说明。)

所有随机生成器都需要播种....您可以通过提供自己的种子来创建随机生成器,但这被认为是不安全的,因为任何人都可以对代码进行逆向工程并查看种子。请记住,伪随机生成器实际上并不是随机的,而是一个定义良好的可再生系列,它遵循数学公式和给定的种子。 (这些数字只是随机的,在没有运行算法本身的情况下,没有任何关于结果值的统计数据可以预测。)

大多数操作系统都有某种API调用会在编译时生成不可预测的内容(即更真实的随机数),但这些调用运行缓慢,因此通常的策略是运行一次以随机生成器播种。运行getStdGen将为您执行此操作,但由于它需要与OS通信,因此其类型为IO a。我在main中完成了这个,它已经是类型IO()。

函数next返回两个东西,一个随机的Int和下一个随机生成器(如果你在同一个随机生成器上运行,你会得到相同的结果....试试吧)。您需要将此值附加到结果列表,并再次将下一个生成器提供给函数以获取列表中的下一个值。

请注意,ByteString表示Word8值的列表,然后返回Int,因此我们需要使用fromIntegral将Int转换为Word8。然后使用pack将其转换为ByteString。