Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 加速Haskell PBKDF2算法_Performance_Haskell_Pbkdf2 - Fatal编程技术网

Performance 加速Haskell PBKDF2算法

Performance 加速Haskell PBKDF2算法,performance,haskell,pbkdf2,Performance,Haskell,Pbkdf2,我在Haskell中编写了PBKDF2算法的新版本。它几乎通过了中列出的所有HMAC-SHA-1测试向量,但效率不高。如何改进代码 当我在测试向量上运行它时,第三种情况(见下文)永远不会结束(我让它在2010 Macbook Pro上运行了1/2个多小时) 我相信foldl'是我的问题。foldr性能会更好,还是需要使用可变数组 {-#语言模式} {-版权所有2013,马里兰州G.拉尔夫·昆茨。保留所有权利。LGPL许可证。-} 模块加密在哪里 导入Codec.Utils(八位字节) 导入符合条

我在Haskell中编写了PBKDF2算法的新版本。它几乎通过了中列出的所有HMAC-SHA-1测试向量,但效率不高。如何改进代码

当我在测试向量上运行它时,第三种情况(见下文)永远不会结束(我让它在2010 Macbook Pro上运行了1/2个多小时)

我相信
foldl'
是我的问题。
foldr
性能会更好,还是需要使用可变数组

{-#语言模式}
{-版权所有2013,马里兰州G.拉尔夫·昆茨。保留所有权利。LGPL许可证。-}
模块加密在哪里
导入Codec.Utils(八位字节)
导入符合条件的数据。二进制为B(编码)
导入数据位(异或)
将限定数据.ByteString.Lazy.Char8作为C(包)导入
将限定的Data.ByteString.Lazy导入为L(解包)
导入数据列表(foldl')
导入Data.HMAC(HMAC_sha1)
导入Text.Bytedump(dumpRaw)
--将PBKDF2计算为十六进制字符串
pbkdf2
::([Octet]->[Octet]->[Octet])--伪随机函数(HMAC)
->Int—以字节为单位的哈希长度
->字符串--密码
->绳子--盐
->Int——迭代
->Int—以字节为单位的派生密钥长度
->串
pbkdf2 prf hashLength密码salt密钥长度=
让
passwordOctets=stringToOctets密码
saltOctets=stringToOctets盐
总积木=
上限$(fromIntegral keyLength::Double)/fromIntegral hashLength
块迭代器消息acc=
foldl'(\(a,m)\->
设!m'=prf密码八位组m
in(带异或a m',m')(acc,message)[1..iterations]
在里面
dumpRaw$take keydlength$foldl'(\acc block->
acc++fst(块迭代器(saltOctets++intToOctets块)
(复制hashLength 0))[[1..totalBlocks]
哪里
intToOctets::Int->[Octet]
intToOctets i=
让a=L.打开包装。B.encode$i
落下(长度a-4)a
stringToOctets::String->[Octet]
stringToOctets=L.打开包装。C.包装
--使用HMAC和SHA-1将PBKDF2计算为十六进制字符串
pbkdf2HmacSha1
::字符串--密码
->绳子--盐
->Int——迭代
->Int—以字节为单位的派生密钥长度
->串
pbkdf2HmacSha1=
pbkdf2 hmac_sha1 20
第三测试向量
我能够在MacBookPro上在约16分钟内完成:

% time Crypto-Main
eefe3d61cd4da4e4e9945b3d6ba2158c2634e984                          
./Crypto-Main  1027.30s user 15.34s system 100% cpu 17:22.61 total
通过改变折叠的严格程度:

let
  -- ...
  blockIterator message acc = foldl' (zipWith' xor) acc ms
    where ms = take iterations . tail $ iterate (prf passwordOctets) message
          zipWith' f as bs = let cs = zipWith f as bs in sum cs `seq` cs
in
  dumpRaw $ take keyLength $ foldl' (\acc block ->
    acc ++ blockIterator (saltOctets ++ intToOctets block)
                    (replicate hashLength 0)) [] [1..totalBlocks]
请注意,我是如何使用xor强制对每个
zipw进行完整计算的。为了计算
将cs
求和到WHNF中,我们必须知道
cs
中每个元素的确切值


这可以防止建立一个thunk链,我认为您现有的代码正试图这样做,但失败了,因为
foldl'
只会强制累加器进入WHNF。因为你的累加器是一对,WHNF只是
(\u thunk,\u另一个\u thunk)
,所以你的中间thunk没有被强迫。

快速观察:你在
foldl'
参数中没有真正强迫
m
。因为
m
是一个你需要使用的列表,例如
deepSeq
来强制执行所有功能。可能我在这一点上完全错了,因为我不是一个真正强大的Haskeller,但是你在一个函数中塞进的数量让它有点难以理解,如果你把它分成更小更简单的部分,你可能会发现改进的空间变得非常明显。我强烈建议将算法改为通过testring来处理
ByteString
s(这可以很容易地看作
Word8
s的向量),而不是
Octet
s的列表。我无法想象这是速度缓慢的唯一原因,尽管这也是一个需要测试的有点棘手的算法,因为你可以调整它以花费你喜欢的时间。我将看看如何使用
ByteString
。你比我更有耐心。我用原始版本等了大约30分钟,但没有完成。我来看看你的建议。谢谢。关于这个问题,Petr Pudlák建议更好的解决方案可能是使用非固定ST数组。我必须看一看,我实际上是用非固定的ST数组重写了这个函数,但它仍然很慢。我需要运行性能测试来找出原因。
let
  -- ...
  blockIterator message acc = foldl' (zipWith' xor) acc ms
    where ms = take iterations . tail $ iterate (prf passwordOctets) message
          zipWith' f as bs = let cs = zipWith f as bs in sum cs `seq` cs
in
  dumpRaw $ take keyLength $ foldl' (\acc block ->
    acc ++ blockIterator (saltOctets ++ intToOctets block)
                    (replicate hashLength 0)) [] [1..totalBlocks]