diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+0.1.0.20
+--------
+* Rewrite Encrypt module, cache password hash
+
 0.1.0.19
 --------
 * Fix a memory leak
diff --git a/moesocks.cabal b/moesocks.cabal
--- a/moesocks.cabal
+++ b/moesocks.cabal
@@ -1,6 +1,6 @@
 name:               moesocks
 category:           Network
-version:            0.1.0.19
+version:            0.1.0.20
 license:            Apache-2.0
 synopsis:           A functional firewall killer
 description:        A socks5 proxy using the client / server architecture.
@@ -54,13 +54,13 @@
   other-modules:        
                       Network.MoeSocks.App
                       Network.MoeSocks.BuilderAndParser
+                      Network.MoeSocks.Common
                       Network.MoeSocks.Config
                       Network.MoeSocks.Constant
                       Network.MoeSocks.Helper
-                      Network.MoeSocks.Internal.ShadowSocks.Encrypt
                       Network.MoeSocks.Options
-                      Network.MoeSocks.Type
-                      Network.MoeSocks.Common
                       Network.MoeSocks.TCP
+                      Network.MoeSocks.Type
                       Network.MoeSocks.UDP
+                      Network.MoeSocks.Encrypt
 
diff --git a/src/Network/MoeSocks/App.hs b/src/Network/MoeSocks/App.hs
--- a/src/Network/MoeSocks/App.hs
+++ b/src/Network/MoeSocks/App.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE LambdaCase #-}
 
 module Network.MoeSocks.App where
 
@@ -20,10 +21,9 @@
 import Network.MoeSocks.TCP
 import Network.MoeSocks.Type
 import Network.MoeSocks.UDP
+import Network.MoeSocks.Encrypt (initBuilder)
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
 import Network.Socket.ByteString
-import OpenSSL (withOpenSSL)
-import OpenSSL.EVP.Cipher (getCipherByName)
 import Prelude hiding ((-), take)
 import System.Log.Formatter
 import System.Log.Handler.Simple
@@ -176,15 +176,12 @@
   _config <- parseConfig - _options
   let _c = _config
 
-  let _method = _config ^. method . _Text
-
-  when (_method /= "none") - do
-    _cipher <- io - withOpenSSL - getCipherByName _method
+  let _method = _config ^. method
 
-    case _cipher of
-      Nothing -> throwError - "Invalid method '" 
-                              <> _method
-      Just _ -> pure ()
+  _cipherBox <- (io - initBuilder _method (_config ^. password)) >>= \case
+    Nothing -> throwError - "Invalid method '" 
+                            <> _method ^. _Text
+    Just (a, b, c, d) -> pure - CipherBox a b c d
 
   let localAppBuilder :: AppType -> String -> 
                           (ByteString -> (Socket, SockAddr) -> IO ()) -> 
@@ -229,7 +226,7 @@
 
   let localSocks5App :: (Socket, SockAddr) -> IO ()
       localSocks5App = localAppBuilder TCP_App "socks5" - 
-                            local_Socks5_RequestHandler _config
+                            local_Socks5_RequestHandler _cipherBox _config
 
       showForwarding :: Forward -> String
       showForwarding (Forward _localPort _remoteHost _remotePort) =
@@ -246,14 +243,16 @@
       forward_TCP_App _f _s = do
         let _m = showForwarding _f
         localAppBuilder TCP_App  ("TCP forwarding " <> _m)
-                                (local_TCP_ForwardRequestHandler _config _f) 
+                                (local_TCP_ForwardRequestHandler _cipherBox 
+                                _config _f) 
                                 _s
 
       forward_UDP_App :: Forward -> (Socket, SockAddr) -> IO ()
       forward_UDP_App _f _s = do
         let _m = showForwarding _f 
         localAppBuilder UDP_App  ("UDP forwarding " <> _m)
-                                (local_UDP_ForwardRequestHandler _config _f) 
+                                (local_UDP_ForwardRequestHandler _cipherBox
+                                _config _f) 
                                 _s
       
   let remote_TCP_App :: (Socket, SockAddr) -> IO ()
@@ -276,7 +275,7 @@
                 
                 forkIO - catchExceptAsyncLog "R thread" - 
                             logSocket "R remote socket" (pure _newSocket) -
