我刚学习 Haskell,想编写一个生成随机字节字符串的函数。
从我的角度来看,Crypto.Random
(来自 crypto-api v0.3.1)似乎是最好的模块可供使用,但我还是无法理解它。
我想要做类似下面的事情:
let size = 2048
let bytestring = randomByteString size
我刚学习 Haskell,想编写一个生成随机字节字符串的函数。
从我的角度来看,Crypto.Random
(来自 crypto-api v0.3.1)似乎是最好的模块可供使用,但我还是无法理解它。
我想要做类似下面的事情:
let size = 2048
let bytestring = randomByteString size
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
RDRAND
、HashDRBG
和HmacDRBG
。你需要在 IO
单子中执行此操作以初始化生成器的熵。以下代码片段可以用作简单示例,但在更复杂的代码中,您可能应该保留生成器 g2
并稍后重用它。
do
g <- newGenIO :: IO SystemRandom
case genBytes size of
Left err -> error $ show err
Right (result, g2) -> return result
System.Entropy
模块更加简洁,可能也更少出错(请参见我的回答)。但我同意你的观点,在部署环境中持续使用 RNG,使用 SystemRandom
再加上像 MonadCryptoRandom
这样的单子是一个不错的函数式解决方案。 - Thomas M. DuBuisson这里有很多部分,所以我稍后会在下面描述所有内容的工作方式.... 但现在,这就是代码
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
getStdGen
将为您完成此操作,但由于它需要与操作系统通信,因此其类型为 IO a。我已经在 main 中完成了这个操作,它的类型已经是 IO()。next
返回两个值,一个随机 Int 和下一个随机生成器(如果您在相同的随机生成器上运行 next,则会获得相同的结果...试试看)。您需要将此值附加到结果列表中,并再次将下一个生成器输入函数以获取列表中的下一个值。fromIntegral
将 Int 转换为 Word8。然后使用 pack 将其转换为 ByteString。