File: KeyGen.hs

package info (click to toggle)
kaya 0.4.2-4
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 4,448 kB
  • ctags: 1,694
  • sloc: cpp: 9,536; haskell: 7,461; sh: 3,013; yacc: 910; makefile: 816; perl: 90
file content (58 lines) | stat: -rw-r--r-- 1,795 bytes parent folder | download | duplicates (4)
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
module KeyGen(mkkey) where

import Char
import System.Random
import System.Directory
import System.IO
import Control.Monad.State

-- Read from /dev/random if available, or just use the built in rng if not
getRandom :: Int -> IO [Int]
getRandom n = do devrnd <- doesFileExist "/dev/urandom"
                 if devrnd 
                    then do
                       h <- openFile "/dev/urandom" ReadMode
                       ns <- readInts n h
                       hClose h
                       return ns
                    else (rndlist n)
  where rndlist 0 = return []
        rndlist n = do ns <- rndlist (n-1)
                       x <- randomIO
                       return (x:ns)
        readInts 0 h = return []
        readInts n h = do ns <- readInts (n-1) h
                          x <- hGetChar h
                          return (fromEnum x : ns)

-- Generate bad random numbers for when a deterministic key is required.
-- (eg testing)
dornd seed = seed*1103515245+12345

mkkey :: Bool -> Int -> Int -> IO String
mkkey det n seed = evalStateT (mkkeyST det n) seed

mkkeyST :: Bool -- Determinism required
        -> Int -- Number of bytes required
        -> StateT Int IO String
mkkeyST False n = do ns <- lift $ getRandom n
                     return $ concat $ map (('\\':).show3dm) ns
mkkeyST True 0 = return ""
mkkeyST True n = do seed <- get
                    let seed' = dornd seed
                    put seed'
 		    rest <- mkkeyST True (n-1)
		    return $ "\\" ++ show3d (seed' `mod` 256) ++ rest

show3d n | n < 8 = "00"++ toOct n
         | n < 64 = "0"++ toOct n
	 | otherwise = toOct n

show3dm n = show3d(n `mod` 256)

toOct :: Int -> String
toOct i =
    let (q,r) = divMod i 8
        e = [intToDigit r]
    in
    if q==0 then e else toOct q++e