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
52
53
54
55
56
57
58
59
60
61
62
63
|
module CaesarCipher(
CaesarKey,
caesarKey,
allKeys,
encipher,
encipherString,
invert,
decipher,
decipherString,
bruteForceCaesar,
) where
import Data.Char
import Control.Applicative
import Math.NumberTheory.Moduli (invertMod)
import Data.Maybe (catMaybes)
textToDigits::String->[Integer]
textToDigits = map (\x->toInteger (ord x 97))
digitsToText::[Integer]->String
digitsToText = map (\x->chr (fromIntegral x + 97))
data CaesarKey = Key { r :: Integer, s :: Integer, q :: Integer }
caesarKey :: Integer -> Integer -> Maybe CaesarKey
caesarKey r s = Key r s <$> invertMod r 26
allKeys :: [CaesarKey]
allKeys = catMaybes $ caesarKey <$> [0..25] <*> [0..25]
encipher :: CaesarKey -> Integer -> Integer
encipher Key{..} p = mod (r * p + s) 26
encipherString :: CaesarKey -> String -> String
encipherString key = digitsToText . map (encipher key) . textToDigits
invert :: CaesarKey -> CaesarKey
invert (Key r s q) = Key q ((26q)*s) r
decipher :: CaesarKey -> Integer -> Integer
decipher key = encipher (invert key)
decipherString :: CaesarKey -> String -> String
decipherString key = encipherString (invert key)
bruteForceCaesar :: String -> [String]
bruteForceCaesar str = [decipherString key str | key <- allKeys]
|