cryptopals

Matasano's cryptopals challenges (cryptopals.com).
git clone git://git.jtobin.io/cryptopals.git
Log | Files | Refs | README | LICENSE

Util.hs (2164B)


      1 module Cryptopals.Util (
      2     CUB.chunks
      3   , CUB.hamming
      4   , fixedXor
      5   , lpkcs7
      6   , CUB.nhamming
      7   , CUS.often
      8   , CUB.panhamming
      9   , pkcs7
     10   , repeatingKeyXor
     11   , CUB.rotate
     12   , roundUpToMul
     13   , CUS.score
     14   , CUS.scoreAlt
     15   , singleByteXor
     16   , CUS.tally
     17   , CUS.gtally
     18   , unpkcs7
     19   , bytes
     20   ) where
     21 
     22 import Control.Monad
     23 import Control.Monad.Primitive
     24 import qualified Cryptopals.Util.ByteString as CUB
     25 import qualified Cryptopals.Util.Similarity as CUS
     26 import qualified Data.Bits as B
     27 import qualified Data.ByteString as BS
     28 import qualified Data.ByteString.Base16 as B16
     29 import qualified Data.ByteString.Base64 as B64
     30 import qualified Data.Text as T
     31 import GHC.Word (Word8)
     32 import qualified System.Random.MWC as MWC
     33 
     34 bytes :: PrimMonad m => Int -> MWC.Gen (PrimState m) -> m BS.ByteString
     35 bytes n gen = fmap BS.pack $ replicateM n (MWC.uniform gen)
     36 
     37 fixedXor :: BS.ByteString -> BS.ByteString -> BS.ByteString
     38 fixedXor l r = BS.pack $ BS.zipWith B.xor l r
     39 
     40 singleByteXor :: Word8 -> BS.ByteString -> BS.ByteString
     41 singleByteXor byt = BS.map (B.xor byt)
     42 
     43 repeatingKeyXor :: BS.ByteString -> BS.ByteString -> BS.ByteString
     44 repeatingKeyXor key pla =
     45   let pl = BS.length pla
     46       ks = BS.pack $ take pl (cycle (BS.unpack key))
     47   in  BS.pack $ BS.zipWith B.xor ks pla
     48 
     49 pkcs7 :: Int -> BS.ByteString -> BS.ByteString
     50 pkcs7 tar bs
     51   | BS.length bs `rem` tar == 0 = bs <> BS.replicate 16 16
     52   | otherwise =
     53       let len = BS.length bs
     54           byt = tar - len `mod` tar
     55       in  bs <> BS.replicate byt (fromIntegral byt)
     56 
     57 -- lazy man's pkcs#7 padding
     58 lpkcs7 :: BS.ByteString -> BS.ByteString
     59 lpkcs7 bs
     60   | BS.null bs = BS.replicate 16 16
     61   | otherwise  = pkcs7 (roundUpToMul 16 (BS.length bs)) bs
     62 
     63 unpkcs7 :: BS.ByteString -> Maybe BS.ByteString
     64 unpkcs7 bs = do
     65   (_, c) <- BS.unsnoc bs
     66   let len = BS.length bs
     67   if   fromIntegral c > len || c == 0
     68   then Nothing
     69   else let (str, pad) = BS.splitAt (len - fromIntegral c) bs
     70        in  if   BS.all (== fromIntegral c) pad
     71            then pure str
     72            else Nothing
     73 
     74 roundUpToMul :: Int -> Int -> Int
     75 roundUpToMul mul num =
     76   let r = num `rem` mul
     77   in  if   r == 0
     78       then num
     79       else num + mul - r
     80