Crytpo for nhc

Dominic Steinitz dominic.steinitz@blueyonder.co.uk
Mon, 28 Apr 2003 20:41:19 +0100


This is a multi-part message in MIME format.

------=_NextPart_000_0007_01C30DC6.85F1AE00
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

I have been trying to write a Crypto library and so far it works with ghc
and hugs.

Am I right in thinking I am going to struggle with nhc? It uses Word8 and
Word64 heavily. For example, cipher block chaining relies on xoring Word64.

I attach the library and a test program. I'd be grateful for any suggestions
on how to make it work with nhc.

Dominic Steinitz



------=_NextPart_000_0007_01C30DC6.85F1AE00
Content-Type: application/octet-stream;
	name="Crypto.hs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="Crypto.hs"

-------------------------------------------------------------------------=
----=0A=
-- |=0A=
-- Module      :  Data.Crypto=0A=
-- Copyright   :  (c) Ian Lynagh, Dominic Steinitz 2001-2003=0A=
-- License     :  BSD-style (see the file libraries/base/LICENSE)=0A=
-- =0A=
-- Maintainer  :  dominic.steinitz@blueyonder.co.uk=0A=
-- Stability   :  experimental=0A=
-- Portability :  non-portable=0A=
--=0A=
-- Cryptographic library based on contributions from Ian Lynagh=0A=
-- <http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh/>.=0A=
--=0A=
-- Requires Bits, Word, Word64 and multi-parameter type classes.=0A=
--=0A=
-- This library currently supports DES Electronic Codebook Mode (ECB) =
mode=0A=
-- and Cipher Block Chainig (CBC) mode.=0A=
-- =0A=
-------------------------------------------------------------------------=
----=0A=
=0A=
module Crypto (=0A=
   -- * Types=0A=
   Octet,=0A=
   -- * Function types=0A=
   des, unDes,=0A=
   cbc, unCbc, =0A=
   pkcs5, unPkcs5,=0A=
   toOctets, fromOctets=0A=
   -- * Example Usage=0A=
   -- $usage=0A=
	      ) where=0A=
=0A=
import Data.Word=0A=
import Data.Bits=0A=
import List=0A=
=0A=
{- BEGIN_HUGS_ONLY -}=0A=
=0A=
import ZordHUGS=0A=
=0A=
{- END_HUGS_ONLY -}=0A=
=0A=
{- BEGIN_GHC_ONLY=0A=
=0A=
type Zord64 =3D Word64=0A=
=0A=
END_GHC_ONLY -}=0A=
=0A=
{- $usage=0A=
=0A=
@=0A=
module Main(main) where=0A=
@=0A=
=0A=
@=0A=
import Crypto=0A=
@=0A=
=0A=
@=0A=
import Char=0A=
@=0A=
=0A=
@=0A=
plainText =3D  "Good morning Mr. Phelps.  Your m" ++=0A=
             "ission,\nshould you choose to acc" ++=0A=
             "ept it, is to learn to use DES.\NUL"=0A=
@=0A=
=0A=
@=0A=
iv  =3D 0x0123456789abcdef=0A=
@=0A=
=0A=
@=0A=
key =3D 0x42652d4861707079=0A=
@=0A=
=0A=
@=0A=
cipherText =3D cbc des iv key $ pkcs5 $ map (fromIntegral . ord) =
plainText=0A=
@=0A=
=0A=
@=0A=
plainText' =3D map (chr . fromIntegral) $ unPkcs5 $ unCbc unDes iv key =
cipherText=0A=
@=0A=
=0A=
@=0A=
main =3D putStrLn plainText'=0A=
@=0A=
=0A=
-}=0A=
=0A=
type Rotation =3D Int=0A=
type Key     =3D Zord64=0A=
type Message =3D Zord64=0A=
type Enc     =3D Zord64=0A=
type InitVector =3D Zord64=0A=
=0A=
type BitsX  =3D [Bool]=0A=
type Bits4  =3D [Bool]=0A=
type Bits6  =3D [Bool]=0A=
type Bits32 =3D [Bool]=0A=
type Bits48 =3D [Bool]=0A=
type Bits56 =3D [Bool]=0A=
type Bits64 =3D [Bool]=0A=
=0A=
instance Num [Bool]=0A=
=0A=
instance Bits [Bool] where=0A=
   a `xor` b =3D (zipWith (\x y -> (not x && y) || (x && not y)) a b)=0A=
   rotate bits rot =3D drop rot' bits ++ take rot' bits=0A=
      where rot' =3D rot `mod` (length bits)=0A=
