signature (empty) → 0.1.0.0
raw patch · 3 files changed
+139/−0 lines, 3 filesdep +aesondep +basedep +byteable
Dependencies added: aeson, base, byteable, bytestring, case-insensitive, cryptohash, hexstring, scientific, text, unordered-containers, vector
Files
- LICENSE +30/−0
- signature.cabal +34/−0
- src/Crypto/Signature.hs +75/−0
+ LICENSE view
@@ -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.
+ signature.cabal view
@@ -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
+ src/Crypto/Signature.hs view
@@ -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]