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