=0A=
bitify :: Zord64 -> Bits64=0A=
bitify w =3D map (\b -> w .&. (shiftL 1 b) /=3D 0) [63,62..0]=0A=
=0A=
unbitify :: Bits64 -> Zord64=0A=
unbitify bs =3D foldl (\i b -> if b then 1 + shiftL i 1 else shiftL i 1) =
0 bs=0A=
=0A=
initial_permutation :: Bits64 -> Bits64=0A=
initial_permutation mb =3D map ((!!) mb) i=0A=
   where i =3D [57, 49, 41, 33, 25, 17,  9, 1, 59, 51, 43, 35, 27, 19, =
11, 3,=0A=
              61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, =
7,=0A=
              56, 48, 40, 32, 24, 16,  8, 0, 58, 50, 42, 34, 26, 18, 10, =
2,=0A=
              60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, =
6]=0A=
=0A=
key_transformation :: Bits64 -> Bits56=0A=
key_transformation kb =3D map ((!!) kb) i=0A=
 where i =3D [56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,=0A=
             9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35,=0A=
            62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,=0A=
            13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3]=0A=
=0A=
des_enc :: Message -> Key -> Enc=0A=
des_enc =3D do_des [1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28]=0A=
=0A=
des_dec :: Message -> Key -> Enc=0A=
des_dec =3D do_des [28,27,25,23,21,19,17,15,14,12,10,8,6,4,2,1]=0A=
=0A=
do_des :: [Rotation] -> Message -> Key -> Enc=0A=
do_des rots m k =3D des_work rots (takeDrop 32 mb) kb=0A=
 where kb =3D key_transformation $ bitify k=0A=
       mb =3D initial_permutation $ bitify m=0A=
=0A=
des_work :: [Rotation] -> (Bits32, Bits32) -> Bits56 -> Enc=0A=
des_work [] (ml, mr) _ =3D unbitify $ final_perm $ (mr ++ ml)=0A=
des_work (r:rs) mb kb =3D des_work rs mb' kb=0A=
 where mb' =3D do_round r mb kb=0A=
