Main.hs (8430B)
1 {-# LANGUAGE OverloadedStrings #-} 2 {-# LANGUAGE RecordWildCards #-} 3 {-# LANGUAGE ViewPatterns #-} 4 5 module Main where 6 7 import qualified Crypto.Hash.SHA256 as SHA256 8 import qualified Data.Aeson as A 9 import qualified Data.ByteString as BS 10 import qualified Data.ByteString.Builder as BSB 11 import qualified Data.ByteString.Lazy as BL 12 import qualified Data.ByteString.Base16 as B16 13 import qualified Data.Text.Encoding as TE 14 import qualified Data.Text.IO as TIO 15 import Test.Tasty 16 import Test.Tasty.HUnit 17 import qualified Wycheproof as W 18 19 main :: IO () 20 main = do 21 wycheproof <- TIO.readFile "etc/wycheproof_hmac_sha256.json" 22 case A.decodeStrictText wycheproof :: Maybe W.Wycheproof of 23 Nothing -> error "couldn't parse wycheproof vectors" 24 Just w -> defaultMain $ testGroup "ppad-sha256" [ 25 unit_tests 26 , wycheproof_tests w 27 ] 28 29 wycheproof_tests :: W.Wycheproof -> TestTree 30 wycheproof_tests W.Wycheproof {..} = testGroup "wycheproof vectors (hmac)" $ 31 fmap execute_group wp_testGroups 32 33 execute_group :: W.MacTestGroup -> TestTree 34 execute_group W.MacTestGroup {..} = 35 testGroup msg (fmap (execute mtg_tagSize) mtg_tests) 36 where 37 msg = "keysize " <> show mtg_keySize <> ", tagsize " <> show mtg_tagSize 38 39 execute :: Int -> W.MacTest -> TestTree 40 execute tag_size W.MacTest {..} = testCase t_msg $ do 41 let key = B16.decodeLenient (TE.encodeUtf8 mt_key) 42 msg = B16.decodeLenient (TE.encodeUtf8 mt_msg) 43 pec = B16.decodeLenient (TE.encodeUtf8 mt_tag) 44 out = BS.take bytes (SHA256.hmac key msg) 45 if mt_result == "invalid" 46 then assertBool "invalid" (pec /= out) 47 else assertEqual mempty pec out 48 where 49 t_msg = "test " <> show mt_tcId -- XX embellish 50 bytes = tag_size `div` 8 51 52 unit_tests :: TestTree 53 unit_tests = testGroup "unit tests" [ 54 testGroup "hash" [ 55 cmp_hash "hv0" hv0_put hv0_pec 56 , cmp_hash "hv1" hv1_put hv1_pec 57 , cmp_hash "hv2" hv2_put hv2_pec 58 , cmp_hash "hv3" hv3_put hv3_pec 59 , cmp_hash "hv4" hv4_put hv4_pec 60 ] 61 , testGroup "hash_lazy" [ 62 cmp_hash_lazy "hv0" hv0_put hv0_pec 63 , cmp_hash_lazy "hv1" hv1_put hv1_pec 64 , cmp_hash_lazy "hv2" hv2_put hv2_pec 65 , cmp_hash_lazy "hv3" hv3_put hv3_pec 66 , cmp_hash_lazy "hv4" hv4_put hv4_pec 67 ] 68 -- uncomment me to run (slow, ~30s) 69 -- 70 -- , testGroup "hash_lazy (1GB input)" [ 71 -- testCase "hv5" $ do 72 -- let out = B16.encode (SHA256.hash_lazy hv5_put) 73 -- assertEqual mempty hv5_pec out 74 -- ] 75 , testGroup "hmac" [ 76 cmp_hmac "hmv1" hmv1_key hmv1_put hmv1_pec 77 , cmp_hmac "hmv2" hmv2_key hmv2_put hmv2_pec 78 , cmp_hmac "hmv3" hmv3_key hmv3_put hmv3_pec 79 , cmp_hmac "hmv4" hmv4_key hmv4_put hmv4_pec 80 , testCase "hmv5" $ do 81 let out = BS.take 32 $ B16.encode (SHA256.hmac hmv5_key hmv5_put) 82 assertEqual mempty hmv5_pec out 83 , testCase "hmv6" $ do 84 let out = B16.encode (SHA256.hmac hmv6_key hmv6_put) 85 assertEqual mempty hmv6_pec out 86 , testCase "hmv7" $ do 87 let out = B16.encode (SHA256.hmac hmv7_key hmv7_put) 88 assertEqual mempty hmv7_pec out 89 ] 90 , testGroup "hmac_lazy" [ 91 cmp_hmac_lazy "hmv1" hmv1_key hmv1_put hmv1_pec 92 , cmp_hmac_lazy "hmv2" hmv2_key hmv2_put hmv2_pec 93 , cmp_hmac_lazy "hmv3" hmv3_key hmv3_put hmv3_pec 94 , cmp_hmac_lazy "hmv4" hmv4_key hmv4_put hmv4_pec 95 , testCase "hmv5" $ do 96 let lut = BL.fromStrict hmv5_put 97 out = BS.take 32 $ B16.encode (SHA256.hmac_lazy hmv5_key lut) 98 assertEqual mempty hmv5_pec out 99 , testCase "hmv6" $ do 100 let lut = BL.fromStrict hmv6_put 101 out = B16.encode (SHA256.hmac_lazy hmv6_key lut) 102 assertEqual mempty hmv6_pec out 103 , testCase "hmv7" $ do 104 let lut = BL.fromStrict hmv7_put 105 out = B16.encode (SHA256.hmac_lazy hmv7_key lut) 106 assertEqual mempty hmv7_pec out 107 ] 108 ] 109 110 -- vectors from 111 -- https://www.di-mgt.com.au/sha_testvectors.html 112 113 hv0_put, hv0_pec :: BS.ByteString 114 hv0_put = "abc" 115 hv0_pec = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" 116 117 hv1_put, hv1_pec :: BS.ByteString 118 hv1_put = mempty 119 hv1_pec = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 120 121 hv2_put, hv2_pec :: BS.ByteString 122 hv2_put = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 123 hv2_pec = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" 124 125 hv3_put, hv3_pec :: BS.ByteString 126 hv3_put = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" 127 hv3_pec = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1" 128 129 hv4_put, hv4_pec :: BS.ByteString 130 hv4_put = BS.replicate 1000000 0x61 131 hv4_pec = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0" 132 133 big_input :: BL.ByteString 134 big_input = go (16777216 :: Int) mempty where 135 go j acc 136 | j == 0 = BSB.toLazyByteString acc 137 | otherwise = 138 let nacc = acc <> BSB.lazyByteString 139 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" 140 in go (pred j) nacc 141 142 hv5_put :: BL.ByteString 143 hv5_put = big_input 144 145 hv5_pec :: BS.ByteString 146 hv5_pec = "50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e" 147 148 -- vectors from 149 -- https://datatracker.ietf.org/doc/html/rfc4231#section-4.1 150 151 hmv1_key :: BS.ByteString 152 hmv1_key = B16.decodeLenient "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" 153 154 hmv1_put :: BS.ByteString 155 hmv1_put = "Hi There" 156 157 hmv1_pec :: BS.ByteString 158 hmv1_pec = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7" 159 160 hmv2_key :: BS.ByteString 161 hmv2_key = "Jefe" 162 163 hmv2_put :: BS.ByteString 164 hmv2_put = "what do ya want for nothing?" 165 166 hmv2_pec :: BS.ByteString 167 hmv2_pec = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843" 168 169 hmv3_key :: BS.ByteString 170 hmv3_key = B16.decodeLenient "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 171 172 hmv3_put :: BS.ByteString 173 hmv3_put = B16.decodeLenient "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" 174 175 hmv3_pec :: BS.ByteString 176 hmv3_pec = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe" 177 178 hmv4_key :: BS.ByteString 179 hmv4_key = B16.decodeLenient "0102030405060708090a0b0c0d0e0f10111213141516171819" 180 181 hmv4_put :: BS.ByteString 182 hmv4_put = B16.decodeLenient "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" 183 184 hmv4_pec :: BS.ByteString 185 hmv4_pec = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b" 186 187 hmv5_key :: BS.ByteString 188 hmv5_key = B16.decodeLenient "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c" 189 190 hmv5_put :: BS.ByteString 191 hmv5_put = "Test With Truncation" 192 193 hmv5_pec :: BS.ByteString 194 hmv5_pec = "a3b6167473100ee06e0c796c2955552b" 195 196 hmv6_key :: BS.ByteString 197 hmv6_key = B16.decodeLenient "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 198 199 hmv6_put :: BS.ByteString 200 hmv6_put = "Test Using Larger Than Block-Size Key - Hash Key First" 201 202 hmv6_pec :: BS.ByteString 203 hmv6_pec = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54" 204 205 hmv7_key :: BS.ByteString 206 hmv7_key = hmv6_key 207 208 hmv7_put :: BS.ByteString 209 hmv7_put = "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm." 210 211 hmv7_pec :: BS.ByteString 212 hmv7_pec = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2" 213 214 cmp_hash :: String -> BS.ByteString -> BS.ByteString -> TestTree 215 cmp_hash msg put pec = testCase msg $ do 216 let out = B16.encode (SHA256.hash put) 217 assertEqual mempty pec out 218 219 cmp_hash_lazy :: String -> BS.ByteString -> BS.ByteString -> TestTree 220 cmp_hash_lazy msg (BL.fromStrict -> put) pec = testCase msg $ do 221 let out = B16.encode (SHA256.hash_lazy put) 222 assertEqual mempty pec out 223 224 cmp_hmac 225 :: String -> BS.ByteString -> BS.ByteString -> BS.ByteString -> TestTree 226 cmp_hmac msg key put pec = testCase msg $ do 227 let out = B16.encode (SHA256.hmac key put) 228 assertEqual mempty pec out 229 230 cmp_hmac_lazy 231 :: String -> BS.ByteString -> BS.ByteString -> BS.ByteString -> TestTree 232 cmp_hmac_lazy msg key (BL.fromStrict -> put) pec = testCase msg $ do 233 let out = B16.encode (SHA256.hmac_lazy key put) 234 assertEqual mempty pec out 235