module Network.WindowsLive.Secret
    ( Secret
    , Key
    , new
    , encryptionKey
    , signingKey
    )
where

import Codec.Utils ( Octet )
import Codec.Text.Raw ( hexdump )
import Text.PrettyPrint.HughesPJ ( text, (<+>), char )
import Control.Monad.Error ( MonadError )
import qualified Data.Digest.SHA256 as SHA256

type Key = [Octet]

newtype Secret = Secret [Octet]

instance Show Secret where
    showsPrec _ (Secret bs) =
        shows $ text "Secret<" <+> hexdump 24 bs <+> char '>'

new :: MonadError e m => String -> m Secret
new s = if null s
        then fail "Empty secret"
        else return $ Secret $ map (toEnum . fromEnum) s

data KeyType = Signature | Encryption deriving Show

keyPrefix :: KeyType -> Key
keyPrefix kt = map (toEnum . fromEnum) $
               case kt of
                 Signature -> "SIGNATURE"
                 Encryption -> "ENCRYPTION"

-- |Generate a cryptographic key from the secret and the key type
key :: Secret -> KeyType -> Key
key (Secret bytes) kt = take 16 $ SHA256.hash $ keyPrefix kt ++ bytes

encryptionKey :: Secret -> Key
encryptionKey = flip key Encryption

signingKey :: Secret -> Key
signingKey = flip key Signature