crypton-2.0.0: tests/StreamCipher/ChaChaSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module StreamCipher.ChaChaSpec (spec) where
import qualified Crypto.Cipher.ChaCha as ChaCha
import Crypto.Hash (Digest, SHA256, hash)
import qualified Data.ByteArray as BA
import Imports
import qualified Data.ByteString as B
b8_128_k0_i0 =
"\xe2\x8a\x5f\xa4\xa6\x7f\x8c\x5d\xef\xed\x3e\x6f\xb7\x30\x34\x86\xaa\x84\x27\xd3\x14\x19\xa7\x29\x57\x2d\x77\x79\x53\x49\x11\x20\xb6\x4a\xb8\xe7\x2b\x8d\xeb\x85\xcd\x6a\xea\x7c\xb6\x08\x9a\x10\x18\x24\xbe\xeb\x08\x81\x4a\x42\x8a\xab\x1f\xa2\xc8\x16\x08\x1b\x8a\x26\xaf\x44\x8a\x1b\xa9\x06\x36\x8f\xd8\xc8\x38\x31\xc1\x8c\xec\x8c\xed\x81\x1a\x02\x8e\x67\x5b\x8d\x2b\xe8\xfc\xe0\x81\x16\x5c\xea\xe9\xf1\xd1\xb7\xa9\x75\x49\x77\x49\x48\x05\x69\xce\xb8\x3d\xe6\xa0\xa5\x87\xd4\x98\x4f\x19\x92\x5f\x5d\x33\x8e\x43\x0d"
b12_128_k0_i0 =
"\xe1\x04\x7b\xa9\x47\x6b\xf8\xff\x31\x2c\x01\xb4\x34\x5a\x7d\x8c\xa5\x79\x2b\x0a\xd4\x67\x31\x3f\x1d\xc4\x12\xb5\xfd\xce\x32\x41\x0d\xea\x8b\x68\xbd\x77\x4c\x36\xa9\x20\xf0\x92\xa0\x4d\x3f\x95\x27\x4f\xbe\xff\x97\xbc\x84\x91\xfc\xef\x37\xf8\x59\x70\xb4\x50\x1d\x43\xb6\x1a\x8f\x7e\x19\xfc\xed\xde\xf3\x68\xae\x6b\xfb\x11\x10\x1b\xd9\xfd\x3e\x4d\x12\x7d\xe3\x0d\xb2\xdb\x1b\x47\x2e\x76\x42\x68\x03\xa4\x5e\x15\xb9\x62\x75\x19\x86\xef\x1d\x9d\x50\xf5\x98\xa5\xdc\xdc\x9f\xa5\x29\xa2\x83\x57\x99\x1e\x78\x4e\xa2\x0f"
b20_128_k0_i0 =
"\x89\x67\x09\x52\x60\x83\x64\xfd\x00\xb2\xf9\x09\x36\xf0\x31\xc8\xe7\x56\xe1\x5d\xba\x04\xb8\x49\x3d\x00\x42\x92\x59\xb2\x0f\x46\xcc\x04\xf1\x11\x24\x6b\x6c\x2c\xe0\x66\xbe\x3b\xfb\x32\xd9\xaa\x0f\xdd\xfb\xc1\x21\x23\xd4\xb9\xe4\x4f\x34\xdc\xa0\x5a\x10\x3f\x6c\xd1\x35\xc2\x87\x8c\x83\x2b\x58\x96\xb1\x34\xf6\x14\x2a\x9d\x4d\x8d\x0d\x8f\x10\x26\xd2\x0a\x0a\x81\x51\x2c\xbc\xe6\xe9\x75\x8a\x71\x43\xd0\x21\x97\x80\x22\xa3\x84\x14\x1a\x80\xce\xa3\x06\x2f\x41\xf6\x7a\x75\x2e\x66\xad\x34\x11\x98\x4c\x78\x7e\x30\xad"
b8_256_k0_i0 =
"\x3e\x00\xef\x2f\x89\x5f\x40\xd6\x7f\x5b\xb8\xe8\x1f\x09\xa5\xa1\x2c\x84\x0e\xc3\xce\x9a\x7f\x3b\x18\x1b\xe1\x88\xef\x71\x1a\x1e\x98\x4c\xe1\x72\xb9\x21\x6f\x41\x9f\x44\x53\x67\x45\x6d\x56\x19\x31\x4a\x42\xa3\xda\x86\xb0\x01\x38\x7b\xfd\xb8\x0e\x0c\xfe\x42\xd2\xae\xfa\x0d\xea\xa5\xc1\x51\xbf\x0a\xdb\x6c\x01\xf2\xa5\xad\xc0\xfd\x58\x12\x59\xf9\xa2\xaa\xdc\xf2\x0f\x8f\xd5\x66\xa2\x6b\x50\x32\xec\x38\xbb\xc5\xda\x98\xee\x0c\x6f\x56\x8b\x87\x2a\x65\xa0\x8a\xbf\x25\x1d\xeb\x21\xbb\x4b\x56\xe5\xd8\x82\x1e\x68\xaa"
b12_256_k0_i0 =
"\x9b\xf4\x9a\x6a\x07\x55\xf9\x53\x81\x1f\xce\x12\x5f\x26\x83\xd5\x04\x29\xc3\xbb\x49\xe0\x74\x14\x7e\x00\x89\xa5\x2e\xae\x15\x5f\x05\x64\xf8\x79\xd2\x7a\xe3\xc0\x2c\xe8\x28\x34\xac\xfa\x8c\x79\x3a\x62\x9f\x2c\xa0\xde\x69\x19\x61\x0b\xe8\x2f\x41\x13\x26\xbe\x0b\xd5\x88\x41\x20\x3e\x74\xfe\x86\xfc\x71\x33\x8c\xe0\x17\x3d\xc6\x28\xeb\xb7\x19\xbd\xcb\xcc\x15\x15\x85\x21\x4c\xc0\x89\xb4\x42\x25\x8d\xcd\xa1\x4c\xf1\x11\xc6\x02\xb8\x97\x1b\x8c\xc8\x43\xe9\x1e\x46\xca\x90\x51\x51\xc0\x27\x44\xa6\xb0\x17\xe6\x93\x16"
b20_256_k0_i0 =
"\x76\xb8\xe0\xad\xa0\xf1\x3d\x90\x40\x5d\x6a\xe5\x53\x86\xbd\x28\xbd\xd2\x19\xb8\xa0\x8d\xed\x1a\xa8\x36\xef\xcc\x8b\x77\x0d\xc7\xda\x41\x59\x7c\x51\x57\x48\x8d\x77\x24\xe0\x3f\xb8\xd8\x4a\x37\x6a\x43\xb8\xf4\x15\x18\xa1\x1c\xc3\x87\xb6\x69\xb2\xee\x65\x86\x9f\x07\xe7\xbe\x55\x51\x38\x7a\x98\xba\x97\x7c\x73\x2d\x08\x0d\xcb\x0f\x29\xa0\x48\xe3\x65\x69\x12\xc6\x53\x3e\x32\xee\x7a\xed\x29\xb7\x21\x76\x9c\xe6\x4e\x43\xd5\x71\x33\xb0\x74\xd8\x39\xd5\x31\xed\x1f\x28\x51\x0a\xfb\x45\xac\xe1\x0a\x1f\x4b\x79\x4d\x6f"
-- XChaCha20 test vector from RFC draft: https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha
xChaCha20_ExampleKAT = fst (ChaCha.combine initState plaintext) `shouldBe` expected
where
iv = B.pack $ [0x40 .. 0x56] ++ [0x58]
key = B.pack [0x80 .. 0x9f]
initState = ChaCha.initializeX 20 key iv
plaintext :: B.ByteString
plaintext =
"The dhole (pronounced \"dole\") is also known as the Asiatic wild dog, red dog, and whistling dog. It is about the size of a German shepherd but looks more like a long-legged fox. This highly elusive and skilled jumper is classified with wolves, coyotes, jackals, and foxes in the taxonomic family Canidae."
expected :: B.ByteString
expected =
"\x45\x59\xab\xba\x4e\x48\xc1\x61\x02\xe8\xbb\x2c\x05\xe6\x94\x7f\x50\xa7\x86\xde\x16\x2f\x9b\x0b\x7e\x59\x2a\x9b\x53\xd0\xd4\xe9\x8d\x8d\x64\x10\xd5\x40\xa1\xa6\x37\x5b\x26\xd8\x0d\xac\xe4\xfa\xb5\x23\x84\xc7\x31\xac\xbf\x16\xa5\x92\x3c\x0c\x48\xd3\x57\x5d\x4d\x0d\x2c\x67\x3b\x66\x6f\xaa\x73\x10\x61\x27\x77\x01\x09\x3a\x6b\xf7\xa1\x58\xa8\x86\x42\x92\xa4\x1c\x48\xe3\xa9\xb4\xc0\xda\xec\xe0\xf8\xd9\x8d\x0d\x7e\x05\xb3\x7a\x30\x7b\xbb\x66\x33\x31\x64\xec\x9e\x1b\x24\xea\x0d\x6c\x3f\xfd\xdc\xec\x4f\x68\xe7\x44\x30\x56\x19\x3a\x03\xc8\x10\xe1\x13\x44\xca\x06\xd8\xed\x8a\x2b\xfb\x1e\x8d\x48\xcf\xa6\xbc\x0e\xb4\xe2\x46\x4b\x74\x81\x42\x40\x7c\x9f\x43\x1a\xee\x76\x99\x60\xe1\x5b\xa8\xb9\x68\x90\x46\x6e\xf2\x45\x75\x99\x85\x23\x85\xc6\x61\xf7\x52\xce\x20\xf9\xda\x0c\x09\xab\x6b\x19\xdf\x74\xe7\x6a\x95\x96\x74\x46\xf8\xd0\xfd\x41\x5e\x7b\xee\x2a\x12\xa1\x14\xc2\x0e\xb5\x29\x2a\xe7\xa3\x49\xae\x57\x78\x20\xd5\x52\x0a\x1f\x3f\xb6\x2a\x17\xce\x6a\x7e\x68\xfa\x7c\x79\x11\x1d\x88\x60\x92\x0b\xc0\x48\xef\x43\xfe\x84\x48\x6c\xcb\x87\xc2\x5f\x0a\xe0\x45\xf0\xcc\xe1\xe7\x98\x9a\x9a\xa2\x20\xa2\x8b\xdd\x48\x27\xe7\x51\xa2\x4a\x6d\x5c\x62\xd7\x90\xa6\x63\x93\xb9\x31\x11\xc1\xa5\x5d\xd7\x42\x1a\x10\x18\x49\x74\xc7\xc5"
rfc8439A2_1 = cipher' `shouldBe` cipher
where
key :: ByteString
key =
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
nonce :: ByteString
nonce = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
plain :: ByteString
plain =
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
cipher :: ByteString
cipher =
"\x76\xb8\xe0\xad\xa0\xf1\x3d\x90\x40\x5d\x6a\xe5\x53\x86\xbd\x28\xbd\xd2\x19\xb8\xa0\x8d\xed\x1a\xa8\x36\xef\xcc\x8b\x77\x0d\xc7\xda\x41\x59\x7c\x51\x57\x48\x8d\x77\x24\xe0\x3f\xb8\xd8\x4a\x37\x6a\x43\xb8\xf4\x15\x18\xa1\x1c\xc3\x87\xb6\x69\xb2\xee\x65\x86"
cipher' = fst $ ChaCha.combine (ChaCha.initialize 20 key nonce) plain
rfc8439A2_2 = cipher' `shouldBe` cipher
where
key :: ByteString
key =
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
nonce :: ByteString
nonce = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
plain :: ByteString
plain =
"\x41\x6e\x79\x20\x73\x75\x62\x6d\x69\x73\x73\x69\x6f\x6e\x20\x74\x6f\x20\x74\x68\x65\x20\x49\x45\x54\x46\x20\x69\x6e\x74\x65\x6e\x64\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x43\x6f\x6e\x74\x72\x69\x62\x75\x74\x6f\x72\x20\x66\x6f\x72\x20\x70\x75\x62\x6c\x69\x63\x61\x74\x69\x6f\x6e\x20\x61\x73\x20\x61\x6c\x6c\x20\x6f\x72\x20\x70\x61\x72\x74\x20\x6f\x66\x20\x61\x6e\x20\x49\x45\x54\x46\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x20\x6f\x72\x20\x52\x46\x43\x20\x61\x6e\x64\x20\x61\x6e\x79\x20\x73\x74\x61\x74\x65\x6d\x65\x6e\x74\x20\x6d\x61\x64\x65\x20\x77\x69\x74\x68\x69\x6e\x20\x74\x68\x65\x20\x63\x6f\x6e\x74\x65\x78\x74\x20\x6f\x66\x20\x61\x6e\x20\x49\x45\x54\x46\x20\x61\x63\x74\x69\x76\x69\x74\x79\x20\x69\x73\x20\x63\x6f\x6e\x73\x69\x64\x65\x72\x65\x64\x20\x61\x6e\x20\x22\x49\x45\x54\x46\x20\x43\x6f\x6e\x74\x72\x69\x62\x75\x74\x69\x6f\x6e\x22\x2e\x20\x53\x75\x63\x68\x20\x73\x74\x61\x74\x65\x6d\x65\x6e\x74\x73\x20\x69\x6e\x63\x6c\x75\x64\x65\x20\x6f\x72\x61\x6c\x20\x73\x74\x61\x74\x65\x6d\x65\x6e\x74\x73\x20\x69\x6e\x20\x49\x45\x54\x46\x20\x73\x65\x73\x73\x69\x6f\x6e\x73\x2c\x20\x61\x73\x20\x77\x65\x6c\x6c\x20\x61\x73\x20\x77\x72\x69\x74\x74\x65\x6e\x20\x61\x6e\x64\x20\x65\x6c\x65\x63\x74\x72\x6f\x6e\x69\x63\x20\x63\x6f\x6d\x6d\x75\x6e\x69\x63\x61\x74\x69\x6f\x6e\x73\x20\x6d\x61\x64\x65\x20\x61\x74\x20\x61\x6e\x79\x20\x74\x69\x6d\x65\x20\x6f\x72\x20\x70\x6c\x61\x63\x65\x2c\x20\x77\x68\x69\x63\x68\x20\x61\x72\x65\x20\x61\x64\x64\x72\x65\x73\x73\x65\x64\x20\x74\x6f"
cipher :: ByteString
cipher =
"\xa3\xfb\xf0\x7d\xf3\xfa\x2f\xde\x4f\x37\x6c\xa2\x3e\x82\x73\x70\x41\x60\x5d\x9f\x4f\x4f\x57\xbd\x8c\xff\x2c\x1d\x4b\x79\x55\xec\x2a\x97\x94\x8b\xd3\x72\x29\x15\xc8\xf3\xd3\x37\xf7\xd3\x70\x05\x0e\x9e\x96\xd6\x47\xb7\xc3\x9f\x56\xe0\x31\xca\x5e\xb6\x25\x0d\x40\x42\xe0\x27\x85\xec\xec\xfa\x4b\x4b\xb5\xe8\xea\xd0\x44\x0e\x20\xb6\xe8\xdb\x09\xd8\x81\xa7\xc6\x13\x2f\x42\x0e\x52\x79\x50\x42\xbd\xfa\x77\x73\xd8\xa9\x05\x14\x47\xb3\x29\x1c\xe1\x41\x1c\x68\x04\x65\x55\x2a\xa6\xc4\x05\xb7\x76\x4d\x5e\x87\xbe\xa8\x5a\xd0\x0f\x84\x49\xed\x8f\x72\xd0\xd6\x62\xab\x05\x26\x91\xca\x66\x42\x4b\xc8\x6d\x2d\xf8\x0e\xa4\x1f\x43\xab\xf9\x37\xd3\x25\x9d\xc4\xb2\xd0\xdf\xb4\x8a\x6c\x91\x39\xdd\xd7\xf7\x69\x66\xe9\x28\xe6\x35\x55\x3b\xa7\x6c\x5c\x87\x9d\x7b\x35\xd4\x9e\xb2\xe6\x2b\x08\x71\xcd\xac\x63\x89\x39\xe2\x5e\x8a\x1e\x0e\xf9\xd5\x28\x0f\xa8\xca\x32\x8b\x35\x1c\x3c\x76\x59\x89\xcb\xcf\x3d\xaa\x8b\x6c\xcc\x3a\xaf\x9f\x39\x79\xc9\x2b\x37\x20\xfc\x88\xdc\x95\xed\x84\xa1\xbe\x05\x9c\x64\x99\xb9\xfd\xa2\x36\xe7\xe8\x18\xb0\x4b\x0b\xc3\x9c\x1e\x87\x6b\x19\x3b\xfe\x55\x69\x75\x3f\x88\x12\x8c\xc0\x8a\xaa\x9b\x63\xd1\xa1\x6f\x80\xef\x25\x54\xd7\x18\x9c\x41\x1f\x58\x69\xca\x52\xc5\xb8\x3f\xa3\x6f\xf2\x16\xb9\xc1\xd3\x00\x62\xbe\xbc\xfd\x2d\xc5\xbc\xe0\x91\x19\x34\xfd\xa7\x9a\x86\xf6\xe6\x98\xce\xd7\x59\xc3\xff\x9b\x64\x77\x33\x8f\x3d\xa4\xf9\xcd\x85\x14\xea\x99\x82\xcc\xaf\xb3\x41\xb2\x38\x4d\xd9\x02\xf3\xd1\xab\x7a\xc6\x1d\xd2\x9c\x6f\x21\xba\x5b\x86\x2f\x37\x30\xe3\x7c\xfd\xc4\xfd\x80\x6c\x22\xf2\x21"
cipher' =
fst $
ChaCha.combine (ChaCha.setCounter32 1 (ChaCha.initialize 20 key nonce)) plain
rfc8439A2_3 = cipher' `shouldBe` cipher
where
key :: ByteString
key =
"\x1c\x92\x40\xa5\xeb\x55\xd3\x8a\xf3\x33\x88\x86\x04\xf6\xb5\xf0\x47\x39\x17\xc1\x40\x2b\x80\x09\x9d\xca\x5c\xbc\x20\x70\x75\xc0"
nonce :: ByteString
nonce = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
plain :: ByteString
plain =
"\x27\x54\x77\x61\x73\x20\x62\x72\x69\x6c\x6c\x69\x67\x2c\x20\x61\x6e\x64\x20\x74\x68\x65\x20\x73\x6c\x69\x74\x68\x79\x20\x74\x6f\x76\x65\x73\x0a\x44\x69\x64\x20\x67\x79\x72\x65\x20\x61\x6e\x64\x20\x67\x69\x6d\x62\x6c\x65\x20\x69\x6e\x20\x74\x68\x65\x20\x77\x61\x62\x65\x3a\x0a\x41\x6c\x6c\x20\x6d\x69\x6d\x73\x79\x20\x77\x65\x72\x65\x20\x74\x68\x65\x20\x62\x6f\x72\x6f\x67\x6f\x76\x65\x73\x2c\x0a\x41\x6e\x64\x20\x74\x68\x65\x20\x6d\x6f\x6d\x65\x20\x72\x61\x74\x68\x73\x20\x6f\x75\x74\x67\x72\x61\x62\x65\x2e"
cipher :: ByteString
cipher =
"\x62\xe6\x34\x7f\x95\xed\x87\xa4\x5f\xfa\xe7\x42\x6f\x27\xa1\xdf\x5f\xb6\x91\x10\x04\x4c\x0d\x73\x11\x8e\xff\xa9\x5b\x01\xe5\xcf\x16\x6d\x3d\xf2\xd7\x21\xca\xf9\xb2\x1e\x5f\xb1\x4c\x61\x68\x71\xfd\x84\xc5\x4f\x9d\x65\xb2\x83\x19\x6c\x7f\xe4\xf6\x05\x53\xeb\xf3\x9c\x64\x02\xc4\x22\x34\xe3\x2a\x35\x6b\x3e\x76\x43\x12\xa6\x1a\x55\x32\x05\x57\x16\xea\xd6\x96\x25\x68\xf8\x7d\x3f\x3f\x77\x04\xc6\xa8\xd1\xbc\xd1\xbf\x4d\x50\xd6\x15\x4b\x6d\xa7\x31\xb1\x87\xb5\x8d\xfd\x72\x8a\xfa\x36\x75\x7a\x79\x7a\xc1\x88\xd1"
cipher' =
fst $
ChaCha.combine (ChaCha.setCounter32 42 (ChaCha.initialize 20 key nonce)) plain
data Vector
= Vector
Int -- rounds
ByteString -- key
ByteString -- nonce
deriving (Show, Eq)
-- The key length decides which of the two sets of constants the state is
-- built from, the nonce length whether the counter is 32 or 64 bits wide,
-- and the vector code paths are entered only at 20 rounds, so the
-- properties below are worth running over all of them rather than over one
-- corner.
instance Arbitrary Vector where
arbitrary =
Vector
<$> elements [8, 12, 20]
<*> (arbitraryBS =<< elements [16, 32])
<*> (arbitraryBS =<< elements [8, 12])
-- | The keystream at lengths either side of the boundaries the bulk loops
-- have -- 192 bytes, where the vector code starts, 320 where it takes five
-- blocks at a time, and 512 where it takes six -- and at counters that are
-- not zero. The expected values are the SHA-256 of the keystream, from
-- OpenSSL 3.6.4 through EVP.
longVectors :: [(Word32, Int, ByteString)]
longVectors =
[
( 0
, 191
, "\x00\xd8\x21\x8c\x32\x59\xc5\x2e\xce\xc5\x72\xbf\x80\x73\x10\x5e\xdd\x01\x9f\xce\x8f\xc0\x0c\x31\x92\xd1\x1c\x97\x88\x5e\xf3\x6a"
)
,
( 0
, 192
, "\x21\x3f\x43\x21\x3a\x5d\xf2\x19\xf3\x25\x4c\x50\x7e\x09\x91\x78\x1d\xa7\x3e\x36\xe0\x40\x56\x9c\x9a\x88\x94\x8d\x80\xf8\x82\xb0"
)
,
( 0
, 193
, "\xf9\xf3\x5b\xb4\xe7\x20\x6c\xd9\xb7\xd3\x9d\xbb\x73\x1d\x0a\xbf\x98\x4d\xbe\x20\x20\x69\x77\x30\xe9\x33\x5e\xf2\x47\x9e\x16\x27"
)
,
( 0
, 255
, "\x2b\x14\xaa\x0e\xba\xf8\x28\x96\xc0\x58\x9a\x7f\x96\x82\x30\x9c\x6c\x58\x16\x56\xc1\xcc\xb5\xcc\xd1\x3e\x3b\x41\xd4\x0c\xe0\x62"
)
,
( 0
, 256
, "\x0e\x92\x3a\x76\xc5\x25\x4f\x1e\xb3\x53\x29\xa7\x93\x79\x44\x6b\x72\x5c\x1b\x68\xc0\xf4\x23\x7a\xf5\x2f\xfd\x82\x1f\x72\xda\xe2"
)
,
( 0
, 320
, "\xf4\xd3\xef\xfe\x43\xec\x46\x78\xa0\x66\x80\x5a\x3e\xb7\x12\x74\x04\x6c\x5e\x30\x40\xf9\xaf\xc2\xe0\xc1\xe0\x52\x50\x36\x6d\xa5"
)
,
( 0
, 383
, "\x30\xab\x6f\x23\xd3\x55\xbc\x2b\x3b\xc3\x9f\x19\x0f\x1a\x58\x19\x19\x4a\x0e\x58\xbc\x50\xd3\x05\x22\x47\x9c\x42\x2e\x23\x8d\x67"
)
,
( 0
, 384
, "\x9f\x4c\x9e\x6f\x16\xf2\x2c\xce\xb1\x1c\x0c\x98\xa9\x64\xf1\x53\x47\xc0\x64\x67\xf6\xb4\x55\x80\x64\x35\xf1\x34\xa9\x77\x99\x90"
)
,
( 0
, 447
, "\x25\x40\xa9\xc0\x66\x18\x9e\x62\xb6\x14\xad\xf5\x00\x2c\x12\xdc\x03\x8a\x38\xb5\xe9\x43\x50\x10\x19\xf0\x16\xa7\x0b\xb4\x04\x7a"
)
,
( 0
, 448
, "\x39\xcc\x80\x48\xb9\x2b\x18\x88\xf5\xa3\x70\x06\xd9\x54\xa1\x33\xb0\x82\x9a\xff\x80\x34\xb2\x63\xfa\xf5\x9c\x18\xda\x4d\xed\x9c"
)
,
( 0
, 511
, "\x6d\xf5\xc5\x31\x38\xc8\x8e\x52\x5b\xe0\x26\x70\xfb\xb3\xef\x77\x50\xe5\x32\x7d\x5a\x21\xde\x3f\x79\x8e\x95\x0b\x23\x7f\x10\x12"
)
,
( 0
, 512
, "\xf0\x38\x11\xa6\x94\x7d\xe9\x42\x63\x49\x0b\x11\x32\x24\x0c\x7d\x46\xab\xd4\x64\x51\x13\x0d\x86\x04\x20\x29\xd0\xda\xe6\x83\x04"
)
,
( 0
, 513
, "\x6a\x4b\x18\xb8\x4e\x67\xca\xac\x64\xe7\x9d\xd0\x0a\x01\x97\x9a\x64\x95\xc4\xe8\x7f\xbd\xe9\xb4\x4a\x24\x8d\xd4\x12\x4b\x24\xf0"
)
,
( 0
, 576
, "\xe3\x17\xfc\x20\x12\x1d\x70\x36\x29\xec\xef\x79\x0e\xba\xf9\xdf\x9b\x09\x35\xc7\x7d\x6c\x88\x8f\x81\xcf\x98\xc7\x42\x88\xe5\x48"
)
,
( 0
, 640
, "\x73\x38\xfe\x4f\x7f\x36\xbb\x15\xb1\x40\x46\xa8\xab\x66\x66\x9c\x6c\x2e\x2a\x7e\x37\xa1\x58\xa0\x39\x27\xe3\xf9\x79\x9a\xd4\xe6"
)
,
( 0
, 704
, "\x8a\x38\x79\x32\xfd\x3f\xcb\xb1\xec\x0e\x4f\xe3\xdb\xd3\x31\x75\x74\xdb\x69\x20\xaa\xd3\x4b\x69\xa2\xe6\x4e\xcb\xfd\x12\xfb\x8b"
)
,
( 0
, 1024
, "\x45\x20\xf2\xe8\xee\x19\xee\x25\xcc\x50\x45\x03\x51\x65\x7b\x81\x25\xbe\x47\x27\x5d\x8e\x88\x5b\x6f\x76\xc5\x6d\x62\x68\x9d\x63"
)
,
( 0
, 2048
, "\xd0\x5c\xe9\x7f\x18\x46\x93\x0b\xd3\xa4\x5c\x15\xf2\xdf\xf7\x7f\x29\xcc\x01\xb5\x48\x55\x10\x41\x94\x1d\xc5\x1e\x2f\xc2\x26\x88"
)
,
( 0
, 4096
, "\x71\x05\xec\x3f\x33\xb9\xe9\x07\x05\x9c\xc5\x30\xec\x41\xb0\x09\xcd\x3d\x8a\xe6\x7b\x88\x3a\xeb\xf4\xea\x53\xee\x42\xea\x2d\x3c"
)
,
( 0
, 8192
, "\x05\x62\x0c\x5d\xc9\xc4\x23\xd2\xb8\x14\x46\xc3\xad\xbf\x17\x5a\xfb\x7c\xd0\xa5\xcc\xc2\x8e\x60\x68\x6b\x77\x97\x47\x44\x8d\x96"
)
,
( 0
, 12288
, "\x09\x67\xf7\x03\x07\x6f\xb6\xb5\xe7\xcd\xaf\x4b\x8c\xad\x66\x39\x41\x99\x72\xd3\x06\xae\x20\x88\xd6\x0c\xd6\x52\x1e\x7e\x5f\xc3"
)
,
( 1
, 191
, "\xf2\x7e\x48\x8b\x09\xfd\xf6\xb8\xbc\x30\xe1\xba\x49\xa0\xff\x51\x29\xe0\x8f\xf0\xfb\x47\x5f\xa4\xbf\x74\x08\x9d\x49\x0e\x04\x3c"
)
,
( 1
, 192
, "\x14\x36\x48\xb5\xbe\xa7\xf8\xb1\x5b\xfb\xaf\xc1\x61\x8e\x02\x19\x80\x4c\xfa\xdc\xa1\xc0\xde\xf4\x81\xc6\xdd\xfe\x95\x87\x12\x94"
)
,
( 1
, 193
, "\x31\x64\xcd\xc8\x37\x13\xe5\xbc\x3e\x47\x03\xb2\xa0\xac\x78\x79\xb7\x67\x06\xfd\x63\x70\xa8\x26\xb5\xeb\xfc\xb8\x2c\xb4\x30\x46"
)
,
( 1
, 255
, "\xff\xdb\x93\x0d\x04\x5d\xfb\xd0\xce\x68\x8a\xb9\x71\x11\xbc\xdd\x2e\xf0\x8e\xeb\xbf\xd1\x29\x4e\x86\x3f\x67\x3f\x7d\x4d\xd5\xd0"
)
,
( 1
, 256
, "\xa6\x91\xf4\x64\x38\x29\x5c\x67\x7a\xd3\x59\x54\x2c\x77\x89\x23\x13\x9b\x38\xda\x9d\x2c\x04\x83\x34\x38\x6d\x0e\x84\x43\x10\xae"
)
,
( 1
, 320
, "\xff\xf0\x79\x6f\x40\x95\xa6\x30\xfa\x3d\x93\x8c\x1a\xe1\x43\x4c\xfe\x70\x75\x80\xe5\x1e\x2b\x58\xf6\x20\xd0\x22\xa9\xbd\xfa\x0a"
)
,
( 1
, 383
, "\xed\xf0\x30\xf2\x34\x53\xb6\x41\x6d\xd1\xdf\x76\xce\xee\xda\x2a\x13\xf2\xb4\xb4\xee\x1f\xde\xc5\x3f\x05\xd2\x57\xe6\xed\x99\xd0"
)
,
( 1
, 384
, "\xb3\x87\x2d\x6b\xa8\x30\xd5\x3f\x08\xc8\x53\x89\x06\xea\xb1\xb2\x42\x90\xbd\x2d\x15\xa1\x64\xbd\xcf\xe2\xa9\x5e\xa4\x28\x98\xfc"
)
,
( 1
, 447
, "\x7c\x73\x0d\xdf\xae\x6d\x29\x16\x24\xdd\x99\x8a\xc1\x33\x7d\xaf\x13\x7b\x89\x6f\xad\x9f\x72\xeb\x7d\x1a\x49\xde\x5b\xee\x41\x82"
)
,
( 1
, 448
, "\x83\x8a\x55\x1e\x18\x0e\x39\x7e\x65\xee\x91\x1e\x30\xfb\x95\x74\xcc\x49\x45\xbd\x38\x2f\xb6\xc0\xb1\x0e\x0b\x79\x83\x73\xf9\x30"
)
,
( 1
, 511
, "\x63\x7a\x92\x5b\x5a\x98\x2d\xa9\xa6\xb6\x91\x6e\x79\x9e\x28\x6a\xc9\x4f\x3e\xe8\x50\x2f\xf7\xdb\xef\xe2\x02\x6f\x65\xd5\x0a\x84"
)
,
( 1
, 512
, "\x37\xa0\xb2\x08\x93\xb3\xd3\xf8\xcd\xfa\x76\xcb\x0a\x77\x99\x19\xb6\x80\x92\x89\x1a\x28\x32\x6b\x42\x96\x9e\xff\xbc\xbf\x80\x11"
)
,
( 1
, 513
, "\x60\x31\x68\x0c\x03\x89\xdd\x65\xb0\xfc\x1b\x8c\xa4\xec\x4f\x90\x7f\x25\xc0\x03\xf1\xde\x85\x77\xf4\x68\xc0\x4a\xe1\xf9\x00\x9b"
)
,
( 1
, 576
, "\xb0\xae\xd0\x02\xce\xa7\x61\xef\xf4\x48\x7d\x1f\x6f\x07\x17\x64\x0f\x72\x5b\xad\x2e\x1b\xc7\x6d\xf7\xee\x2b\xcf\xf4\xb4\x72\x5f"
)
,
( 1
, 640
, "\x82\xfc\x19\x96\x59\x37\x41\x8b\x6f\x12\x0d\xae\xfc\xa8\xce\xc7\x02\xbb\x7e\x6a\x66\x37\xf3\x8d\xc8\x86\xe6\x1d\x90\xb4\x4d\x67"
)
,
( 1
, 704
, "\xf5\x3c\x7c\xfa\x24\xee\x6f\x49\x79\x16\xdb\x8f\x72\x4a\x3d\xc8\x6c\x78\x42\x8b\xf0\x8d\xdd\x0d\x71\xff\x36\x74\xa6\xb7\x8a\xe6"
)
,
( 1
, 1024
, "\x23\xa1\xce\x21\x96\x72\x54\xa0\xeb\x3a\xbd\xbc\x24\xa2\xa9\x65\x93\x98\x74\x92\x6d\xe5\x56\xe7\xed\xa4\x17\x2b\xdc\x1c\x3f\x02"
)
,
( 1
, 2048
, "\x7d\x86\xa4\xb2\x82\x57\x78\x16\x38\x6f\x44\xed\x4a\x13\x50\x9c\x94\x12\x5d\x84\xf6\x3c\x09\x86\xf1\x94\x29\xe7\x10\x75\x54\xe5"
)
,
( 1
, 4096
, "\x4b\xd4\x83\xc4\x45\x2d\x54\x6a\x5b\x4e\xf8\xae\xcb\x87\x10\xfb\xda\xcd\x68\xbe\x95\xd0\x73\x44\xdb\xce\x25\x83\xd9\x6c\x72\xaf"
)
,
( 1
, 8192
, "\x43\x22\x12\x02\xd5\x94\x93\x26\x2f\xea\xc8\x82\xe2\xc2\x8a\x4c\x36\x10\xd3\x5c\x59\x82\x92\x27\x3a\x4f\x3a\x6c\x2a\x9a\x6f\xa2"
)
,
( 1
, 12288
, "\x00\x75\xab\x26\xfe\x8e\x9c\x2e\xcb\xa2\xcd\x16\x26\xd8\x88\x89\xe3\x9a\xeb\x2b\xb8\xbe\xb1\x7f\x46\x8a\x5a\x72\x38\x57\x88\xe4"
)
,
( 305419896
, 191
, "\x19\x27\x86\x98\xbf\xe8\x52\x42\x4a\x72\x76\xb8\xcf\x7f\x40\x2b\xf2\x41\x97\x39\xf4\x13\x7d\x62\x25\x8d\x5e\x32\x7b\x3e\x19\xe0"
)
,
( 305419896
, 192
, "\x6c\x17\x58\xd2\x31\xf9\x5f\x02\x82\x8a\x76\x32\x13\xd6\x9c\x32\xf0\x81\x6a\x6a\xe7\x43\x78\x19\xd9\x89\x8e\xda\x55\xa4\x7e\x06"
)
,
( 305419896
, 193
, "\x85\x4d\x53\xe9\x9a\x06\x20\x4e\x6e\x30\x5d\xa1\xab\x66\xc0\xb1\x85\xe7\x1b\xd6\xed\x1e\xa3\xd7\x13\x91\x28\x69\xb1\xf8\x6a\x32"
)
,
( 305419896
, 255
, "\x34\xb9\x16\x61\xca\xe0\xe7\x75\x55\x44\x54\x3d\x1f\xff\x93\xcb\x02\x89\xd1\x32\x48\xc1\x70\xa5\xa1\x6d\xfb\x07\xf4\xc2\x73\x6b"
)
,
( 305419896
, 256
, "\x36\x3b\x26\x10\x5c\xdc\x9d\xba\x59\xae\x8d\xe0\x92\xe5\xd9\xdc\x99\xd8\xa4\xa1\x68\xec\xfc\x1e\xce\x2a\x18\x8c\xb8\x56\xfb\xa9"
)
,
( 305419896
, 320
, "\x41\xb1\x29\x5e\x42\xe2\x3a\xfd\xdc\xeb\x09\xd2\x22\x62\xc0\xff\x44\x17\xa0\x54\xd7\x6e\x93\x77\xb4\xa1\xec\xe1\x62\x31\x5e\x43"
)
,
( 305419896
, 383
, "\xbc\xec\xe8\x44\x2d\x0d\x7c\x68\x67\x30\xa6\xbf\x42\x39\x75\x39\xda\x5c\x3b\xd0\x82\x98\xdf\xf1\xa6\x94\x3a\x1e\x45\xd0\x5e\x4b"
)
,
( 305419896
, 384
, "\xc4\xa0\x5c\x22\x3c\xed\xdf\x3c\xc8\x40\x9f\x15\x6e\x54\x7b\xaa\x46\x51\xa0\xf5\xbd\x5d\xba\x73\x86\xba\x41\x2f\x88\x21\x8c\x6a"
)
,
( 305419896
, 447
, "\xa6\x16\x3c\x57\xe3\xfc\x78\xe2\x1c\xaf\xef\x51\x81\xa3\x00\x2b\xfa\xe3\x3e\x97\x4c\xaf\x37\x6a\x3a\xb0\xe3\x31\x74\x97\x4d\x3b"
)
,
( 305419896
, 448
, "\xbf\xf8\xea\x06\x20\x99\xca\x63\x97\x88\xe3\xfe\xed\x9d\x59\x98\x52\xf2\xc0\x9e\xda\xb3\x91\xbd\x00\x05\x31\x0e\xc9\xa3\x5f\x7b"
)
,
( 305419896
, 511
, "\x38\x2c\x89\x65\x0f\x15\x33\x28\xb7\x07\xbc\xe0\x40\x28\x77\x75\x81\x3c\x77\x58\xe0\xa0\xe2\xb4\xf4\xd8\xb0\xce\xc6\x10\x45\x08"
)
,
( 305419896
, 512
, "\x87\x6f\xcc\xc1\xd9\x61\x56\xc5\x3c\x9d\xf0\x06\x8b\x12\xbf\x7c\xd5\x60\x2f\xa3\x20\x7b\x71\x3d\xdc\x30\x57\x74\x24\xa8\x2e\x18"
)
,
( 305419896
, 513
, "\x73\x1c\x5b\x67\x29\xb5\xcf\x59\xd1\x6e\x28\x2c\x8d\x99\x6f\xad\xbc\x42\xd7\xf7\xbd\x1b\x05\xc2\x04\x4d\x4e\x16\x52\x04\x27\x88"
)
,
( 305419896
, 576
, "\x1c\x63\x4a\x40\xcc\x65\x66\x57\x62\x52\xa3\xdf\x2a\x5a\x24\x01\xaa\x12\xf9\xf7\xa7\xf1\x13\xd5\xd4\x57\x26\x9b\xae\xf0\xc2\xc2"
)
,
( 305419896
, 640
, "\x31\x36\x49\xcc\x53\xba\x02\x7c\x1f\x73\xf8\x80\x75\xb9\x82\xef\xc2\x90\xaa\xb3\xba\x5a\x93\x1f\x59\x02\xf3\x1a\x86\xac\xe2\x7a"
)
,
( 305419896
, 704
, "\x02\xcb\x50\x33\xb9\x6d\x14\x20\x7f\xdb\xb9\x6a\x9c\x32\x75\x0f\x57\x4b\x3c\x8b\x77\xc7\x7e\x36\x2d\x86\x54\x6c\x3d\x34\x9c\xd9"
)
,
( 305419896
, 1024
, "\x47\x2e\x03\xd7\xec\x96\x19\xc5\x4e\x49\xa7\x9f\x4f\xb6\x1c\x3c\x33\xd9\x6b\x23\xb2\x61\x34\xf5\x24\x23\xcf\xe8\x00\x71\x89\xd6"
)
,
( 305419896
, 2048
, "\x55\xef\xa5\x8b\xb9\xbb\x9e\x94\xa3\x75\xb1\x40\x84\x4f\x55\x41\x12\xd0\x5f\x4f\x2d\xa3\xc8\xc7\x36\x78\x91\x4e\xba\x68\x91\xcb"
)
,
( 305419896
, 4096
, "\x2d\x31\xc3\x49\x9f\xc7\x6b\x99\x46\xf7\x8a\x64\xff\x7e\x70\x92\x83\x5f\x06\x03\xa7\xe3\x88\x83\x76\x2d\x3a\x78\x88\x4a\x11\x48"
)
,
( 305419896
, 8192
, "\x4c\xe7\x49\xa6\xd5\x80\x77\xd4\x9e\x9b\x77\xcd\x46\x33\x8c\x15\xae\x97\xc8\x63\x8e\x45\xcd\x40\x74\xe3\x92\x96\x7e\xab\xbb\xd0"
)
,
( 305419896
, 12288
, "\x47\x90\x36\xe5\x3d\xd1\x06\x37\x0e\x9d\xd6\x52\x7e\x78\x85\xd7\x4d\x9a\xb0\x4d\xc3\x13\xec\x8c\xc8\x08\xc6\xd2\x5a\xea\xc6\x3d"
)
]
longKey :: ByteString
longKey = B.pack [fromIntegral (0x40 + i) | i <- [0 .. 31 :: Int]]
longNonce :: ByteString
longNonce = B.pack [fromIntegral (0xf0 - i) | i <- [0 .. 11 :: Int]]
longTests :: Spec
longTests = describe "long keystream" $ mapM_ test longVectors
where
test (counter, len, expected) =
it (show len ++ " bytes from counter " ++ show counter) $ do
digest (fst (ChaCha.generate st len) :: ByteString) `shouldBe` expected
digest (fst (ChaCha.combine st (B.replicate len 0)) :: ByteString)
`shouldBe` expected
where
st =
ChaCha.setCounter32 counter $
ChaCha.initialize 20 longKey longNonce
digest bs = BA.convert (hash bs :: Digest SHA256) :: ByteString
-- The 32-bit counter carries into the word above it, which the bulk loops
-- must not do on their own account, so a message that runs over the carry
-- has to come out the same as the same message taken a block at a time.
counterCarry :: Spec
counterCarry =
describe "counter carry" $
mapM_ test [0xffffff00, 0xfffffff0, 0xfffffffe]
where
test counter =
it ("crossing 2^32 from " ++ show (counter :: Word32)) $
fst (ChaCha.combine st (B.replicate len 0))
`shouldBe` B.concat (blockAtATime len st)
where
len = 8192
st = ChaCha.setCounter32 counter (ChaCha.initialize 20 longKey longNonce)
blockAtATime 0 _ = []
blockAtATime n s =
let (c, next) = ChaCha.combine s (B.replicate (min 64 n) 0)
in c : blockAtATime (n - min 64 n) next
spec :: Spec
spec = do
it "8-128-K0-I0" (chachaRunSimple b8_128_k0_i0 8 16 8)
it "12-128-K0-I0" (chachaRunSimple b12_128_k0_i0 12 16 8)
it "20-128-K0-I0" (chachaRunSimple b20_128_k0_i0 20 16 8)
it "8-256-K0-I0" (chachaRunSimple b8_256_k0_i0 8 32 8)
it "12-256-K0-I0" (chachaRunSimple b12_256_k0_i0 12 32 8)
it "20-256-K0-I0" (chachaRunSimple b20_256_k0_i0 20 32 8)
it "XChaCha20 example KAT" xChaCha20_ExampleKAT
it "RFC 8439 A2 #1 ChaCha20" rfc8439A2_1
it "RFC 8439 A2 #2 ChaCha20" rfc8439A2_2
it "RFC 8439 A2 #3 ChaCha20" rfc8439A2_3
longTests
counterCarry
prop "generate-combine" chachaGenerateCombine
prop "chunking-generate" chachaGenerateChunks
prop "chunking-combine" chachaCombineChunks
where
chachaRunSimple expected rounds klen nonceLen =
let chacha = ChaCha.initialize rounds (B.replicate klen 0) (B.replicate nonceLen 0)
in fst (ChaCha.generate chacha (B.length expected)) `shouldBe` expected
chachaGenerateChunks :: ChunkingLen -> Vector -> Bool
chachaGenerateChunks (ChunkingLen ckLen) (Vector rounds key iv) =
let initChaCha = ChaCha.initialize rounds key iv
nbBytes = 1048
(expected, _) = ChaCha.generate initChaCha nbBytes
chunks = loop nbBytes ckLen initChaCha
in expected `propertyEq` B.concat chunks
where
loop n [] chacha = loop n ckLen chacha
loop 0 _ _ = []
loop n (x : xs) chacha =
let len = min x n
(c, next) = ChaCha.generate chacha len
in c : loop (n - len) xs next
chachaGenerateCombine :: ChunkingLen0_127 -> Vector -> Int0_2901 -> Bool
chachaGenerateCombine (ChunkingLen0_127 ckLen) (Vector rounds key iv) (Int0_2901 nbBytes) =
let initChaCha = ChaCha.initialize rounds key iv
in loop nbBytes ckLen initChaCha
where
loop n [] chacha = loop n ckLen chacha
loop 0 _ _ = True
loop n (x : xs) chacha =
let len = min x n
(c1, next) = ChaCha.generate chacha len
(c2, _) = ChaCha.combine chacha (B.replicate len 0)
in if c1 == c2 then loop (n - len) xs next else False
chachaCombineChunks :: ChunkingLen0_127 -> Vector -> ArbitraryBS0_2901 -> Bool
chachaCombineChunks (ChunkingLen0_127 ckLen) (Vector rounds key iv) (ArbitraryBS0_2901 wholebs) =
let initChaCha = ChaCha.initialize rounds key iv
(expected, _) = ChaCha.combine initChaCha wholebs
chunks = loop wholebs ckLen initChaCha
in expected `propertyEq` B.concat chunks
where
loop bs [] chacha = loop bs ckLen chacha
loop bs (x : xs) chacha
| B.null bs = []
| otherwise =
let (bs1, bs2) = B.splitAt (min x (B.length bs)) bs
(c, next) = ChaCha.combine chacha bs1
in c : loop bs2 xs next