RC4 Haskell und JavaScript

RC4 in JavaScript: (Quelle)

/*
 * RC4 symmetric cipher encryption/decryption
 *
 * @license Public Domain
 * @param string key - secret key for encryption/decryption
 * @param string str - string to be encrypted/decrypted
 * @return string
 */
function rc4(key, str) {
	var s = [], j = 0, x, res = '';
	for (var i = 0; i < 256; i++) {
		s[i] = i;
	}
	for (i = 0; i < 256; i++) {
		j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
		x = s[i];
		s[i] = s[j];
		s[j] = x;
	}
	i = 0;
	j = 0;
	for (var y = 0; y < str.length; y++) {
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		x = s[i];
		s[i] = s[j];
		s[j] = x;
		res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
	}
	return res;
}

RC4 in Haskell:

module RC4
(
 encode,
 decode
)
where
 
import Data.Map (Map, (!))
import qualified Data.Map as Map
import Data.Char (ord, chr)
import Data.Bits (xor)
 
encode :: String -> String -> String
encode = rc4
 
decode :: String -> String -> String
decode = rc4
 
initS = Map.fromList $ zip [0 .. 255] [0 .. 255]
 
rc4 :: String -> String -> String
rc4 key str =
    resultStr
    where
      (_, s) = foldl mkBox (0, initS) [0 .. 255]
      mkBox (inpJ, inpS) i =
          (j, s'')
          where
            j = (inpJ + (inpS ! i) + (ord (key !! (i `mod` (length key))))) `mod` 256
            x = inpS ! i
            s' = Map.insert i (inpS ! j) inpS
            s'' = Map.insert j x s'
 
      (resultStr, _, _, _) = result
 
      result = foldl core ("", 0, 0, s) [0 .. ((length str) - 1)]
      core (res, inpI, inpJ, inpS) y =
          (res', i, j, s'')
          where
            i = (inpI + 1) `mod` 256
            j = (inpJ + (inpS ! i)) `mod` 256
            x = inpS ! i
            s' =  Map.insert i (inpS ! j) inpS
            s'' = Map.insert j x s'
            k = ((s'' ! i) + (s'' ! j)) `mod` 256
            res' = res ++ [chr $ (ord (str !! y)) `xor` (s'' ! k)]

GHC 7.6 auf Mac OSX Lion installieren

Heute musste ich mal wieder GHC 7.6 und cabal-install auf eine Mac installieren. Ich möchte hier nur kurz meine Vorgehensweise dokumentieren:

GHC installieren

Folgende Befehle laden und installieren GHC:

curl -O http://www.haskell.org/ghc/dist/7.6.1/ghc-7.6.1-x86_64-apple-darwin.tar.bz2
tar -xjvf ghc-7.6.1-x86_64-apple-darwin.tar.bz2
cd ghc-7.6.1
./configure
make install

Hinweis: Möchte man ein eigenes Ziel-Directory für die GHC-Binaries wählen, geht das per ./configure --prefix=(hier der pfad)

cabal-install installieren

Folgende Befehle laden und installieren cabal-install (1.16.0)

curl -O http://hackage.haskell.org/packages/archive/cabal-install/1.16.0/cabal-install-1.16.0.tar.gz
tar -xzvf cabal-install-1.16.0.tar.gz
cd cabal-install-1.16.0
sh bootstrap.sh

Haskell: Multiplikatives Inverse in einem Restklassenring

Das multiplikative Inverse einer Restklasse in einem Restklassenring kann man in Haskell mit folgendem Snippet berrechnen:

-- multiplicative inverse for a in Z \ bZ
mulInverse :: (Int, Int) -> Int
mulInverse (a, m) =
  (x + m) `mod` m
  where
    (gcd, (x, y)) = euclid a m
 
-- returns (gcd(a,b), (x, y)) in eq ax + by = gcd(a,b)
euclid :: Int -> Int -> (Int, (Int, Int))
euclid 0 b = (b, (0, 1))
euclid a b = 
  (gcd, (y - (x*(b `div` a)), x))
  where
    (gcd, (x, y)) = euclid (b `mod` a) a

Beispiel: Das multiplikative Inverse für 8 im Restklassenring Z / 21 Z ist 8.

$ ghci mulInverse.hs
*Main> mulInverse (8, 21)
8