packages feed

cipher-rc4 (empty) → 0.1.0

raw patch · 8 files changed

+344/−0 lines, 8 filesdep +QuickCheckdep +basedep +bytestringsetup-changed

Dependencies added: QuickCheck, base, bytestring, cipher-rc4, criterion, deepseq, mtl, test-framework, test-framework-quickcheck2, vector

Files

+ Benchmarks/Benchmarks.hs view
@@ -0,0 +1,34 @@+module Main where++import Criterion.Main++import Crypto.Cipher.RC4+import qualified Data.ByteString as B+import Control.DeepSeq++instance NFData Ctx where+    rnf (Ctx c) = c `seq` ()++main = defaultMain+    [ bgroup "init"+        [ bench "1"    $ whnf initCtx b1+        , bench "8"    $ whnf initCtx b8+        , bench "32"   $ whnf initCtx b32+        , bench "64"   $ whnf initCtx b64+        , bench "256"  $ whnf initCtx b256+        ]+    , bgroup "encrypt"+        [ bench "8"    $ nf (encrypt ctx) b8+        , bench "32"   $ nf (encrypt ctx) b32+        , bench "64"   $ nf (encrypt ctx) b64+        , bench "256"  $ nf (encrypt ctx) b256+        , bench "1024" $ nf (encrypt ctx) b1024+        ]+    ]+    where b1    = B.replicate 1 0xf7+          b8    = B.replicate 8 0xf7+          b32   = B.replicate 32 0xf7+          b64   = B.replicate 64 0x7f+          b256  = B.replicate 256 0x7f+          b1024 = B.replicate 1024 0x7f+          ctx   = initCtx $ B.pack [1..10]
+ Crypto/Cipher/RC4.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Cipher.RC4+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : stable+-- Portability : Good+--+-- Initial FFI implementation by Peter White <peter@janrain.com>+--+-- Reorganized and simplified to have an opaque context.+--+module Crypto.Cipher.RC4+    ( Ctx(..)+    , initCtx+    , generate+    , combine+    , encrypt+    , decrypt+    ) where++import Data.Word+import Foreign.Ptr+import Foreign.ForeignPtr+import System.IO.Unsafe (unsafeDupablePerformIO)+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as B+import Control.Applicative ((<$>))++----------------------------------------------------------------------++-- | The encryption context for RC4+newtype Ctx = Ctx B.ByteString++instance Show Ctx where+    show _ = "RC4.Ctx"++-- | C Call for initializing the encryptor+foreign import ccall unsafe "rc4.h rc4_init"+    c_rc4_init :: Ptr Word8 -- ^ The rc4 key+               -> Word32    -- ^ The key length+               -> Ptr Ctx   -- ^ The context+               -> IO ()++foreign import ccall unsafe "rc4.h rc4_combine"+    c_rc4_combine :: Ptr Ctx        -- ^ Pointer to the permutation+                  -> Ptr Word8      -- ^ Pointer to the clear text+                  -> Word32         -- ^ Length of the clear text+                  -> Ptr Word8      -- ^ Output buffer+                  -> IO ()++withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a+withByteStringPtr b f = withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off)+    where (fptr, off, _) = B.toForeignPtr b++-- | RC4 context initialization.+--+-- seed the context with an initial key. the key size need to be+-- adequate otherwise security takes a hit.+initCtx :: B.ByteString -- ^ The key+        -> Ctx          -- ^ The RC4 context with the key mixed in+initCtx key = unsafeDupablePerformIO $+    Ctx <$> (B.create 264 $ \ctx -> B.useAsCStringLen key $ \(keyPtr,keyLen) -> c_rc4_init (castPtr keyPtr) (fromIntegral keyLen) (castPtr ctx))++-- | generate the next len bytes of the rc4 stream without combining+-- it to anything.+generate :: Ctx -> Int -> (Ctx, B.ByteString)+generate ctx len = combine ctx (B.replicate len 0)++-- | RC4 xor combination of the rc4 stream with an input+combine :: Ctx                 -- ^ rc4 context+        -> B.ByteString        -- ^ input+        -> (Ctx, B.ByteString) -- ^ new rc4 context, and the output+combine (Ctx cctx) clearText = unsafeDupablePerformIO $+    B.mallocByteString 264 >>= \dctx ->+    B.mallocByteString len >>= \outfptr ->+    withByteStringPtr clearText $ \clearPtr ->+    withByteStringPtr cctx $ \srcCtx ->+    withForeignPtr dctx $ \dstCtx -> do+    withForeignPtr outfptr $ \outptr -> do+        B.memcpy dstCtx srcCtx 264+        c_rc4_combine (castPtr dstCtx) clearPtr (fromIntegral len) outptr+        return $! (Ctx $! B.PS dctx 0 264, B.PS outfptr 0 len)+    where len = B.length clearText++{-# DEPRECATED encrypt "use combine instead" #-}+{-# DEPRECATED decrypt "use combine instead" #-}+encrypt,decrypt :: Ctx -> B.ByteString -> (Ctx, B.ByteString)+encrypt = combine+decrypt = combine
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2008-2012 Vincent Hanquez <vincent@snarc.org>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Tests/Tests.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+module Main where++import Control.Applicative+import Control.Monad++import Test.Framework (Test, defaultMain, testGroup)+import Test.Framework.Providers.QuickCheck2 (testProperty)++import Test.QuickCheck+import Test.QuickCheck.Test+import Test.Framework.Providers.QuickCheck2 (testProperty)++import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import qualified Crypto.Cipher.RC4 as RC4++-- taken from wikipedia pages+kats :: [ (B.ByteString, B.ByteString, B.ByteString) ]+kats =+    [   ("Key"+        ,"Plaintext"+        ,B.pack [0xBB,0xF3,0x16,0xE8,0xD9,0x40,0xAF,0x0A,0xD3]+        )+    ,   ("Wiki"+        ,"pedia"+        ,B.pack [0x10,0x21,0xBF,0x04,0x20]+        )+    ,   ("Secret"+        ,"Attack at dawn"+        ,B.pack [0x45,0xA0,0x1F,0x64,0x5F,0xC3,0x5B,0x38,0x35,0x52,0x54,0x4B,0x9B,0xF5]+        )+    ]++runKat (key,plainText,cipherText) =+       snd (RC4.encrypt ctx plainText)  == cipherText+    && snd (RC4.decrypt ctx cipherText) == plainText+    where ctx = RC4.initCtx $ key++katToTestProperty (kat, i) = testProperty ("KAT " ++ show i) (runKat kat)++data RC4Unit = RC4Unit B.ByteString B.ByteString+    deriving (Show)++instance Arbitrary RC4Unit where+    arbitrary = RC4Unit <$> generateKey <*> generatePlaintext++generateKey = choose (1, 284) >>= \sz -> (B.pack <$> replicateM sz arbitrary)+generatePlaintext = choose (0,324) >>= \sz -> (B.pack <$> replicateM sz arbitrary)++runOp f1 f2 (RC4Unit key plainText) =+    let ctx = RC4.initCtx key+     in (snd $ f2 ctx $ snd $ f1 ctx plainText) == plainText++tests =+    [ testGroup "KAT-RC4" $ map katToTestProperty $ zip kats [0..]+    , testGroup "id"+        [ testProperty "encrypt.decrypt" (runOp RC4.decrypt RC4.encrypt)+        , testProperty "decrypt.encrypt" (runOp RC4.encrypt RC4.decrypt)+        ]+    ]++main = defaultMain tests
+ cbits/rc4.c view
@@ -0,0 +1,63 @@+/* initial implementation by+ *   Peter White <peter@janrain.com>+ */++/* C Standard includes */+#include <stdlib.h>+#include <stdio.h>+#include <string.h>+#include <stdint.h>++/* Local include */+#include "rc4.h"++/* Swap array elements i=State[i] and b=State[j]. */+static void swap(uint8_t *i, uint8_t *j)+{+	uint8_t temp;++	temp = *i;+	*i = *j;+	*j = temp;+}++/* Key scheduling algorithm. Swap array elements based on the key. */+void rc4_init(uint8_t *key, uint32_t keylen, struct rc4_ctx *ctx)+{+	uint32_t i, j;+	memset(ctx, 0, sizeof(struct rc4_ctx));++	/* initialize context */+	for (i = 0; i < 256; i++)+		ctx->state[i] = i;+	for (i = j = 0; i < 256; i++) {+		j = (j + ctx->state[i] + key[i % keylen]) % 256;+		swap(&ctx->state[i], &ctx->state[j]);+	}+}++/* Combine the stream generated by the rc4 with some input */+void rc4_combine(struct rc4_ctx *ctx, uint8_t *input, uint32_t len, uint8_t *output)+{+	uint32_t i = ctx->i;+	uint32_t j = ctx->j;+	uint32_t m;+	uint8_t si, sj;++	/* The RC4 algorithm */+	for (m = 0; m < len; m++) {+		i = (i + 1) & 0xff;+		si = ctx->state[i];+		j = (j + si) & 0xff;+		sj = ctx->state[j];+		/* swap(&state[i], &state[j]); */+		ctx->state[i] = sj;+		ctx->state[j] = si;+		/* Xor the key stream value into the input */+		*output++ = *input++ ^ (ctx->state[(si + sj) & 0xff]);+	}++	/* Output new S-box indices */+	ctx->i = i;+	ctx->j = j;+}
+ cbits/rc4.h view
@@ -0,0 +1,14 @@+#ifndef RC4_H+# define RC4_H++struct rc4_ctx+{+	uint8_t state[256];+	uint32_t i;+	uint32_t j;+};++void rc4_init(uint8_t * key, uint32_t keylen, struct rc4_ctx *ctx);+void rc4_combine(struct rc4_ctx *ctx, uint8_t *input, uint32_t len, uint8_t *output);++#endif
+ cipher-rc4.cabal view
@@ -0,0 +1,49 @@+Name:                cipher-rc4+Version:             0.1.0+Description:         Fast RC4 cipher implementation+License:             BSD3+License-file:        LICENSE+Copyright:           Vincent Hanquez <vincent@snarc.org>+Author:              Vincent Hanquez <vincent@snarc.org>+Maintainer:          Vincent Hanquez <vincent@snarc.org>+Synopsis:            Fast RC4 cipher implementation+Category:            Cryptography+Build-Type:          Simple+Homepage:            http://github.com/vincenthz/hs-cipher-rc4+Cabal-Version:       >=1.8+Extra-Source-Files:  Tests/*.hs+                     cbits/*.h++Library+  Build-Depends:     base >= 4 && < 5+                   , bytestring+                   , vector+  Exposed-modules:   Crypto.Cipher.RC4+  ghc-options:       -Wall+  C-sources:         cbits/rc4.c++Test-Suite test-cipher-rc4+  type:              exitcode-stdio-1.0+  hs-source-dirs:    Tests+  Main-Is:           Tests.hs+  Build-depends:     base >= 4 && < 5+                   , cipher-rc4+                   , bytestring+                   , QuickCheck >= 2+                   , test-framework >= 0.3.3+                   , test-framework-quickcheck2 >= 0.2.9++Benchmark bench-cipher-rc4+  hs-source-dirs:    Benchmarks+  Main-Is:           Benchmarks.hs+  type:              exitcode-stdio-1.0+  Build-depends:     base >= 4 && < 5+                   , bytestring+                   , cipher-rc4+                   , deepseq+                   , criterion+                   , mtl++source-repository head+  type:     git+  location: git://github.com/vincenthz/hs-cipher-rc4