-                              remote_TCP_RequestHandler _config 
+                              remote_TCP_RequestHandler _cipherBox _config 
 
           forever - handleRemote _remoteSocket
 
@@ -297,7 +296,7 @@
 
 
                 forkIO - catchExceptAsyncLog "R thread" - 
-                            remote_UDP_RequestHandler _config _msg _s
+                            remote_UDP_RequestHandler _cipherBox _config _msg _s
 
                 
 
diff --git a/src/Network/MoeSocks/Common.hs b/src/Network/MoeSocks/Common.hs
--- a/src/Network/MoeSocks/Common.hs
+++ b/src/Network/MoeSocks/Common.hs
@@ -4,24 +4,17 @@
 
 import Control.Lens
 import Control.Monad.Writer hiding (listen)
-import Data.ByteString (ByteString)
 import Data.Text (Text)
 import Data.Text.Lens
-import Data.Text.Strict.Lens (utf8)
 import Network.MoeSocks.Helper
-import Network.MoeSocks.Internal.ShadowSocks.Encrypt as E
 import Network.MoeSocks.Type
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
 import Prelude hiding ((-), take)
 import qualified Data.List as L
-import qualified Data.Strict as S
+import qualified Network.MoeSocks.Encrypt as E
 
-plainCipher :: (S.Maybe ByteString) -> IO ByteString
+plainCipher :: Cipher
 plainCipher = E.plainCipher
-
-getCipher :: Text -> Text -> IO (Cipher, Cipher)
-getCipher aMethod aPassword =
-  getEncDec aMethod (review utf8 aPassword)
 
 showAddressType :: AddressType -> Text
 showAddressType (IPv4_address xs) = view (from _Text) - 
