# Hex chain to Base64 in Haskell

This is my opinion about the first challenge in the cryptopals crypto challenge list. I think I made it quite simple, but I feel it is possible to optimize it even more. Any suggestion?

The code:

``````import qualified Data.HashMap.Strict as HM
import qualified Data.IntMap.Strict as IM
import Data.Maybe
import Data.Char (digitToInt)

type BinString = String
type HexString = String
type Base64String = String

base64 = IM.fromList (zip (0..63) (('A'..'Z') ++ ('a'..'z') ++ ('0'..'9') ++ ('+','/')))

hexToBinDict = HM.fromList (('0',"0000"),('1',"0001"),('2',"0010"),('3',"0011"),('4',"0100"),('5',"0101"),
('6',"0110"),('7',"0111"),('8',"1000"),('9',"1001"),('a',"1010"),('b',"1011"),
('c',"1100"),('d',"1101"),('e',"1110"),('f',"1111"))

hexToBase64 :: HexString -> Base64String
hexToBase64 xs = map fromJust (IM.lookup x base64 | x <- base10) ++ padMissingSextets sextets
where base10 = map (fromJust) (map (binToDec) sextets)
sextets = binToSextets (hexToBin xs)

--returns a list of the 4-digit binary encodings of the given string's hex codes
hexToQuartets :: HexString -> (BinString)
hexToQuartets () = ()
hexToQuartets hexCode = fromJust (HM.lookup (head hexCode) hexToBinDict) : hexToQuartets (tail hexCode)

--converts an hex string into a binary string
hexToBin :: HexString -> BinString
hexToBin xs = concat (hexToQuartets xs)

--pads the string with 0's on the right until its a sextet
padRight xs = xs ++ (replicate n '0')
where n = 6 - length xs

--returns a list of all full sextets on the string
binToSextets :: BinString -> (BinString)
binToSextets xs = binToSextetsAux (tail xs) () (head xs) 1

--recursiverly find sextets and pad the last one if necessary
binToSextetsAux :: BinString -> (BinString) -> BinString -> Int -> (String)
binToSextetsAux () sextets ys _
|length ys == 6     = sextets ++ (ys)
|otherwise          = sextets ++ (padRight ys)
binToSextetsAux xs sextets ys i
|i == 6     = binToSextetsAux (tail xs) (sextets ++ (ys)) (head xs) 1
|otherwise  = binToSextetsAux (tail xs) sextets (ys ++ (head xs)) (i+1)

--binary string to decimal conversion
binToDec :: Integral a => BinString -> Maybe a
binToDec = fmap fst . listToMaybe . readInt 2 (`elem` "01") digitToInt

--pads with "=" on the right for each empty sextet
--if the length is not divisible by 4, then theres 1 or 2 empty sextets
$$```$$