feat(storage-key): postStorageKeyR
This commit is contained in:
parent
fed81fdbce
commit
059efe5085
@ -4,16 +4,18 @@ module Handler.StorageKey
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
-- import qualified Data.Binary as Binary
|
import Crypto.Hash
|
||||||
|
|
||||||
|
import qualified Data.Aeson as Aeson
|
||||||
|
import qualified Data.ByteString.Base64 as Base64 (encode, decodeLenient)
|
||||||
|
import qualified Data.Binary as Binary (encode)
|
||||||
|
import qualified Crypto.KDF.HKDF as HKDF
|
||||||
|
|
||||||
|
|
||||||
data StorageKeyType
|
data StorageKeyType
|
||||||
= SKTExamCorrect ExamId
|
= SKTExamCorrect ExamId
|
||||||
-- { sktExamCorrectExamId :: ExamId
|
|
||||||
-- }
|
|
||||||
deriveJSON defaultOptions
|
deriveJSON defaultOptions
|
||||||
{ fieldLabelModifier = camelToPathPiece' 3
|
{ constructorTagModifier = camelToPathPiece' 3
|
||||||
, constructorTagModifier = camelToPathPiece' 3
|
|
||||||
} ''StorageKeyType
|
} ''StorageKeyType
|
||||||
|
|
||||||
data StorageKeyRequest
|
data StorageKeyRequest
|
||||||
@ -29,7 +31,9 @@ deriveJSON defaultOptions
|
|||||||
|
|
||||||
data StorageKeyResponse
|
data StorageKeyResponse
|
||||||
= StorageKeyResponse
|
= StorageKeyResponse
|
||||||
{ skResKey :: Text
|
{ skResKey :: Text
|
||||||
|
, skResTimestamp :: UTCTime
|
||||||
|
, skResSalt :: Text
|
||||||
}
|
}
|
||||||
deriveJSON defaultOptions
|
deriveJSON defaultOptions
|
||||||
{ fieldLabelModifier = camelToPathPiece' 2
|
{ fieldLabelModifier = camelToPathPiece' 2
|
||||||
@ -39,8 +43,35 @@ deriveJSON defaultOptions
|
|||||||
|
|
||||||
postStorageKeyR :: Handler Value
|
postStorageKeyR :: Handler Value
|
||||||
postStorageKeyR = do
|
postStorageKeyR = do
|
||||||
|
uid <- requireAuthId
|
||||||
|
sbKey <- secretBoxKey
|
||||||
|
|
||||||
StorageKeyRequest{..} <- requireCheckJsonBody
|
StorageKeyRequest{..} <- requireCheckJsonBody
|
||||||
|
|
||||||
let key = "TODO"
|
now <- liftIO getCurrentTime
|
||||||
|
|
||||||
sendResponseStatus ok200 $ toJSON StorageKeyResponse{ skResKey = key }
|
let
|
||||||
|
(lBound,rBound) = case skReqType of
|
||||||
|
SKTExamCorrect _ -> (-30*nominalDay, nominalDay)
|
||||||
|
|
||||||
|
timestampInBounds = maybe False (\ts -> addUTCTime lBound now < ts && addUTCTime rBound now > ts) skReqTimestamp
|
||||||
|
|
||||||
|
timestamp = if
|
||||||
|
| Just ts <- skReqTimestamp, timestampInBounds -> ts
|
||||||
|
| otherwise -> now
|
||||||
|
|
||||||
|
salt <- let sltSize = hashDigestSize SHA3_256 in if
|
||||||
|
| Just slt <- Base64.decodeLenient . encodeUtf8 <$> skReqSalt
|
||||||
|
, timestampInBounds
|
||||||
|
, length slt == sltSize -> return slt
|
||||||
|
| otherwise -> pack . take sltSize <$> liftIO getRandoms
|
||||||
|
|
||||||
|
let
|
||||||
|
ikm = (toStrict . Aeson.encode) (skReqType, uid, sbKey)
|
||||||
|
key = HKDF.expand (HKDF.extract salt ikm :: HKDF.PRK SHA3_256) (toStrict $ Binary.encode (timestamp,skReqLength)) skReqLength
|
||||||
|
|
||||||
|
sendResponseStatus ok200 $ toJSON StorageKeyResponse
|
||||||
|
{ skResKey = (decodeUtf8 . Base64.encode) key
|
||||||
|
, skResTimestamp = timestamp
|
||||||
|
, skResSalt = (decodeUtf8 . Base64.encode) salt
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user