hnix-store-core-0.8.0.0: src/System/Nix/Hash/Truncation.hs
module System.Nix.Hash.Truncation
( truncateInNixWay
) where
import Data.Word (Word8)
import Data.ByteString (ByteString)
import qualified Data.ByteString
import qualified Data.Bits
import qualified Data.Bool
import qualified Data.List
-- | Bytewise truncation of a 'Digest'.
--
-- When truncation length is greater than the length of the bytestring
-- but less than twice the bytestring length, truncation splits the
-- bytestring into a head part (truncation length) and tail part
-- (leftover part), right-pads the leftovers with 0 to the truncation
-- length, and combines the two strings bytewise with 'xor'.
truncateInNixWay
:: Int -> ByteString -> ByteString
-- 2021-06-07: NOTE: Renamed function, since truncation can be done in a lot of ways, there is no practice of truncting hashes this way, moreover:
-- 1. <https://crypto.stackexchange.com/questions/56337/strength-of-hash-obtained-by-xor-of-parts-of-sha3>
-- 2. <https://www.reddit.com/r/crypto/comments/6olqfm/ways_to_truncated_hash/>
truncateInNixWay n c =
Data.ByteString.pack $ fmap truncOutputByte [0 .. n-1]
where
truncOutputByte :: Int -> Word8
truncOutputByte i = Data.List.foldl' (aux i) 0 [0 .. Data.ByteString.length c - 1]
inputByte :: Int -> Word8
inputByte j = Data.ByteString.index c j
aux :: Int -> Word8 -> Int -> Word8
aux i x j =
Data.Bool.bool
id
(`Data.Bits.xor` inputByte j)
(j `mod` n == i)
x