1 -- kubgen in haskell
  2 
  3 -- updated for RFNG-2 hash (Robbie's Fragile
  4 -- Number Garden version 2) :)
  5 
  6 -- this should track changes in kg4.html
  7 -- RFNG-2 change one, mod 4hash index by 256, not 127
  8 
  9 -- RFNG-2 change mixy119 = sum %119 replaced with
 10 -- mixy2 = (sum *3 + 119 + plainLength) mod 256
 11 
 12 -- RFNG-2 change, remove the random 1 from churn
 13 
 14 -- RFNG-2 split plainVal into plainVals and 
 15 -- and plainVal and moved the mod plainLen
 16 -- out of churn, and added an edge case to
 17 -- plainVal to nicely handle if plainText = ""
 18 
 19 
 20 -- change plainText to the text you want to hash
 21 -- to dispaly the kubgen numbers:
 22 -- main = mapM_ putStrLn (krows churnHash)
 23 -- to dispaly the kubgen  picture:
 24 -- main = mapM_ putStrLn (krows kpicture)
 25 
 26 
 27 -- hsh is the sort of initialization vector for the hash
 28 -- it's a 128 digit hex.  I forget where it came from
 29 hsh :: String
 30 hsh= concat
 31     [ "7ef0742612e4db668ea2a7b5779f69cf"
 32     , "13762b48d36812fd72eda69207460a71"
 33     , "bd2e2c901b8f46991249bd566e98b9e2"
 34     , "b31e897029c54c20f57a31e8e23f452f"
 35     ]
 36 
 37 -- this converts a hex digit to base 4 for the
 38 -- 'fourhash' I know it's not elegant but it's
 39 -- clear :)
 40 hexToFour :: Char -> [Char]
 41 hexToFour '0' = "00"
 42 hexToFour '1' = "01"
 43 hexToFour '2' = "02"
 44 hexToFour '3' = "03"
 45 hexToFour '4' = "10"
 46 hexToFour '5' = "11"
 47 hexToFour '6' = "12"
 48 hexToFour '7' = "13"
 49 hexToFour '8' = "20"
 50 hexToFour '9' = "21"
 51 hexToFour 'a' = "22"
 52 hexToFour 'b' = "23"
 53 hexToFour 'c' = "30"
 54 hexToFour 'd' = "31"
 55 hexToFour 'e' = "32"
 56 hexToFour 'f' = "33"
 57 hexToFour c = error ("Not a hex digit" ++ [c])
 58 
 59 -- converts back to hex digit
 60 fourToHex :: String -> Char
 61 fourToHex "00" = '0'
 62 fourToHex "01" = '1'
 63 fourToHex "02" = '2'
 64 fourToHex "03" = '3'
 65 fourToHex "10" = '4'
 66 fourToHex "11" = '5'
 67 fourToHex "12" = '6'
 68 fourToHex "13" = '7'
 69 fourToHex "20" = '8'
 70 fourToHex "21" = '9'
 71 fourToHex "22" = 'a'
 72 fourToHex "23" = 'b'
 73 fourToHex "30" = 'c'
 74 fourToHex "31" = 'd'
 75 fourToHex "32" = 'e'
 76 fourToHex "33" = 'f'
 77 fourToHex c = error ("Not expected kubgen fourSet" ++ c)
 78 
 79 -- makes the fourhash
 80 fourHash :: String -> String
 81 fourHash = concatMap hexToFour
 82 
 83 -- constant, the init vector's hash
 84 hash4 :: String
 85 hash4 = fourHash hsh
 86 
 87 plainText :: String
 88 plainText = "here is some different text"
 89 --plainText = ""
 90 
 91 plainLen :: Int
 92 plainLen = length plainText
 93 
 94 -- mixy converts all charaters to their code numbers,
 95 -- sums them multiplies by 3, adds 119 and plaintext
 96 -- length then mods by 256
 97 mixy2 :: [Char] -> Int
 98 mixy2 x = mod ((sum $ map fromEnum x) * 3 + 119 + length x) 256
 99 -- or from chatGPT: mixy119 = (`mod` 119) . sum . map fromEnum
100 
101 -- the static mixy value we will use for this string
102 mixVal :: Int
103 mixVal = mixy2 plainText
104 
105 -- takes a digit from a fourhash and returns a number 0..3
106 hash4Val :: Int -> Int
107 hash4Val x = fromEnum (hash4 !! x) - fromEnum '0'
108 
109 -- takes a character from the plaintext and returns 
110 -- its char value
111 plainVals :: [Int]
112 plainVals
113     | null plainText = [0]
114     | otherwise = map fromEnum plainText
115 
116 plainVal :: Int -> Int
117 plainVal x = plainVals !! mod x (length plainVals)
118 
119 -- old plainVal
120 -- plainVal :: Int -> Int
121 -- plainVal x = fromEnum (plainText !! x)
122 
123 -- main hash functions, steps through the 256 values of
124 -- of the initial fourhash vector and takes the xth value
125 -- of the plain text, adds the init 4hash with index
126 -- offset by mixy and mod 256, adds mixy, and adds 1 and
127 -- does mod 4 producing a 0 through 3
128 churn :: Int -> Int
129 churn x = mod (mixVal + (hash4Val (mod (x +mixVal) 256)) +
130     plainVal x ) 4
131 
132 -- old churn
133 -- churn :: Int -> Int
134 -- churn x = mod (mixVal + (hash4Val (mod (x +mixVal) 256)) +
135 --     plainVal (mod x plainLen) ) 4
136 
137 -- puts the 256 [0..3]s into a string to be displayed
138 churnHash :: String
139 churnHash = concatMap (show . churn) [0..255]
140 
141 -- breaks 4hash into pairs for conversion to hex
142 pairs :: String -> [String]
143 pairs [] = []
144 pairs (x:y:xs) = [x, y] : pairs xs
145 pairs _ = error "pairs: odd-length string"
146 
147 -- applies pairs (above) to churnHash
148 churnHex :: String
149 churnHex = map fourToHex (pairs churnHash)
150 
151 -- breaks 256 char string into 16 16 char strings
152 -- to make grid
153 krows :: String -> [String]
154 krows [] = []
155 krows xs = take 16 xs : krows (drop 16 xs)
156 
157 --main = mapM_ putStrLn (krows churnHash)
158 
159 -- alternate glyph representation of the kubgen
160 glyph :: Char -> Char
161 glyph '0' = ' '
162 glyph '1' = '.'
163 glyph '2' = 'o'
164 glyph '3' = '#'
165 glyph  _  = '?'
166 
167 kpicture :: String
168 kpicture = map glyph churnHash
169 
170 --main = mapM_ putStrLn (krows kpictire)