summaryrefslogtreecommitdiff
path: root/080_blog/00065_Base64-Encoder-(Haskell)/index.md
blob: 830ed8d7b678d9c30a968f72056224ce61c03906 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Miguel's Naive Base64 Encoder
==============================
    February 19, 2018

Coded on a winter afterfnoon on 19th Feb 2018 A.D. to fully understand 
base64 encoding and play with haskell, which is always an indisputable 
pleasure.

The following lines were written in full awareness that 'libraries' for 
this very purpose, which perform way better, are in existence.

Coded in big anger due to nick's stories about saving his binary format, 
encrypted passwords in an ascii config file, featuring 
strange letters and characters.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines}
-- File: base64.hs --
 
import Data.Char
import Text.Printf
import qualified Data.List as L
import qualified Data.List.Split as T
 
toBase64 x      = maskBase64 x . toBase64core . asciiToBin . binFill $ x
toBase64core    = map base64toDigit . map binToDec . T.chunksOf 6
 
base64toDigit x = (['A'..'Z']++['a'..'z']++['0'..'9']++['+','/']) !! x
binToDec        = sum . map (2^) . L.findIndices (=='1') . reverse
asciiToBin      = concat . map (\y -> printf "%08b" y) . map ord 
binFill x       = x ++ (take (fill64length x) $ cycle "\000")
 
maskBase64 o x  = take (length x - l ) x ++ (take l $ cycle "=")
                  where l = (fill64length o)
 
fill64length x | m==0      = 0
               | otherwise = 3-m
               where m=mod (length x) 3
 
main = do
    line <- getLine
    putStrLn $ toBase64 line
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Example usage, with decoding via `base64 -d`

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.bash}
miguel@megaloman:~$ echo -n "secret haskell" | runghc base64.hs 
c2VjcmV0IGhhc2tlbGw=
miguel@megaloman:~$ echo -n "c2VjcmV0IGhhc2tlbGw=" | base64 -d # decode to check
secret haskell
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~