cipher-rc4-0.1.4/0000755000000000000000000000000012224677601011651 5ustar0000000000000000cipher-rc4-0.1.4/LICENSE0000644000000000000000000000273112224677601012661 0ustar0000000000000000Copyright (c) 2008-2012 Vincent Hanquez 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. cipher-rc4-0.1.4/Setup.hs0000644000000000000000000000005612224677601013306 0ustar0000000000000000import Distribution.Simple main = defaultMain cipher-rc4-0.1.4/cipher-rc4.cabal0000644000000000000000000000350112224677601014574 0ustar0000000000000000Name: cipher-rc4 Version: 0.1.4 Description: Fast RC4 cipher implementation License: BSD3 License-file: LICENSE Copyright: Vincent Hanquez Author: Vincent Hanquez Maintainer: Vincent Hanquez 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 , byteable , crypto-cipher-types >= 0.0.5 && < 0.1 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 , crypto-cipher-types >= 0.0.5 , crypto-cipher-tests >= 0.0.7 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 , crypto-cipher-types >= 0.0.5 , crypto-cipher-benchmarks >= 0.0.3 , deepseq , criterion , mtl source-repository head type: git location: git://github.com/vincenthz/hs-cipher-rc4 cipher-rc4-0.1.4/cbits/0000755000000000000000000000000012224677601012755 5ustar0000000000000000cipher-rc4-0.1.4/cbits/rc4.c0000644000000000000000000000254412224677601013616 0ustar0000000000000000/* initial implementation by * Peter White */ /* C Standard includes */ #include #include #include #include /* 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; } cipher-rc4-0.1.4/cbits/rc4.h0000644000000000000000000000040412224677601013614 0ustar0000000000000000#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-0.1.4/Benchmarks/0000755000000000000000000000000012224677601013726 5ustar0000000000000000cipher-rc4-0.1.4/Benchmarks/Benchmarks.hs0000644000000000000000000000021512224677601016335 0ustar0000000000000000module Main where import Crypto.Cipher.Benchmarks import Crypto.Cipher.RC4 main = defaultMainAll [Stream $ GStreamCipher (undefined :: RC4)] cipher-rc4-0.1.4/Crypto/0000755000000000000000000000000012224677601013131 5ustar0000000000000000cipher-rc4-0.1.4/Crypto/Cipher/0000755000000000000000000000000012224677601014343 5ustar0000000000000000cipher-rc4-0.1.4/Crypto/Cipher/RC4.hs0000644000000000000000000000754512224677601015302 0ustar0000000000000000{-# LANGUAGE ForeignFunctionInterface, CPP #-} -- | -- Module : Crypto.Cipher.RC4 -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : stable -- Portability : Good -- -- Simple implementation of the RC4 stream cipher. -- http://en.wikipedia.org/wiki/RC4 -- -- Initial FFI implementation by Peter White -- -- Reorganized and simplified to have an opaque context. -- module Crypto.Cipher.RC4 ( RC4 -- * deprecated types , Ctx(..) -- * deprecated functions, use crypto-cipher-types StreamCipher function , initCtx , generate , combine , encrypt , decrypt ) where import Data.Word import Data.Byteable import Foreign.Ptr import Foreign.ForeignPtr import System.IO.Unsafe import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Internal as B import Control.Applicative ((<$>)) import Crypto.Cipher.Types ---------------------------------------------------------------------- unsafeDoIO :: IO a -> a #if __GLASGOW_HASKELL__ > 704 unsafeDoIO = unsafeDupablePerformIO #else unsafeDoIO = unsafePerformIO #endif -- | RC4 Stream cipher newtype RC4 = RC4 Ctx instance Byteable RC4 where toBytes (RC4 (Ctx b)) = b instance Cipher RC4 where cipherInit key = RC4 (initCtx $ toBytes key) cipherName _ = "RC4" cipherKeySize _ = KeySizeRange 1 1024 instance StreamCipher RC4 where streamCombine (RC4 ctx) b = (\(ctx2, r) -> (r, RC4 ctx2)) $ combine ctx b -- | 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 = unsafeDoIO $ 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 = unsafeDoIO $ 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 cipher-rc4-0.1.4/Tests/0000755000000000000000000000000012224677601012753 5ustar0000000000000000cipher-rc4-0.1.4/Tests/Tests.hs0000644000000000000000000000201412224677601014406 0ustar0000000000000000{-# 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 Crypto.Cipher.RC4 (RC4) import Crypto.Cipher.Types import Crypto.Cipher.Tests -- taken from wikipedia pages kats :: [KAT_Stream] kats = map (\(k,p,c) -> KAT_Stream k p c) [ ("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] ) ] main = defaultMain [ testStreamCipher kats (undefined :: RC4) ]