=0A=
do_round :: Rotation -> (Bits32, Bits32) -> Bits56 -> (Bits32, Bits32)=0A=
do_round r (ml, mr) kb =3D (mr, m')=0A=
 where kb' =3D get_key kb r=0A=
       comp_kb =3D compression_permutation kb'=0A=
       expa_mr =3D expansion_permutation mr=0A=
       res =3D comp_kb `xor` expa_mr=0A=
       res' =3D tail $ iterate (trans 6) ([], res)=0A=
       trans n (_, b) =3D (take n b, drop n b)=0A=
       res_s =3D concat $ zipWith (\f (x,_) -> f x) [s_box_1, s_box_2,=0A=
                                                   s_box_3, s_box_4,=0A=
                                                   s_box_5, s_box_6,=0A=
                                                   s_box_7, s_box_8] res'=0A=
       res_p =3D p_box res_s=0A=
       m' =3D res_p `xor` ml=0A=
=0A=
get_key :: Bits56 -> Rotation -> Bits56=0A=
get_key kb r =3D kb'=0A=
 where (kl, kr) =3D takeDrop 28 kb=0A=
       kb' =3D rotateL kl r ++ rotateL kr r=0A=
=0A=
compression_permutation :: Bits56 -> Bits48=0A=
compression_permutation kb =3D map ((!!) kb) i=0A=
 where i =3D [13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,=0A=
            22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,=0A=
            40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,=0A=
            43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31]=0A=
=0A=
expansion_permutation :: Bits32 -> Bits48=0A=
expansion_permutation mb =3D map ((!!) mb) i=0A=
 where i =3D [31,  0,  1,  2,  3,  4,  3,  4,  5,  6,  7,  8,=0A=
             7,  8,  9, 10, 11, 12, 11, 12, 13, 14, 15, 16,=0A=
            15, 16, 17, 18, 19, 20, 19, 20, 21, 22, 23, 24,=0A=
            23, 24, 25, 26, 27, 28, 27, 28, 29, 30, 31,  0]=0A=
=0A=
s_box :: [[Word8]] -> Bits6 -> Bits4=0A=
s_box s [a,b,c,d,e,f] =3D to_bool 4 $ (s !! row) !! col=0A=
 where row =3D sum $ zipWith numericise [a,f]     [1, 0]=0A=
       col =3D sum $ zipWith numericise [b,c,d,e] [3, 2, 1, 0]=0A=
       numericise =3D (\x y -> if x then 2^y else 0)=0A=
       to_bool 0 _ =3D []=0A=
       to_bool n i =3D ((i .&. 8) =3D=3D 8):to_bool (n-1) (shiftL i 1)=0A=
=0A=
s_box_1 :: Bits6 -> Bits4=0A=
s_box_1 =3D s_box i=0A=
 where i =3D [[14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  =
0,  7],=0A=
            [ 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3, =
 8],=0A=
            [ 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5, =
 0],=0A=
            [15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, =
13]]=0A=
=0A=
s_box_2 :: Bits6 -> Bits4=0A=
s_box_2 =3D s_box i=0A=
 where i =3D [[15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  =
5, 10],=0A=
            [3,  13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9,  =
11, 5],=0A=
            [0,  14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, =
15],=0A=
            [13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5,  =
14, 9]]=0A=
=0A=
s_box_3 :: Bits6 -> Bits4=0A=
s_box_3 =3D s_box i=0A=
 where i =3D [[10,  0,  9, 14 , 6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  =
2,  8],=0A=
            [13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15, =
 1],=0A=
            [13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14, =
 7],=0A=
            [1,  10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, =
12]]=0A=
=0A=
s_box_4 :: Bits6 -> Bits4=0A=
s_box_4 =3D s_box i=0A=
 where i =3D [[7,  13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  =
4, 15],=0A=
            [13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14, =
 9],=0A=
            [10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8, =
 4],=0A=
            [3,  15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, =
14]]=0A=
=0A=
s_box_5 :: Bits6 -> Bits4=0A=
s_box_5 =3D s_box i=0A=
 where i =3D [[2,  12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, =
14,  9],=0A=
            [14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8, =
 6],=0A=
            [4,   2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, =
14],=0A=
            [11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5, =
 3]]=0A=
=0A=
s_box_6 :: Bits6 -> Bits4=0A=
s_box_6 =3D s_box i=0A=
 where i =3D [[12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  =
5, 11],=0A=
            [10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3, =
 8],=0A=
            [9,  14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11, =
 6],=0A=
            [4,  3,   2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, =
13]]=0A=
=0A=
s_box_7 :: Bits6 -> Bits4=0A=
s_box_7 =3D s_box i=0A=
 where i =3D [[4,  11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  =
6,  1],=0A=
            [13, 0,  11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8, =
 6],=0A=
            [1,  4,  11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9, =
 2],=0A=
            [6,  11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, =
12]]=0A=
=0A=
s_box_8 :: Bits6 -> Bits4=0A=
s_box_8 =3D s_box i=0A=
 where i =3D [[13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, =
12,  7],=0A=
            [1,  15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9, =
 2],=0A=
            [7,  11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5, =
 8],=0A=
            [2,   1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, =
11]]=0A=
=0A=
p_box :: Bits32 -> Bits32=0A=
p_box kb =3D map ((!!) kb) i=0A=
 where i =3D [15, 6, 19, 20, 28, 11, 27, 16,  0, 14, 22, 25,  4, 17, 30, =
 9,=0A=
             1, 7, 23, 13, 31, 26,  2,  8, 18, 12, 29,  5, 21, 10,  3, =
24]=0A=
=0A=
final_perm :: Bits64 -> Bits64=0A=
final_perm kb =3D map ((!!) kb) i=0A=
 where i =3D [39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, =
30,=0A=
            37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28,=0A=
            35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26,=0A=
            33, 1, 41,  9, 49, 17, 57, 25, 32, 0, 40 , 8, 48, 16, 56, 24]=0A=
=0A=
takeDrop :: Int -> [a] -> ([a], [a])=0A=
takeDrop _ [] =3D ([], [])=0A=
takeDrop 0 xs =3D ([], xs)=0A=
takeDrop n (x:xs) =3D (x:ys, zs)=0A=
 where (ys, zs) =3D takeDrop (n-1) xs=0A=
=0A=
powersOf n =3D 1 : (map (*n) (powersOf n))=0A=
=0A=
toBase x =3D =0A=
   map fromIntegral .=0A=
   reverse .=0A=
   map (flip mod x) .=0A=
   takeWhile (/=3D0) .=0A=
   iterate (flip div x)=0A=
=0A=
-- * CBC or Cipher Block Chaining Mode=0A=
=0A=
-- | In CBC or Cipher Block Chaining mode each block is XORed with =0A=
-- the previous enciphered block before encryption.  For the first =0A=
-- block we start with an initialization vector.=0A=
=0A=
cbc :: Bits block =3D>=0A=
       (key -> block -> block) -> =0A=
       block -> =0A=
       key ->=0A=
       [block] -> =0A=
       [block]=0A=
=0A=
cbc e iv k ps =3D =0A=
   ciphers where=0A=
      ciphers =3D map (e k) feedIns=0A=
      feedIns =3D zipWith xor (iv : ciphers) ps=0A=
=0A=
-- | To  decipher in CBC or Cipher Block Chaining mode we decipher =0A=
-- each block, then XOR the result with the previous block of =0A=
-- plaintext result.  Note that we treat the initialization vector as =
the zeroth block of plaintext.=0A=
=0A=
unCbc :: Bits block =3D>=0A=
         (key -> block -> block) -> =0A=
         block -> =0A=
         key ->=0A=
         [block] -> =0A=
         [block]=0A=
=0A=
unCbc d iv k ms =3D=0A=
   outOfCbcs where=0A=
      beforeXOrs =3D map (d k) ms=0A=
      outOfCbcs  =3D zipWith xor (iv : ms) beforeXOrs=0A=
=0A=
-- * PKCS#5 Padding Method=0A=
=0A=
-- | When the last block of plaintext is shorter than the block size =
then it=0A=
-- must be padded. PKCS#5 specifies that the padding octets should each =0A=
-- contain the number of octets which must be stripped off. So, for =
example,=0A=
-- with a block size of 8, "0a0b0c" will be padded with "05" resulting in=0A=
-- "0a0b0c0505050505". If the final block is a full block of 8 octets=0A=
-- then a whole block of "0808080808080808" is appended.=0A=
=0A=
pkcs5 s =3D=0A=
   blocks where=0A=
      octetSize =3D (bitSize $ head blocks) `div` 8=0A=
      blocks =3D map fromOctets (unfoldr h $ concat $ unfoldr g s) =0A=
      g :: [Octet] -> Maybe ([Octet],[Octet])=0A=
      g x =0A=
         | l =3D=3D 0         =3D Nothing=0A=
         | l <  octetSize =3D Just (t ++ (p (octetSize-l)), [])=0A=
         | d =3D=3D []        =3D Just (t ++ (p octetSize), [])=0A=
         | otherwise      =3D Just (t, d)=0A=
         where l   =3D length t=0A=
               t   =3D take octetSize x=0A=
	       d   =3D drop octetSize x=0A=
	       p n =3D replicate n (fromIntegral n)=0A=
      h :: [Octet] -> Maybe ([Octet],[Octet])=0A=
      h x =0A=
         | x =3D=3D []   =3D Nothing=0A=
         | otherwise =3D Just (take octetSize x, drop octetSize x)=0A=
=0A=
toOctets :: Integral a =3D> a -> [Octet]=0A=
toOctets x =3D (toBase 256 . fromIntegral) x=0A=
=0A=
type Octet =3D Word8=0A=
=0A=
fromOctets :: Num a =3D> [Octet] -> a=0A=
fromOctets x =3D =0A=
   sum $ zipWith (*) (powersOf 256) =0A=
                     (reverse (map fromIntegral x))=0A=
=0A=
unPkcs5 ws =3D =0A=
   concat $ map toOctets (concat $ unfoldr g ws) where=0A=
      g :: (Integral a, Bits a) =3D> [a] -> Maybe ([a],[a])=0A=
      g x =0A=
         | t =3D=3D []   =3D Nothing=0A=
         | d =3D=3D []   =3D Just ([s], [])=0A=
         | otherwise =3D Just (t, d)=0A=
         where t   =3D take 1 x=0A=
	       d   =3D drop 1 x=0A=
	       u   =3D head t=0A=
               octetSize =3D (bitSize u) `div` 8=0A=
               h x =3D take (octetSize - (fromIntegral (last x))) x=0A=
	       s   =3D fromOctets $ h $ toOctets u=0A=
=0A=
-- * Basic DES Encryption=0A=
=0A=
-- | Basic DES encryption which takes a key and a block of plaintext =0A=
-- and returns the encrypted block of ciphertext according to the =
standard.=0A=
=0A=
des :: Zord64 -> Zord64 -> Zord64=0A=
des =3D flip des_enc=0A=
=0A=
-- | Basic DES decryption which takes a key and a block of ciphertext and=0A=
-- returns the decrypted block of plaintext according to the standard.=0A=
=0A=
unDes :: Zord64 -> Zord64 -> Zord64=0A=
unDes =3D flip des_dec=0A=

------=_NextPart_000_0007_01C30DC6.85F1AE00
Content-Type: application/octet-stream;
	name="ITest.hs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="ITest.hs"

module Main(main) where=0A=
=0A=
import Crypto=0A=
import Char=0A=
=0A=
plainText =3D  "Good morning Mr. Phelps.  Your m" ++=0A=
             "ission,\nshould you choose to acc" ++=0A=
             "ept it, is to learn to use DES.\NUL"=0A=
=0A=
iv  =3D 0x0123456789abcdef=0A=
=0A=
key =3D 0x42652d4861707079=0A=
=0A=
cipherText =3D cbc des iv key $ pkcs5 $ map (fromIntegral . ord) =
plainText=0A=
=0A=
plainText' =3D map (chr . fromIntegral) $ unPkcs5 $ unCbc unDes iv key =
cipherText=0A=
=0A=
main =3D putStrLn plainText'=0A=

------=_NextPart_000_0007_01C30DC6.85F1AE00
Content-Type: application/octet-stream;
	name="ZordHUGS.lhs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="ZordHUGS.lhs"

=0A=
> module ZordHUGS (Zord64) where=0A=
=0A=
> import Data.Word=0A=
> import Data.Bits=0A=
> import Numeric=0A=
=0A=
> data Zord64 =3D W64 {lo,hi::Word32} deriving (Eq, Ord, Bounded)=0A=
=0A=
> w64ToInteger W64{lo=3Dlo,hi=3Dhi} =3D toInteger lo + 0x100000000 * =
toInteger hi=0A=
> integerToW64 x =3D case x `quotRem` 0x100000000 of=0A=
>                  (h,l) -> W64{lo=3DfromInteger l, hi=3DfromInteger h}=0A=
=0A=
> instance Show Zord64 where=0A=
>   showsPrec p =3D showInt . w64ToInteger=0A=
=0A=
> instance Read Zord64 where=0A=
>   readsPrec p s =3D [ (integerToW64 x,r) | (x,r) <- readDec s ]=0A=
=0A=
> instance Num Zord64 where=0A=
>  W64{lo=3Dlo_a,hi=3Dhi_a} + W64{lo=3Dlo_b,hi=3Dhi_b} =3D W64{lo=3Dlo', =
hi=3Dhi'}=0A=
>   where lo' =3D lo_a + lo_b=0A=
>         hi' =3D hi_a + hi_b + if lo' < lo_a then 1 else 0=0A=
>  fromInteger =3D integerToW64=0A=
=0A=
> instance Bits Zord64 where=0A=
>  W64{lo=3Dlo_a,hi=3Dhi_a} .&. W64{lo=3Dlo_b,hi=3Dhi_b} =3D =
W64{lo=3Dlo', hi=3Dhi'}=0A=
>   where lo' =3D lo_a .&. lo_b=0A=
>         hi' =3D hi_a .&. hi_b=0A=
>  W64{lo=3Dlo_a,hi=3Dhi_a} .|. W64{lo=3Dlo_b,hi=3Dhi_b} =3D =
W64{lo=3Dlo', hi=3Dhi'}=0A=
>   where lo' =3D lo_a .|. lo_b=0A=
>         hi' =3D hi_a .|. hi_b=0A=
>  shift w 0 =3D w=0A=
>  shift W64{lo=3Dlo,hi=3Dhi} x=0A=
>   | x > 63 =3D W64{lo=3D0,hi=3D0}=0A=
>   | x > 31 =3D W64{lo =3D 0, hi =3D shift lo (x-32)}=0A=
>   | x > 0 =3D W64{lo =3D shift lo x, hi =3D shift hi x .|. shift lo =
(x-32)}=0A=
>  xor W64{lo=3Dalo,hi=3Dahi} W64{lo=3Dblo,hi=3Dbhi} =3D =0A=
>    W64{lo=3Dalo `xor` blo, hi=3Dahi `xor` bhi}=0A=
=0A=
> instance Integral Zord64 where=0A=
>  toInteger =3D w64ToInteger=0A=
=0A=
> instance Real Zord64=0A=
> instance Enum Zord64=0A=
=0A=

------=_NextPart_000_0007_01C30DC6.85F1AE00
Content-Type: application/octet-stream;
	name="Makefile"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="Makefile"

PACKAGES=3D-package data=0A=
HCFLAGS=3D$(PACKAGES) =0A=
LINKFLAGS=3D$(PACKAGES)=0A=
CPP=3D -cpp -DBEGIN_GHC_ONLY=3D'-}' -DEND_GHC_ONLY=3D'{-' \=0A=
     -DBEGIN_HUGS_ONLY=3D'{-' -DEND_HUGS_ONLY=3D'-}'=0A=
HC =3D ghc=0A=
=0A=
SRCS=3DCrypto.hs ITest.hs=0A=
OBJS=3DCrypto.o  ITest.o=0A=
=0A=
all: ITest=0A=
=0A=
doc: Crypto.hs=0A=
	$(HC) -E Crypto.hs -o Crypto.hspp=0A=
	sed -e '/^#/d' Crypto.hspp > Crypto-hash.hspp=0A=
	haddock -h Crypto-hash.hspp=0A=
	rm Crypto.hspp Crypto-hash.hspp=0A=
=0A=
ITest: ITest.o=0A=
	$(HC) $(PACKAGES) -o ITest $(OBJS)=0A=
=0A=
Crypto.o: Crypto.hs=0A=
	$(HC) $(HCFLAGS) -fglasgow-exts $(CPP) -c $<=0A=
=0A=
%.o: %.hs=0A=
	$(HC) $(HCFLAGS) -c $<=0A=
=0A=
clean:=0A=
	rm -f *.o *.hi ITest=0A=
=0A=
depend:=0A=
	ghc -M $(PACKAGES) $(SRCS) $(CPP)=0A=
	sed "s/\([^\*\\]\)\.hi/\1.o/g" < Makefile > Makefile.new=0A=
	mv Makefile.new Makefile=0A=
# DO NOT DELETE: Beginning of Haskell dependencies=0A=
Crypto.o : Crypto.hs=0A=
ITest.o : ITest.hs=0A=
ITest.o : Crypto.o=0A=
# DO NOT DELETE: End of Haskell dependencies=0A=

------=_NextPart_000_0007_01C30DC6.85F1AE00--