2025-10-06 00:57:05 +02:00

65 lines
1.8 KiB
Haskell

-- | The Monolith permutation with @t = 12@
{-# LANGUAGE Strict #-}
module Hash.Monolith.Permutation where
--------------------------------------------------------------------------------
import Data.Array (Array)
import Data.Array.IArray
import Data.Bits
import Data.Word
import Field.Goldilocks
import Hash.Monolith.Constants
import Hash.Common
--------------------------------------------------------------------------------
permutation :: State -> State
permutation
= foldr1 (.) (map monolithRound $ reverse [0..5])
. linearDiffusion
monolithRound :: Int -> State -> State
monolithRound ridx = concrete ridx . bricks . bars
--------------------------------------------------------------------------------
sboxByte :: Word8 -> Word8
sboxByte y = rol1 $ y `xor` (rol1 ny .&. rol2 y .&. rol3 y) where
ny = complement y
rol1 = flip rotateL 1
rol2 = flip rotateL 2
rol3 = flip rotateL 3
sboxField :: F -> F
sboxField = toF . bytesToWord64LE . map sboxByte . bytesFromWord64LE . fromF
bars :: State -> State
bars old = case splitAt 4 (elems old) of
(four,eight) -> listToState' 12 (map sboxField four ++ eight)
bricks :: State -> State
bricks old = listToState' 12 $ zipWith (+) (0 : map sqr xs) xs where xs = elems old
concrete' :: [F] -> State -> State
concrete' rcs = listToState' 12 . zipWith (+) rcs . elems . linearDiffusion
concrete :: Int -> State -> State
concrete ridx = concrete' [ monolithRoundConstants ! (ridx,j) | j<-[0..11] ]
--------------------------------------------------------------------------------
circulantRow :: State
circulantRow = listToState' 12 [ 7, 23, 8, 26, 13, 10, 9, 7, 6, 22, 21, 8 ]
linearDiffusion :: State -> State
linearDiffusion old = listToState' 12
[ sum [ old!j * circulantRow!(mod (j-k) 12) | j<-[0..11] ]
| k <- [0..11]
]
--------------------------------------------------------------------------------