{-# LANGUAGE TupleSections #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Network.S3.Sign ( sign ) where import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Base64 as Base64 import Data.ByteString.UTF8 (ByteString) import Blaze.ByteString.Builder (toByteString, fromByteString) import Data.Monoid ((<>)) import Data.Time.Clock (UTCTime) import Data.Time.Format (formatTime, defaultTimeLocale) import Network.S3.Types (S3Request(..), S3SignedRequest(..)) import Network.S3.URL (canonicalRequest) import Data.Byteable (toBytes) import Crypto.Hash reqString :: S3Request -> Digest SHA256 reqString = hash . toByteString . canonicalRequest hmacSHA256 :: ByteString -> ByteString -> HMAC SHA256 hmacSHA256 key = hmac key hmac_ :: ByteString -> ByteString -> ByteString hmac_ key = toBytes . hmacGetDigest . hmacSHA256 key -- | SHA1 Encrypted Signature sign :: ByteString -> S3Request -> UTCTime -> S3SignedRequest sign key req utc = let seconds = BS.pack (formatTime defaultTimeLocale "T%M%H%SZ" utc) date = BS.pack (formatTime defaultTimeLocale "%Y%m%d" utc) timestamp = fromByteString (date <> seconds) reqHash = fromByteString (digestToHexByteString (reqString req)) region = regionName req service = "s3" dateKey = hmac_ ("AWS4" <> key) date dateRegionKey = hmac_ dateKey region dateRegionServiceKey = hmac_ dateRegionKey service signingKey = hmac_ dateRegionServiceKey "aws4_request" scope = fromByteString date <> fromByteString "/" <> fromByteString region <> fromByteString "/" <> fromByteString service <> fromByteString "/aws4_request" algorithm = "AWS4-HMAC-SHA256" signingStringBuilder = algorithm <> "\n" <> timestamp <> "\n" <> scope <> "\n" <> reqHash stringToSign = toByteString signingStringBuilder signature = hmacSHA256 signingKey stringToSign hexSignature = digestToHexByteString (hmacGetDigest signature) in S3SignedRequest { sigHeaders = s3headers req , sigDate = toByteString timestamp , sigCredential = toByteString scope , sigPolicy = Base64.encode stringToSign , sigSignature = hexSignature , sigAlgorithm = toByteString algorithm }