packages feed

tahoe-chk-0.2.0.0: test/SpecCrypto.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module SpecCrypto (
    tests,
) where

import Crypto.Cipher.AES (AES128)
import Crypto.Cipher.Types (Cipher (..), KeySizeSpecifier (..))
import Crypto.Error (CryptoFailable (CryptoPassed))
import qualified Data.ByteString as B
import Data.Char (
    ord,
 )
import Tahoe.CHK.Cipher (Key)
import Tahoe.CHK.Crypto (
    blockHash',
    ciphertextSegmentHash',
    convergenceEncryptionTag,
    convergenceSecretLength,
    sha256,
    sha256d,
    storageIndexHash,
    taggedHash,
    taggedHash',
    taggedPairHash,
    taggedPairHash',
 )
import Tahoe.CHK.SHA256d (SHA256d)
import Tahoe.CHK.Types (
    Parameters (..),
 )
import Test.Tasty (
    TestTree,
    testGroup,
 )
import Test.Tasty.HUnit (
    assertEqual,
    testCase,
 )

tests :: TestTree
tests =
    testGroup
        "Crypto"
        [ testGroup
            "sha256"
            [ testCase "sha256" $
                assertEqual
                    "known value"
                    "\x23\xfb\xe2\x1e\x2f\xae\xde\xb5\x44\x92\xcb\x7a\xc6\x0e\x04\x4a\xbb\x47\x3f\xcb\x13\x1a\x65\x8e\xd2\x5c\xd0\x17\x06\xc3\xf3\x98"
                    (sha256 "4:tag1,value")
            , testCase "sha256d" $
                assertEqual
                    "known value"
                    "\x6b\xd0\xdc\xb0\x2f\x11\x0a\xe1\xe9\x41\x1f\x12\x52\x07\x03\x66\xfe\xaa\xcb\xc9\xda\xdb\x66\xa4\xa9\xa0\xc0\xdd\x85\x49\x5d\xc4"
                    (sha256d "4:tag1,value")
            , testCase "storage index tagged hash" $
                -- Adapted from allmydata.test.test_hashutil.HashUtilTests.test_known_answers
                assertEqual
                    "known value"
                    (CryptoPassed "\xb5\x4c\x60\xc5\xb1\x26\x46\xf0\x77\x0\xc4\x4c\x8b\x75\xb9\x48")
                    (storageIndexHash <$> xKey)
            , testCase "tagged hash length" $ do
                -- The length of the result equals the given size.
                let expected = 17
                assertEqual "taggedHash result length /= expected" expected (B.length $ taggedHash expected "tag" "hello world")
                assertEqual "taggedPairHash result length /= expected" expected (B.length $ taggedPairHash expected "tag" "hello" "world")
            , testCase "well-known tagged hashes" $ do
                assertEqual
                    "taggedHash' result /= expected"
                    "yra322btzoqjp4ts2jon5dztgnilcdg6jgztgk7joi6qpjkitg2q"
                    (taggedHash' @SHA256d "tag" "hello world")
                assertEqual
                    "taggedHash' result /= expected"
                    "kfbsfssrv2bvtp3regne6j7gpdjcdjwncewriyfdtt764o5oa7ta"
                    (taggedHash' @SHA256d "different" "hello world")
                assertEqual
                    "taggedHash' result /= expected"
                    "z34pzkgo36chbjz2qykonlxthc4zdqqquapw4bcaoogzvmmcr3zq"
                    (taggedHash' @SHA256d "different" "goodbye world")
            , testCase "well-known tagged pair hashes" $ do
                assertEqual
                    "taggedPairHash' result /= expected"
                    "wmto44q3shtezwggku2fxztfkwibvznkfu6clatnvfog527sb6dq"
                    (taggedPairHash' @SHA256d "tag" "hello" "world")
                assertEqual
                    "taggedPairHash' result /= expected"
                    "lzn27njx246jhijpendqrxlk4yb23nznbcrihommbymg5e7quh4a"
                    (taggedPairHash' @SHA256d "different" "hello" "world")
                assertEqual
                    "taggedPairHash' result /= expected"
                    "qnehpoypxxdhjheqq7dayloghtu42yr55uylc776zt23ii73o3oq"
                    (taggedPairHash' @SHA256d "different" "goodbye" "world")
            , testCase "well-known ciphertext segment hashes" $ do
                assertEqual
                    "ciphertextSegmentHash' result /= expected"
                    "aovy5aa7jej6ym5ikgwyoi4pxawnoj3wtaludjz7e2nb5xijb7aa"
                    (ciphertextSegmentHash' @SHA256d "")
            , testCase "well-known block hashes" $ do
                assertEqual
                    "blockHash' result /= expected"
                    "msjr5bh4evuh7fa3zw7uovixfbvlnstr5b65mrerwfnvjxig2jvq"
                    (blockHash' @SHA256d "")
            , testCase "convergence hasher tag" $
                -- See allmydata.test.test_hashutil.HashUtilTests.test_convergence_hasher_tag
                let convergenceSecret = B.replicate convergenceSecretLength 0x42
                    params =
                        Parameters
                            { paramSegmentSize = 1024
                            , paramTotalShares = 10
                            , paramHappyShares = undefined
                            , paramRequiredShares = 3
                            }
                 in assertEqual
                        "known value"
                        ( mconcat
                            [ "allmydata_immutable_content_to_key_with_added_secret_v1+"
                            , "16:\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42,"
                            , "9:3,10,1024,"
                            ]
                        )
                        (convergenceEncryptionTag convergenceSecret params)
            ]
        ]
  where
    xKey = cipherInit keyBytes :: CryptoFailable (Key AES128)
    keyBytes = B.replicate keySize (fromIntegral $ ord 'x')
    keySize = case cipherKeySize @(Key AES128) undefined of
        KeySizeRange _ high -> high
        KeySizeEnum [] -> error "no key sizes!"
        KeySizeEnum (s : _) -> s
        KeySizeFixed s -> s