diff --git a/src/Network/MoeSocks/Encrypt.hs b/src/Network/MoeSocks/Encrypt.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/MoeSocks/Encrypt.hs
@@ -0,0 +1,140 @@
+-- Heavily inspired by
+-- https://github.com/rnons/shadowsocks-haskell/blob/86bd47d474df6800e1f3706b33ae9e8f80696d8f/Shadowsocks/Encrypt.hs
+
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE LambdaCase #-}
+
+module Network.MoeSocks.Encrypt where
+
+import Control.Lens
+import Control.Monad.Except
+import Crypto.Hash.MD5 (hash)
+import Data.ByteString (ByteString)
+import Data.Map
+import Data.Monoid ((<>))
+import Data.Text (Text)
+import Data.Text.Lens
+import Data.Text.Strict.Lens (utf8)
+import OpenSSL (withOpenSSL)
+import OpenSSL.EVP.Cipher (getCipherByName, CryptoMode(..))
+import OpenSSL.Random (randBytes)
+import Prelude hiding ((-))
+import qualified Data.ByteString as S
+import qualified Data.Strict as S
+import qualified OpenSSL.EVP.Internal as E
+
+-- BEGIN backports
+
+infixr 0 -
+(-) :: (a -> b) -> a -> b
+(-) = ($)
+
+-- END backports
+
+type KeyLength = Int
+type IV_Length = Int
+
+type Cipher = S.Maybe ByteString -> IO ByteString 
+type CipherBuilder = ByteString -> IO Cipher
+type CipherBox = (Int, IO ByteString, CipherBuilder, CipherBuilder)
+
+type MaybeExceptT = ExceptT () IO
+
+methods :: Map Text (KeyLength, IV_Length)
+methods = fromList
+    [ ("aes-128-cfb", (16, 16))
+    , ("aes-192-cfb", (24, 16))
+    , ("aes-256-cfb", (32, 16))
+    , ("bf-cfb", (16, 8))
+    , ("camellia-128-cfb", (16, 16))
+    , ("camellia-192-cfb", (24, 16))
+    , ("camellia-256-cfb", (32, 16))
+    , ("cast5-cfb", (16, 8))
+    , ("des-cfb", (8, 8))
+    , ("idea-cfb", (16, 8))
+    , ("rc2-cfb", (16, 8))
+    , ("rc4", (16, 0))
+    , ("seed-cfb", (16, 16))
+    ]
+
+
+hashKey :: ByteString -> Int -> Int -> ByteString
+hashKey aPassword aKeyLen a_IV_len = loop mempty mempty 
+  where
+    _stopLength = aKeyLen + a_IV_len
+
+    loop :: ByteString -> ByteString -> ByteString
+    loop _lastHashedBytes _accumHashedBytes
+      | S.length _accumHashedBytes >= _stopLength 
+        = S.take aKeyLen _accumHashedBytes
+      | otherwise = let _new = hash - _lastHashedBytes <> aPassword
+                    in
+                    loop _new - _accumHashedBytes <> _new
+
+
+ssl :: IO a -> IO a
+ssl = withOpenSSL
+
+eitherToMaybe :: Either a b -> Maybe b
+eitherToMaybe (Left _) = Nothing
+eitherToMaybe (Right x) = Just x
+
+getMaybe :: Maybe a -> MaybeExceptT a
+getMaybe Nothing = throwError ()
+getMaybe (Just x) = pure x
+
+mio :: IO (Maybe a) -> MaybeExceptT a
+mio = (>>= getMaybe) . io
+
+io :: (MonadIO m) => IO a -> m a
+io = liftIO
+
+plainCipher :: Cipher
+plainCipher = pure . S.fromMaybe mempty
+
+initBuilder :: Text -> Text -> IO (Maybe CipherBox)
+initBuilder aMethod aPassword 
+  | aMethod == "none" = let constCipher = const - pure plainCipher
+                        in
+                        pure - Just (0, pure mempty, constCipher, constCipher)
+
+  | otherwise =
+      fmap eitherToMaybe - runExceptT - initBuilder' aMethod aPassword
+
+initBuilder' :: Text -> Text -> MaybeExceptT CipherBox
+initBuilder' aMethod aPassword = do
+  _method <- mio - ssl - getCipherByName - aMethod ^. _Text
+
+  (_keyLength, _IV_Length) <- getMaybe - methods ^? ix aMethod
+
+  let _hashed = hashKey (review utf8 aPassword) _keyLength _IV_Length
+      _IV_Maker = io - ssl - randBytes _IV_Length
+
+      _encryptBuilder :: ByteString -> IO Cipher
+      _encryptBuilder _iv = do
+          _ctx <- io - ssl - E.cipherInitBS _method _hashed _iv Encrypt
+
+          let _encrypt :: Cipher
+              _encrypt = \case
+                  S.Nothing -> E.cipherFinalBS _ctx
+                  S.Just _bytes -> do
+                    ssl - E.cipherUpdateBS _ctx _bytes
+
+          pure _encrypt
+
+      _decryptBuilder :: ByteString -> IO Cipher
+      _decryptBuilder _iv = do
+          _ctx <- io - ssl - E.cipherInitBS _method _hashed _iv Decrypt
+
+          let _decrypt :: Cipher
+              _decrypt = \case
+                  S.Nothing -> E.cipherFinalBS _ctx
+                  S.Just _bytes -> do
+                    ssl - E.cipherUpdateBS _ctx _bytes 
+          
+          pure _decrypt
+          
+
+  pure - (_IV_Length, _IV_Maker, _encryptBuilder, _decryptBuilder)
+
diff --git a/src/Network/MoeSocks/Helper.hs b/src/Network/MoeSocks/Helper.hs
--- a/src/Network/MoeSocks/Helper.hs
+++ b/src/Network/MoeSocks/Helper.hs
@@ -254,16 +254,19 @@
 send_ :: Socket -> ByteString -> IO ()
 send_ = sendAll
 
+
+sendBytes :: HQueue -> ByteString -> IO ()
+sendBytes _queue = atomically . writeTBQueue _queue . S.Just
+
+sendBytesEncrypt :: HQueue -> HCipher -> ByteString -> IO ()
+sendBytesEncrypt _queue _cipher x = sendBytes _queue =<< _cipher (S.Just x)
+
 sendBuilder :: HQueue -> B.Builder -> IO ()
-sendBuilder _queue = 
-  atomically . writeTBQueue _queue . S.Just . builder_To_ByteString
+sendBuilder _queue = sendBytes _queue . builder_To_ByteString
 
