我是haskell的新手,想写一个函数来生成随机字节串。
从我的角度来看Crypto.Random
(来自crypto-api v0.3.1)似乎是最好用的模块,但我无法弄明白。
我想做以下事情:
let size = 2048
let bytestring = randomByteString size
答案 0 :(得分:8)
CryptoRandomGen
的任何实例,如Ganesh所示System.Random
用于非安全随机值(请参阅jamshidh的回答)SystemRandom
所涵盖的内容。)选项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 - 他们中的大多数人都不符合任何标准(这不是很好,他们似乎完全脱离了程序员的袖口发明) RDRAND
,HashDRBG
和HmacDRBG
的例外情况。
答案 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。