main.hs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. -- RSA LAB
  2. import Data.Char
  3. type Message = [Int]
  4. stringToMessage::String -> Message
  5. stringToMessage = map ord
  6. messageToString::Message -> String
  7. messageToString = map chr
  8. pad::Int -> Message -> Message
  9. pad bsize msg =
  10. let msgSize = length msg in
  11. let gap = mod msgSize bsize in
  12. let padding = bsize - gap in
  13. msg ++ [padding | _ <- [1..padding] ]
  14. unpad::Message -> Message
  15. unpad m = reverse $ subunpad (-1) [] m
  16. -- First arg s
  17. -- -1 > Travel until reaching end if
  18. -- 0 > Pad removed
  19. -- n > Still n items to remove
  20. subunpad::Int -> Message -> Message -> Message
  21. subunpad _ [] [] = []
  22. subunpad (-1) ys (s:[]) = subunpad (s - 1) ys []
  23. subunpad (-1) ys (x:xs) = subunpad (-1) (x:ys) xs
  24. subunpad 0 ys _ = ys
  25. subunpad s (y:ys) _ = subunpad (s - 1) ys []
  26. groupBytes::Message -> Int
  27. groupBytes = subgroupBytes 1 0
  28. -- First arg : pow > Contains 256^n where n is the number of recursive calls
  29. -- Second arg : acc > contains the result of the block
  30. subgroupBytes::Int -> Int -> Message -> Int
  31. subgroupBytes _ acc [] = acc
  32. subgroupBytes pow acc (c:msg) = subgroupBytes (pow * 256) (acc + c * pow) msg
  33. ungroupBytes::Int -> Message
  34. ungroupBytes 0 = []
  35. ungroupBytes n = (mod n 256):ungroupBytes (div n 256)
  36. groupN::Int -> Message -> [Message]
  37. groupN _ [] = []
  38. groupN bsize s = (take bsize s):groupN bsize (drop bsize s)
  39. makeBlocks::Int -> Message -> Message
  40. makeBlocks bsize msg = map groupBytes (groupN bsize msg)
  41. splitBlocks::Message -> Message
  42. splitBlocks msg = concat (map ungroupBytes msg)
  43. -- Reuse arithmetics from slide 42
  44. primecandidates = [6 * k + a | k <- [1..], a <- [-1, 1]]
  45. dividers n = [k | k <- takeWhile (\k -> k * k <= n) primeinf, rem n k == 0]
  46. prime n = null (dividers n)
  47. primeinf = 2:3:[n | n <- primecandidates, prime n]
  48. choosePrime::Int -> Int
  49. choosePrime b = head $ dropWhile (<= b) primeinf
  50. -- a -> b -> (g, u, v) where a * u + b * v = g with g GCD
  51. euclide::Int -> Int -> (Int, Int, Int)
  52. euclide a 0 = (a, 1, 0)
  53. euclide a b = let (d', u', v') = euclide b (mod a b) in (d', v', u' - (div a b) * v')
  54. modInv e n = let (_, d, _) = euclide e n in d
  55. -- Return x ^ k (mod) n
  56. expMod x k n =
  57. if k == 0
  58. then 1
  59. else if even k
  60. then expMod (mod ((mod x n) * (mod x n)) n) (div k 2) n
  61. else (mod x n) * expMod (mod ((mod x n) * (mod x n)) n) (div k 2) n
  62. encrypt::Int -> Int -> Int -> String -> Message
  63. encrypt e n bsize smsg =
  64. let msg = stringToMessage smsg in
  65. let pmsg = pad bsize msg in
  66. let bmsg = makeBlocks bsize pmsg in
  67. map (\m -> expMod m e n) bmsg
  68. decrypt::Int -> Int -> Int -> Message -> String
  69. decrypt d n bsize cmsg =
  70. let bmsg = map (\c -> expMod c d n) cmsg in
  71. let pmsg = splitBlocks bmsg in
  72. let msg = unpad pmsg in
  73. messageToString msg
  74. main::IO ()
  75. main =
  76. let e = choosePrime 256 in
  77. let q = choosePrime e in
  78. let p = choosePrime q in
  79. let n = p * q in
  80. let d = modInv e n in
  81. let clearmsg = "Z" in
  82. let msg = encrypt e n 1 clearmsg in
  83. let outmsg = decrypt d n 1 msg in
  84. do
  85. print "Message clear :"
  86. print clearmsg
  87. print "Message cyphered :"
  88. print msg
  89. print "Message decyphered :"
  90. print outmsg