-sendBuilderEncrypted ::  HQueue -> 
-                          HCipher -> 
-                          B.Builder -> IO ()
-sendBuilderEncrypted _queue _encrypt x = 
-  atomically . writeTBQueue _queue . S.Just =<< 
-                                      _encrypt (S.Just - builder_To_ByteString x)
+sendBuilderEncrypt :: HQueue -> HCipher -> B.Builder -> IO ()
+sendBuilderEncrypt _queue _encrypt = 
+  sendBytesEncrypt _queue _encrypt . builder_To_ByteString
 
 -- | An exception raised when parsing fails.
 data ParseException = ParseException String
diff --git a/src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs b/src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs
deleted file mode 100644
--- a/src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs
+++ /dev/null
@@ -1,166 +0,0 @@
-{- Original file from the shadowsocks package hosted on Hackage:
- - https://hackage.haskell.org/package/shadowsocks
- - Copyright: rnons
- - Licence: MIT
- - Heavily modified here
- -}
-
-
-{- 
-The MIT License (MIT)
-
-Copyright (c) 2014 rnons
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
--}
-
-
-
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE LambdaCase #-}
-
-module Network.MoeSocks.Internal.ShadowSocks.Encrypt
-  ( getEncDec
-  , iv_len
-  , plainCipher
-  ) where
-
-import           Control.Concurrent.MVar ( newEmptyMVar, isEmptyMVar
-                                         , putMVar, readMVar)
-import           Crypto.Hash.MD5 (hash)
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.HashMap.Strict as HM
-import           Data.Maybe (fromJust)
-import           Data.Monoid ((<>))
-import           OpenSSL (withOpenSSL)
-import           OpenSSL.EVP.Cipher (getCipherByName, CryptoMode(..))
-import           OpenSSL.EVP.Internal (cipherInitBS, cipherUpdateBS,
-                                        cipherFinalBS)
-import           OpenSSL.Random (randBytes)
-import           Data.Text (Text)
-import           Control.Lens
-import           Data.Text.Lens
-import qualified Data.Strict as S
-
-
-method_supported :: HM.HashMap Text (Int, Int)
-method_supported = HM.fromList
-    [ ("aes-128-cfb", (16, 16))
-    , ("aes-192-cfb", (24, 16))
-    , ("aes-256-cfb", (32, 16))
-    , ("bf-cfb", (16, 8))
-    , ("camellia-128-cfb", (16, 16))
-    , ("camellia-192-cfb", (24, 16))
-    , ("camellia-256-cfb", (32, 16))
-    , ("cast5-cfb", (16, 8))
-    , ("des-cfb", (8, 8))
-    , ("idea-cfb", (16, 8))
-    , ("rc2-cfb", (16, 8))
-    , ("rc4", (16, 0))
-    , ("seed-cfb", (16, 16))
-    ]
-
-iv_len :: Text -> Int
-iv_len method = m1
-  where
-    (_, m1) = method_supported HM.! method
-
-evpBytesToKey :: ByteString -> Int -> Int -> (ByteString, ByteString)
-evpBytesToKey password keyLen ivLen =
-    let ms' = S.concat $ ms 0 []
-        key = S.take keyLen ms'
-        iv  = S.take ivLen $ S.drop keyLen ms'
-     in (key, iv)
-  where
-    ms :: Int -> [ByteString] -> [ByteString]
-    ms 0 _ = ms 1 [hash password]
-    ms i m
-        | S.length (S.concat m) < keyLen + ivLen =
-            ms (i+1) (m ++ [hash (last m <> password)])
-        | otherwise = m
-
-getSSLEncDec :: Text -> ByteString
-             -> IO (S.Maybe ByteString -> IO ByteString
-                    , S.Maybe ByteString -> IO ByteString)
-getSSLEncDec method password = do
-    let (m0, m1) = fromJust $ HM.lookup method method_supported
-    random_iv <- withOpenSSL $ randBytes 32
-    let cipher_iv = S.take m1 random_iv
-    let (key, _) = evpBytesToKey password m0 m1
-    cipherCtx <- newEmptyMVar
-    decipherCtx <- newEmptyMVar
-
-    cipherMethod <- fmap fromJust $ withOpenSSL $ getCipherByName $ 
-                                        method ^. _Text
-    ctx <- withOpenSSL $ cipherInitBS cipherMethod key cipher_iv Encrypt
-    let
-        encrypt :: (S.Maybe ByteString) -> IO ByteString
-        encrypt = \case
-          S.Nothing -> cipherFinalBS ctx
-          S.Just buf -> do
-            if S.null buf
-              then return $! mempty
-              else do
-                empty <- isEmptyMVar cipherCtx
-                if empty
-                    then do
-                        putMVar cipherCtx $! ()
-                        ciphered <- withOpenSSL $ cipherUpdateBS ctx buf
-                        return $! cipher_iv <> ciphered
-                    else do
-                        r <- withOpenSSL $ cipherUpdateBS ctx buf
-                        return $! r
-
-        decrypt :: (S.Maybe ByteString) -> IO ByteString
-        decrypt = \case
-          S.Nothing -> cipherFinalBS ctx
-          S.Just buf -> do 
-            if S.null buf
-              then return $! S.empty
-              else do
-                empty <- isEmptyMVar decipherCtx
-                if empty
-                    then do
-                        let decipher_iv = S.take m1 buf
-                        dctx <- withOpenSSL $ 
-                                cipherInitBS cipherMethod key decipher_iv Decrypt
-                        putMVar decipherCtx $! dctx
-                        if S.null (S.drop m1 buf)
-                            then return ""
-                            else do
-                                r <- withOpenSSL $
-                                        cipherUpdateBS dctx (S.drop m1 buf)
-                                return $! r
-                    else do
-                        dctx <- readMVar decipherCtx
-                        r <- withOpenSSL $ cipherUpdateBS dctx buf
-                        return $! r
-
-    return (encrypt, decrypt)
-
-plainCipher :: (S.Maybe ByteString -> IO ByteString)
-plainCipher = pure . S.fromMaybe mempty
-
-getEncDec :: Text -> ByteString  
-          -> IO (S.Maybe ByteString -> IO ByteString
-                , S.Maybe ByteString -> IO ByteString)
-getEncDec t
-  | t == "none" = const $ pure (plainCipher, plainCipher)
-  | otherwise = getSSLEncDec t
diff --git a/src/Network/MoeSocks/TCP.hs b/src/Network/MoeSocks/TCP.hs
--- a/src/Network/MoeSocks/TCP.hs
+++ b/src/Network/MoeSocks/TCP.hs
@@ -14,12 +14,16 @@
 import Network.MoeSocks.Helper
 import Network.MoeSocks.Type
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
+import Network.Socket.ByteString (recv)
 import Prelude hiding ((-), take)
 import qualified Data.Strict as S
 
