File: Salsa.hs

package info (click to toggle)
haskell-crypton 1.0.4-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,548 kB
  • sloc: haskell: 26,764; ansic: 22,294; makefile: 6
file content (134 lines) | stat: -rw-r--r-- 6,508 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
{-# LANGUAGE OverloadedStrings #-}

module Salsa (tests) where

import qualified Crypto.Cipher.Salsa as Salsa
import qualified Data.ByteString as B

import Imports

type Vector = (Int, B.ByteString, B.ByteString, [(Int, B.ByteString)])

vectors :: [Vector]
vectors =
    [
        ( 20
        , key
        , iv
        ,
            [
                ( 0
                , "\x99\xA8\xCC\xEC\x6C\x5B\x2A\x0B\x6E\x33\x6C\xB2\x06\x52\x24\x1C\x32\xB2\x4D\x34\xAC\xC0\x45\x7E\xF6\x79\x17\x8E\xDE\x7C\xF8\x05\x80\x5A\x93\x05\xC7\xC4\x99\x09\x68\x3B\xD1\xA8\x03\x32\x78\x17\x62\x7C\xA4\x6F\xE8\xB9\x29\xB6\xDF\x00\x12\xBD\x86\x41\x83\xBE"
                )
            ,
                ( 192
                , "\x2D\x22\x6C\x11\xF4\x7B\x3C\x0C\xCD\x09\x59\xB6\x1F\x59\xD5\xCC\x30\xFC\xEF\x6D\xBB\x8C\xBB\x3D\xCC\x1C\xC2\x52\x04\xFC\xD4\x49\x8C\x37\x42\x6A\x63\xBE\xA3\x28\x2B\x1A\x8A\x0D\x60\xE1\x3E\xB2\xFE\x59\x24\x1A\x9F\x6A\xF4\x26\x68\x98\x66\xED\xC7\x69\xE1\xE6\x48\x2F\xE1\xC1\x28\xA1\x5C\x11\x23\xB5\x65\x5E\xD5\x46\xDF\x01\x4C\xE0\xC4\x55\xDB\xF5\xD3\xA1\x3D\x9C\xD4\xF0\xE2\xD1\xDA\xB9\xF1\x2F\xB6\x8C\x54\x42\x61\xD7\xF8\x8E\xAC\x1C\x6C\xBF\x99\x3F\xBB\xB8\xE0\xAA\x85\x10\xBF\xF8\xE7\x38\x35\xA1\xE8\x6E\xAD\xBB"
                )
            ,
                ( 448
                , "\x05\x97\x18\x8A\x1C\x19\x25\x57\x69\xBE\x1C\x21\x03\x99\xAD\x17\x2E\xB4\x6C\x52\xF9\x2F\xD5\x41\xDF\x2E\xAD\x71\xB1\xFF\x8E\xA7\xAD\xD3\x80\xEC\x71\xA5\xFD\x7A\xDB\x51\x81\xEA\xDD\x18\x25\xEC\x02\x77\x9A\x45\x09\xBE\x58\x32\x70\x8C\xA2\x83\x6C\x16\x93\xA5"
                )
            ]
        )
    ,
        ( 20
        , "\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD\x30\x83\xD6\x29\x7C\xCF\x22\x75\xC8\x1B\x6E\xC1\x14\x67\xBA\x0D"
        , "\x0D\x74\xDB\x42\xA9\x10\x77\xDE"
        ,
            [
                ( 0
                , "\xF5\xFA\xD5\x3F\x79\xF9\xDF\x58\xC4\xAE\xA0\xD0\xED\x9A\x96\x01\xF2\x78\x11\x2C\xA7\x18\x0D\x56\x5B\x42\x0A\x48\x01\x96\x70\xEA\xF2\x4C\xE4\x93\xA8\x62\x63\xF6\x77\xB4\x6A\xCE\x19\x24\x77\x3D\x2B\xB2\x55\x71\xE1\xAA\x85\x93\x75\x8F\xC3\x82\xB1\x28\x0B\x71"
                )
            ,
                ( 65472
                , "\xB7\x0C\x50\x13\x9C\x63\x33\x2E\xF6\xE7\x7A\xC5\x43\x38\xA4\x07\x9B\x82\xBE\xC9\xF9\xA4\x03\xDF\xEA\x82\x1B\x83\xF7\x86\x07\x91\x65\x0E\xF1\xB2\x48\x9D\x05\x90\xB1\xDE\x77\x2E\xED\xA4\xE3\xBC\xD6\x0F\xA7\xCE\x9C\xD6\x23\xD9\xD2\xFD\x57\x58\xB8\x65\x3E\x70\x81\x58\x2C\x65\xD7\x56\x2B\x80\xAE\xC2\xF1\xA6\x73\xA9\xD0\x1C\x9F\x89\x2A\x23\xD4\x91\x9F\x6A\xB4\x7B\x91\x54\xE0\x8E\x69\x9B\x41\x17\xD7\xC6\x66\x47\x7B\x60\xF8\x39\x14\x81\x68\x2F\x5D\x95\xD9\x66\x23\xDB\xC4\x89\xD8\x8D\xAA\x69\x56\xB9\xF0\x64\x6B\x6E"
                )
            ,
                ( 131008
                , "\xA1\x3F\xFA\x12\x08\xF8\xBF\x50\x90\x08\x86\xFA\xAB\x40\xFD\x10\xE8\xCA\xA3\x06\xE6\x3D\xF3\x95\x36\xA1\x56\x4F\xB7\x60\xB2\x42\xA9\xD6\xA4\x62\x8C\xDC\x87\x87\x62\x83\x4E\x27\xA5\x41\xDA\x2A\x5E\x3B\x34\x45\x98\x9C\x76\xF6\x11\xE0\xFE\xC6\xD9\x1A\xCA\xCC"
                )
            ]
        )
    ]
  where
    key :: B.ByteString
    key =
        "\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"

    iv = B.replicate 8 0

newtype RandomVector = RandomVector Vector
    deriving (Show, Eq)

instance Arbitrary RandomVector where
    arbitrary = RandomVector <$> elements vectors

tests =
    testGroup
        "Salsa"
        [ testGroup "KAT" $
            zipWith
                (\i (r, k, n, e) -> testCase (show (i :: Int)) $ salsaRunSimple e r k n)
                [1 ..]
                vectors
        , testProperty "generate-combine" salsaGenerateCombine
        , testProperty "chunking-generate" salsaGenerateChunks
        , testProperty "chunking-combine" salsaCombineChunks
        ]
  where
    salsaRunSimple expected rounds key nonce =
        let salsa = Salsa.initialize rounds key nonce
         in map snd expected @=? salsaLoop 0 salsa expected

    salsaLoop _ _ [] = []
    salsaLoop current salsa (r@(ofs, expectBs) : rs)
        | current < ofs =
            let (_, salsaNext) = Salsa.generate salsa (ofs - current) :: (ByteString, Salsa.State)
             in salsaLoop ofs salsaNext (r : rs)
        | current == ofs =
            let (e, salsaNext) = Salsa.generate salsa (B.length expectBs)
             in e : salsaLoop (current + B.length expectBs) salsaNext rs
        | otherwise = error "internal error in salsaLoop"

    salsaGenerateCombine :: ChunkingLen0_127 -> RandomVector -> Int0_2901 -> Bool
    salsaGenerateCombine (ChunkingLen0_127 ckLen) (RandomVector (rounds, key, iv, _)) (Int0_2901 nbBytes) =
        let initSalsa = Salsa.initialize rounds key iv
         in loop nbBytes ckLen initSalsa
      where
        loop n [] salsa = loop n ckLen salsa
        loop 0 _ _ = True
        loop n (x : xs) salsa =
            let len = min x n
                (c1, next) = Salsa.generate salsa len
                (c2, _) = Salsa.combine salsa (B.replicate len 0)
             in if c1 == c2 then loop (n - len) xs next else False

    salsaGenerateChunks :: ChunkingLen -> RandomVector -> Bool
    salsaGenerateChunks (ChunkingLen ckLen) (RandomVector (rounds, key, iv, _)) =
        let initSalsa = Salsa.initialize rounds key iv
            nbBytes = 1048
            (expected, _) = Salsa.generate initSalsa nbBytes
            chunks = loop nbBytes ckLen (Salsa.initialize rounds key iv)
         in expected == B.concat chunks
      where
        loop n [] salsa = loop n ckLen salsa
        loop 0 _ _ = []
        loop n (x : xs) salsa =
            let len = min x n
                (c, next) = Salsa.generate salsa len
             in c : loop (n - len) xs next

    salsaCombineChunks :: ChunkingLen -> RandomVector -> ArbitraryBS0_2901 -> Bool
    salsaCombineChunks (ChunkingLen ckLen) (RandomVector (rounds, key, iv, _)) (ArbitraryBS0_2901 wholebs) =
        let initSalsa = Salsa.initialize rounds key iv
            (expected, _) = Salsa.combine initSalsa wholebs
            chunks = loop wholebs ckLen initSalsa
         in expected `propertyEq` B.concat chunks
      where
        loop bs [] salsa = loop bs ckLen salsa
        loop bs (x : xs) salsa
            | B.null bs = []
            | otherwise =
                let (bs1, bs2) = B.splitAt (min x (B.length bs)) bs
                    (c, next) = Salsa.combine salsa bs1
                 in c : loop bs2 xs next