diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Li Meng Jun (c) 2017
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * 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.
+
+    * Neither the name of Li Meng Jun nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+OWNER 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.
diff --git a/signature.cabal b/signature.cabal
new file mode 100644
--- /dev/null
+++ b/signature.cabal
@@ -0,0 +1,34 @@
+name:                signature
+version:             0.1.0.0
+synopsis:            Hmac sha256 signature json and http payload
+description:         Hmac sha256 signature json and http payload.
+homepage:            https://github.com/Lupino/yuntan-common/tree/master/signature#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Li Meng Jun
+maintainer:          lmjubuntu@gmail.com
+copyright:           MIT
+category:            value
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Crypto.Signature
+  build-depends:       base >= 4.7 && < 5
+                     , byteable
+                     , bytestring
+                     , vector
+                     , aeson
+                     , unordered-containers
+                     , text
+                     , scientific
+                     , cryptohash
+                     , case-insensitive
+                     , hexstring
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/Lupino/yuntan-common
diff --git a/src/Crypto/Signature.hs b/src/Crypto/Signature.hs
new file mode 100644
--- /dev/null
+++ b/src/Crypto/Signature.hs
@@ -0,0 +1,75 @@
+module Crypto.Signature
+  ( signParams
+  , signJSON
+  , hmacSHA256
+  , signRaw
+  ) where
+
+import           Crypto.Hash           (SHA256)
+import           Crypto.MAC            (HMAC (..), hmac)
+import           Data.Aeson            (Value (..))
+import           Data.Byteable         (toBytes)
+import qualified Data.ByteString.Char8 as B (ByteString, concat, empty, pack,
+                                             unpack)
+import           Data.CaseInsensitive  (CI, mk)
+import qualified Data.HashMap.Lazy     as LH (HashMap, toList)
+import           Data.HexString        (fromBytes, toText)
+import           Data.List             (sortOn)
+import           Data.Scientific       (Scientific, floatingOrInteger)
+import qualified Data.Text             as T (Text, unpack)
+import           Data.Text.Encoding    (encodeUtf8)
+import qualified Data.Text.Lazy        as LT (Text, toStrict, unpack)
+import qualified Data.Vector           as V (Vector, toList)
+
+hex :: B.ByteString -> CI B.ByteString
+hex = mk . encodeUtf8 . toText . fromBytes
+
+hmacSHA256 :: B.ByteString -> B.ByteString -> CI B.ByteString
+hmacSHA256 solt = hex . h2b . hmac solt
+
+h2b :: HMAC SHA256 -> B.ByteString
+h2b = toBytes . hmacGetDigest
+
+signParams :: B.ByteString -> [(LT.Text, LT.Text)] -> CI B.ByteString
+signParams solt = hmacSHA256 solt . join . sort
+  where sort :: [(LT.Text, LT.Text)] -> [(LT.Text, LT.Text)]
+        sort = sortOn (\(k, _) -> LT.unpack k)
+
+        join :: [(LT.Text, LT.Text)] -> B.ByteString
+        join ((k,v):xs) = B.concat [encodeUtf8 $ LT.toStrict k, encodeUtf8 $ LT.toStrict v, join xs]
+        join []         = B.empty
+
+signJSON :: B.ByteString -> Value -> CI B.ByteString
+signJSON solt = hmacSHA256 solt . v2b
+  where sortHashMap :: LH.HashMap T.Text Value -> [(T.Text, Value)]
+        sortHashMap = sortOn (\(k, _) -> T.unpack k) . LH.toList
+
+        joinList :: [(T.Text, Value)] -> B.ByteString
+        joinList []          = B.empty
+        joinList ((k, v):xs) = B.concat [encodeUtf8 k, v2b v, joinList xs]
+
+        joinArray :: V.Vector Value -> B.ByteString
+        joinArray = B.concat . map v2b . V.toList
+
+        v2b :: Value -> B.ByteString
+        v2b (Object v)   = (joinList . sortHashMap) v
+        v2b (Array v)    = joinArray v
+        v2b (String v)   = encodeUtf8 v
+        v2b (Number v)   = B.pack $ showNumber v
+        v2b (Bool True)  = B.pack "true"
+        v2b (Bool False) = B.pack "false"
+        v2b Null         = B.empty
+
+        showNumber :: Scientific -> String
+        showNumber v = case floatingOrInteger v of
+                         Left n  -> show n
+                         Right n -> show n
+
+signRaw :: B.ByteString -> [(B.ByteString, B.ByteString)] -> CI B.ByteString
+signRaw solt = hmacSHA256 solt . join . sort
+  where sort :: [(B.ByteString, B.ByteString)] -> [(B.ByteString, B.ByteString)]
+        sort = sortOn (\(k, _) -> B.unpack k)
+
+        join :: [(B.ByteString, B.ByteString)] -> B.ByteString
+        join []         = B.empty
+        join ((k,v):xs) = B.concat [k, v, join xs]