-local_Socks5_RequestHandler :: MoeConfig -> ByteString -> (Socket, SockAddr) 
-                                                                    -> IO ()
-local_Socks5_RequestHandler aConfig _ (aSocket,_) = do
+local_Socks5_RequestHandler :: CipherBox 
+                            -> MoeConfig 
+                            -> ByteString 
+                            -> (Socket, SockAddr) 
+                            -> IO ()
+local_Socks5_RequestHandler aCipherBox aConfig _ (aSocket,_) = do
   (_partialBytesAfterGreeting, _r) <- 
       parseSocket "clientGreeting" mempty plainCipher
         greetingParser aSocket
@@ -37,26 +41,34 @@
                                 connectionParser
                                 aSocket
 
-  local_TCP_RequestHandler aConfig _parsedRequest True aSocket
+  local_TCP_RequestHandler aCipherBox aConfig _parsedRequest True aSocket
 
 
 
-local_TCP_ForwardRequestHandler :: MoeConfig -> Forward -> 
-                                  ByteString -> (Socket, SockAddr) -> IO ()
-local_TCP_ForwardRequestHandler aConfig aForwarding _ (aSocket,_) = do
+local_TCP_ForwardRequestHandler :: CipherBox 
+                                -> MoeConfig 
+                                -> Forward 
+                                -> ByteString 
+                                -> (Socket, SockAddr) 
+                                -> IO ()
+local_TCP_ForwardRequestHandler aCipherBox aConfig aForwarding _ (aSocket,_) = do
   let _clientRequest = ClientRequest
                           TCP_IP_stream_connection
                           (Domain_name - aForwarding ^. 
                             forwardRemoteHost)
                           (aForwarding ^. forwardRemotePort)
               
-  local_TCP_RequestHandler aConfig (mempty, _clientRequest) False aSocket
+  local_TCP_RequestHandler aCipherBox aConfig (mempty, _clientRequest) False aSocket
 
 
 
