File: RC4.hs

package info (click to toggle)
haskell-crypton 1.0.4-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,548 kB
  • sloc: haskell: 26,764; ansic: 22,294; makefile: 6
file content (105 lines) | stat: -rw-r--r-- 3,015 bytes parent folder | download
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

-- |
-- Module      : Crypto.Cipher.RC4
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : stable
-- Portability : Good
--
-- Simple implementation of the RC4 stream cipher.
-- http://en.wikipedia.org/wiki/RC4
--
-- Initial FFI implementation by Peter White <peter@janrain.com>
--
-- Reorganized and simplified to have an opaque context.
module Crypto.Cipher.RC4 (
    initialize,
    combine,
    generate,
    State,
) where

import Crypto.Internal.ByteArray (
    ByteArray,
    ByteArrayAccess,
    ScrubbedBytes,
 )
import qualified Crypto.Internal.ByteArray as B
import Data.Word
import Foreign.Ptr

import Crypto.Internal.Compat
import Crypto.Internal.Imports

-- | The encryption state for RC4
--
-- This type is an instance of 'ByteArrayAccess' for debugging purpose. Internal
-- layout is architecture dependent, may contain uninitialized data fragments,
-- and change in future versions.  The bytearray should not be used as input to
-- cryptographic algorithms.
newtype State = State ScrubbedBytes
    deriving (ByteArrayAccess, NFData)

-- | C Call for initializing the encryptor
foreign import ccall unsafe "crypton_rc4.h crypton_rc4_init"
    c_rc4_init
        :: Ptr Word8
        -- ^ The rc4 key
        -> Word32
        -- ^ The key length
        -> Ptr State
        -- ^ The context
        -> IO ()

foreign import ccall unsafe "crypton_rc4.h crypton_rc4_combine"
    c_rc4_combine
        :: Ptr State
        -- ^ Pointer to the permutation
        -> Ptr Word8
        -- ^ Pointer to the clear text
        -> Word32
        -- ^ Length of the clear text
        -> Ptr Word8
        -- ^ Output buffer
        -> IO ()

-- | RC4 context initialization.
--
-- seed the context with an initial key. the key size need to be
-- adequate otherwise security takes a hit.
initialize
    :: ByteArrayAccess key
    => key
    -- ^ The key
    -> State
    -- ^ The RC4 context with the key mixed in
initialize key = unsafeDoIO $ do
    st <- B.alloc 264 $ \stPtr ->
        B.withByteArray key $ \keyPtr -> c_rc4_init keyPtr (fromIntegral $ B.length key) (castPtr stPtr)
    return $ State st

-- | generate the next len bytes of the rc4 stream without combining
-- it to anything.
generate :: ByteArray ba => State -> Int -> (State, ba)
generate ctx len = combine ctx (B.zero len)

-- | RC4 xor combination of the rc4 stream with an input
combine
    :: ByteArray ba
    => State
    -- ^ rc4 context
    -> ba
    -- ^ input
    -> (State, ba)
    -- ^ new rc4 context, and the output
combine (State prevSt) clearText = unsafeDoIO $
    B.allocRet len $ \outptr ->
        B.withByteArray clearText $ \clearPtr -> do
            st <- B.copy prevSt $ \stPtr ->
                c_rc4_combine (castPtr stPtr) clearPtr (fromIntegral len) outptr
            return $! State st
  where
    -- return $! (State st, B.PS outfptr 0 len)
    len = B.length clearText