-local_TCP_RequestHandler :: MoeConfig -> (ByteString, ClientRequest) -> 
-                        Bool -> Socket -> IO ()
-local_TCP_RequestHandler aConfig 
+local_TCP_RequestHandler :: CipherBox 
+                          -> MoeConfig 
+                          -> (ByteString, ClientRequest) 
+                          -> Bool 
+                          -> Socket 
+                          -> IO ()
+local_TCP_RequestHandler aCipherBox aConfig 
                         (_partialBytesAfterClientRequest, _clientRequest) 
                         shouldReplyClient aSocket = do
   let 
@@ -84,11 +96,9 @@
     _log - "L T: " <> _msg
 
     let handleLocal __remoteSocket = do
-          (_encrypt, _decrypt) <- getCipher
-                                    (aConfig ^. method)
-                                    (aConfig ^. password)
-
-
+          _encodeIV <- aCipherBox ^. generateIV 
+          _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV
+          
           let 
               _header = shadowSocksRequestBuilder _clientRequest
           
@@ -103,13 +113,12 @@
                   else Nothing
 
           let sendThread = do
-                sendBuilderEncrypted 
-                  sendChannel _encrypt _header
+                sendBytes sendChannel _encodeIV
+                sendBuilderEncrypt sendChannel _encrypt _header
 
                 when (_partialBytesAfterClientRequest & isn't _Empty) -
-                  atomically . writeTBQueue sendChannel . S.Just =<< 
-                    _encrypt (S.Just _partialBytesAfterClientRequest)
-
+                  sendBytesEncrypt sendChannel _encrypt 
+                    _partialBytesAfterClientRequest
 
                 let _produce = do
                                   produceLoop (_logId "L --> + Loop")
@@ -133,6 +142,9 @@
                   pure ()
 
           let receiveThread = do
+                _decodeIV <- recv __remoteSocket (aCipherBox ^. ivLength)
+                _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV
+
                 let _produce = produceLoop (_logId "L <-- + Loop")
                                   _timeout
                                   _NoThrottle
@@ -161,12 +173,11 @@
     handleLocal _remoteSocket
 
 
-remote_TCP_RequestHandler:: MoeConfig -> Socket -> IO ()
-remote_TCP_RequestHandler aConfig aSocket = do
-  (_encrypt, _decrypt) <- getCipher
-                            (aConfig ^. method)
-                            (aConfig ^. password)
-  
+remote_TCP_RequestHandler :: CipherBox -> MoeConfig -> Socket -> IO ()
+remote_TCP_RequestHandler aCipherBox aConfig aSocket = do
+  _decodeIV <- recv aSocket (aCipherBox ^. ivLength)
+  _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV
+
   (_leftOverBytes, _clientRequest) <- parseSocket 
                                           "clientRequest"
                                           mempty
@@ -229,6 +240,10 @@
                   pure ()
 
           let receiveThread = do
+                _encodeIV <- aCipherBox ^. generateIV 
+                _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV
+                sendBytes receiveChannel _encodeIV
+
                 let _produce = do
                                   produceLoop (_logId "R <-- + Loop")
                                     _timeout
diff --git a/src/Network/MoeSocks/Type.hs b/src/Network/MoeSocks/Type.hs
--- a/src/Network/MoeSocks/Type.hs
+++ b/src/Network/MoeSocks/Type.hs
@@ -99,16 +99,30 @@
 
 makeLenses ''MoeOptions
 
+type Cipher = S.Maybe ByteString -> IO ByteString 
+type CipherBuilder = ByteString -> IO Cipher
+
+data CipherBox = CipherBox
+  {
+    _ivLength :: Int
+  , _generateIV :: IO ByteString
+  , _encryptBuilder :: CipherBuilder
+  , _decryptBuilder ::  CipherBuilder
+  }
+
+makeLenses '' CipherBox
+
 data Env = Env
   {
     _options :: MoeOptions
   , _config :: MoeConfig
+  , _cipherBox :: CipherBox
   }
-  deriving (Show, Eq)
 
 makeLenses ''Env
 
-type Cipher = S.Maybe ByteString -> IO ByteString 
-type Queue = TBQueue (Maybe ByteString) 
 
+
+type Queue = TBQueue (Maybe ByteString) 
 type MoeMonadT = ReaderT MoeOptions (ExceptT String IO)
+
diff --git a/src/Network/MoeSocks/UDP.hs b/src/Network/MoeSocks/UDP.hs
--- a/src/Network/MoeSocks/UDP.hs
+++ b/src/Network/MoeSocks/UDP.hs
@@ -8,6 +8,7 @@
 import Control.Monad.Writer hiding (listen)
 import Data.Attoparsec.ByteString
 import Data.ByteString (ByteString)
+import qualified Data.ByteString as S
 import Network.MoeSocks.BuilderAndParser
 import Network.MoeSocks.Common
 import Network.MoeSocks.Helper
@@ -36,9 +37,13 @@
 processAll f x = 
   (<>) <$> f (S.Just x) <*> f S.Nothing
 
-local_UDP_ForwardRequestHandler :: MoeConfig -> Forward -> 
-                                  ByteString -> (Socket,SockAddr) -> IO ()
-local_UDP_ForwardRequestHandler aConfig aForwarding aMessage 
+local_UDP_ForwardRequestHandler :: CipherBox 
+                                -> MoeConfig 
+                                -> Forward 
+                                -> ByteString 
+                                -> (Socket,SockAddr) 
+                                -> IO ()
+local_UDP_ForwardRequestHandler aCipherBox aConfig aForwarding aMessage 
                                                     (aSocket, aSockAddr) = do
 
   let _c = aConfig
@@ -57,9 +62,8 @@
     \(_remoteSocket, _remoteAddr) -> do
       connect _remoteSocket _remoteAddr
 
-      (_encrypt, _decrypt) <- getCipher
-                                (aConfig ^. method)
-                                (aConfig ^. password)
+      _encodeIV <- aCipherBox ^. generateIV 
+      _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV
 
       {-let (_encrypt, _decrypt) = (pure, pure)-}
 
@@ -70,27 +74,34 @@
       let _msg = show aSockAddr <> " -> " <> showRequest _clientRequest
       _log - "L U: " <> _msg
       
-      send_ _remoteSocket =<< _encrypt (S.Just _bytes)
+      _eMsg <- _encrypt (S.Just _bytes)
 
-      (_r, _) <- recv_ _remoteSocket >>= processAll _decrypt 
+      send_ _remoteSocket - _encodeIV <> _eMsg
+
+      _response <- recv_ _remoteSocket 
+
+      let (_decodeIV, _responseMsg) = S.splitAt (aCipherBox ^. ivLength) 
+                                        _response
+      _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV
+      
+      (_r, _) <- processAll _decrypt _responseMsg
                                       >>= parseShadowSocksRequest
 
-      {-puts - "L UDP <--: " <> show _r-}
       when (_r & isn't _Empty) - do
         sendAllTo aSocket _r aSockAddr
 
 
-remote_UDP_RequestHandler:: MoeConfig -> ByteString -> (Socket, SockAddr) 
-                                                                      -> IO ()
-remote_UDP_RequestHandler aConfig aMessage (aSocket, aSockAddr) = do
-  (_encrypt, _decrypt) <- getCipher
-                            (aConfig ^. method)
-                            (aConfig ^. password)
-  
+remote_UDP_RequestHandler :: CipherBox 
+                          -> MoeConfig 
+                          -> ByteString 
+                          -> (Socket, SockAddr) 
+                          -> IO ()
+remote_UDP_RequestHandler aCipherBox _ aMessage (aSocket, aSockAddr) = do
+  let (_decodeIV, _eMsg) = S.splitAt (aCipherBox ^. ivLength) 
+                                       aMessage 
 
-  {-let (_encrypt, _decrypt) = (pure, pure)-}
-  
-  _msg <- processAll _decrypt aMessage
+  _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV
+  _msg <- processAll _decrypt _eMsg
 
   (_decryptedMessage, _clientRequest) <- parseShadowSocksRequest _msg
   
@@ -114,5 +125,8 @@
     {-puts - "R UDP <--: " <> show _r-}
 
     when (_r & isn't _Empty) - do
+      _encodeIV <- aCipherBox ^. generateIV 
+      _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV
+      
       _encryptedMessage <- processAll _encrypt _r
-      sendAllTo aSocket _encryptedMessage aSockAddr
+      sendAllTo aSocket (_encodeIV <> _encryptedMessage) aSockAddr
