--   This Source Code Form is subject to the terms of the Mozilla Public
--   License, v. 2.0. If a copy of the MPL was not distributed with this
--   file, You can obtain one at http://mozilla.org/MPL/2.0/.

{-# OPTIONS_HADDOCK show-extensions #-}

{-# LANGUAGE DerivingStrategies #-}

-- | Keys used for signing and validation
module Libjwt.Keys
  ( Secret(..)
  , RsaKeyPair(..)
  , EcKeyPair(..)
  )
where

import           Data.ByteString                ( ByteString )

import qualified Data.ByteString.UTF8          as UTF8

import           Data.String

-- | Secret used in /HMAC/ algorithms.
-- 
--   According to RFC:
--   /A key of the same size as the hash output (for instance, 256 bits for 'HS256') or larger MUST be used (...)/ 
--   - the user must ensure this property holds.
--
--   A secret is just an octet sequence e.g.
--
-- @
-- hs512 =
--  HS512
--    "MjZkMDY2OWFiZmRjYTk5YjczZWFiZjYzMmRjMzU5NDYyMjMxODBjMTg3ZmY5OTZjM2NhM2NhN2Mx\\
--    \\YzFiNDNlYjc4NTE1MjQxZGI0OWM1ZWI2ZDUyZmMzZDlhMmFiNjc5OWJlZTUxNjE2ZDRlYTNkYjU5\\
--    \\Y2IwMDZhYWY1MjY1OTQgIC0K"
-- @
newtype Secret = MkSecret { Secret -> ByteString
reveal :: ByteString }
  deriving stock (Int -> Secret -> ShowS
[Secret] -> ShowS
Secret -> String
(Int -> Secret -> ShowS)
-> (Secret -> String) -> ([Secret] -> ShowS) -> Show Secret
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Secret] -> ShowS
$cshowList :: [Secret] -> ShowS
show :: Secret -> String
$cshow :: Secret -> String
showsPrec :: Int -> Secret -> ShowS
$cshowsPrec :: Int -> Secret -> ShowS
Show, Secret -> Secret -> Bool
(Secret -> Secret -> Bool)
-> (Secret -> Secret -> Bool) -> Eq Secret
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Secret -> Secret -> Bool
$c/= :: Secret -> Secret -> Bool
== :: Secret -> Secret -> Bool
$c== :: Secret -> Secret -> Bool
Eq)

instance IsString Secret where
  fromString :: String -> Secret
fromString = ByteString -> Secret
MkSecret (ByteString -> Secret)
-> (String -> ByteString) -> String -> Secret
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
UTF8.fromString

-- | RSA key-pair used in /RSA/ algorithms
--
--   According to RFC:
--   /A key of size 2048 bits or larger MUST be used with these algorithms./ 
--   - the user must ensure this property holds.
--
--   Both fields are assumed to be strings representing /PEM-encoded/ keys
--
-- >
-- >rsa2048KeyPair =
-- >  let private = C8.pack $ unlines
-- >        [ "-----BEGIN RSA PRIVATE KEY-----"
-- >        , "MIIEpgIBAAKCAQEAwCXp2P+qboao0tjUyU+D3YI+sgBn8dkGaxOvPFLBFQMNkhbL"
-- >        , "0HEoRKNnQCubZNc0jXnMK5hCeGRnDS7lYclROXocRWUn5s2W3jP5xn7lM4otIpuE"
-- >        , "3FStthMCrPSEQiBCXE4cyKiHaZqmbqXlHAHVEuGMM7oddiB6s3zjwf2h1v0SEiHf"
-- >        , "5ZFzTVarStablqh6wVDAiYyM+8aUM0x9p3JcaWW+eDk/UU3jCfCke7R3t2rbD1ZC"
-- >        , "j1cO08Uir3Lhf65TfU+iIrgLU3umV4B3gRcpd8iz0ZTLaG8Qnm0GsPQjR3PTZYEC"
-- >        , "xEnFaRgXcQLHYYMAW9YaX6T3rlTGZAaP5YboxQIDAQABAoIBAQCg/OMBsauc8Ovv"
-- >        , "xEX76MglxeM7hgWQ5vFus05lrzwgm686EClxme1QHMv8QszuXzSjuEFs4SQH9K82"
-- >        , "p2z+UgrgqkOXjNoykVvvDgMe4OCuHv4T+dMGO1hTrXfXawKI2Lhg1/1bzX+u5ii9"
-- >        , "mfbsUUixihHKoQvgFfRX/7JfrV50XZ3diwzd8DoEaIgeAIdyhLhVuh2W7wXbOF+l"
-- >        , "aZW7gqCVzTBhC04E/D6eqFqvnkQyHzZPgaaDi4oL7gP8nGpcswlqKSLO5eVkkEHY"
-- >        , "C88nAwU4Q/+qcAf09ijmTLlo07xLrLC0cOf2yQTwLj6ZffzTJ7NSMaPrTdEXThsW"
-- >        , "wAeB/GcBAoGBAOzLST9/zakFGBTkwiLqgNVgEBUoYjB0Z+Fpx4qBLzKZNQP1yNup"
-- >        , "LhC/4pIVQM+ZjOS0Wx7Sh0FTLHFb018quPiAPsKMEC2CW5v7vKwC4zW72/v5UrIw"
-- >        , "pcBzl67nsc53r5Lblol9PU4oCjDzuFMjMbg+EzD3kVp/gxC9bRMwK3zBAoGBAM+7"
-- >        , "nOV80uteB1ZXazccj6g0ANd2AyJY6gHfxD1CopvRReYm36wmG00HQ3jHZPUcsLQp"
-- >        , "dWvWplRFprZlce0jl7HcB/8g5wUkErMop3KK5cA886HxsATNSl6rYghZGALqxm/a"
-- >        , "+v2AKoZThns8QRYL5bsBD4kTQLEIwp7j6sNbBrkFAoGBAL6fL8o0gkUsWqSHO1mM"
-- >        , "WkZrXMcLiW/kZbPqyb3QHUSoXStg818RpInLTwO2pEP7IpcCMdBwPn3yDPb8qv4T"
-- >        , "kHBMHTnUMznPlRvO3aXDdVFOd9sybMYRr31sEJG250aExwx8RYVNEssWJI4fxST4"
-- >        , "UhA1uJFU2uh1efdB5srpnjiBAoGBALTDCPAZAmCVXcUgJMe8LrWrKuBSbL/Cpz4i"
-- >        , "PV0hUuZL4Is5YIEoV7FblLbQq2UvJgRf3zGLgwjp4vvsooo74pB+auby9pReo3cK"
-- >        , "9UqS2wHBCC/vY7+J9CEU+SVSgbZoHWzQHH/iux5QKEGsWOaaS7nCXoZlHnHusYwZ"
-- >        , "v/tmhh8RAoGBAIi3Lbup0AVwougANLXwMLCfT8HxI8Hozdr+Pe0ibTnjfY+BPuy1"
-- >        , "vSgozXao68TwW3u58PcdvfBnfg/7XCK6TXtij48JDu6qw0IiSRxOZ5Ed/GW2P031"
-- >        , "7TfwnjBohjM2O6NRne8qe6Qv5xLagoVKQfa1WhQEFU2bTNLYA/2kv266"
-- >        , "-----END RSA PRIVATE KEY-----"
-- >        ]
-- >      public = C8.pack $ unlines
-- >        [ "-----BEGIN PUBLIC KEY-----"
-- >        , "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwCXp2P+qboao0tjUyU+D"
-- >        , "3YI+sgBn8dkGaxOvPFLBFQMNkhbL0HEoRKNnQCubZNc0jXnMK5hCeGRnDS7lYclR"
-- >        , "OXocRWUn5s2W3jP5xn7lM4otIpuE3FStthMCrPSEQiBCXE4cyKiHaZqmbqXlHAHV"
-- >        , "EuGMM7oddiB6s3zjwf2h1v0SEiHf5ZFzTVarStablqh6wVDAiYyM+8aUM0x9p3Jc"
-- >        , "aWW+eDk/UU3jCfCke7R3t2rbD1ZCj1cO08Uir3Lhf65TfU+iIrgLU3umV4B3gRcp"
-- >        , "d8iz0ZTLaG8Qnm0GsPQjR3PTZYECxEnFaRgXcQLHYYMAW9YaX6T3rlTGZAaP5Ybo"
-- >        , "xQIDAQAB"
-- >        , "-----END PUBLIC KEY-----"
-- >        ]
-- >  in  FromRsaPem { privKey = private, pubKey = public }
data RsaKeyPair = FromRsaPem { RsaKeyPair -> ByteString
privKey :: ByteString, RsaKeyPair -> ByteString
pubKey :: ByteString }
  deriving stock (Int -> RsaKeyPair -> ShowS
[RsaKeyPair] -> ShowS
RsaKeyPair -> String
(Int -> RsaKeyPair -> ShowS)
-> (RsaKeyPair -> String)
-> ([RsaKeyPair] -> ShowS)
-> Show RsaKeyPair
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RsaKeyPair] -> ShowS
$cshowList :: [RsaKeyPair] -> ShowS
show :: RsaKeyPair -> String
$cshow :: RsaKeyPair -> String
showsPrec :: Int -> RsaKeyPair -> ShowS
$cshowsPrec :: Int -> RsaKeyPair -> ShowS
Show, RsaKeyPair -> RsaKeyPair -> Bool
(RsaKeyPair -> RsaKeyPair -> Bool)
-> (RsaKeyPair -> RsaKeyPair -> Bool) -> Eq RsaKeyPair
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RsaKeyPair -> RsaKeyPair -> Bool
$c/= :: RsaKeyPair -> RsaKeyPair -> Bool
== :: RsaKeyPair -> RsaKeyPair -> Bool
$c== :: RsaKeyPair -> RsaKeyPair -> Bool
Eq)

-- | Elliptic curves parameters used in /ECDSA/ algorithms
--
--   According to RFC, the following curves are to be used:
--
--  +-------------------+-------------------------------+
--  | "alg" Param Value | Digital Signature Algorithm   |
--  +===================+===============================+
--  | ES256             | ECDSA using P-256 and SHA-256 |
--  +-------------------+-------------------------------+
--  | ES384             | ECDSA using P-384 and SHA-384 |
--  +-------------------+-------------------------------+
--  | ES512             | ECDSA using P-521 and SHA-512 |
--  +-------------------+-------------------------------+
--
--  It is up to the user to use the appropriate curves.
--
--  The following names are used in OpenSSL: /prime256v1/, /secp384r1/ and /secp521r1/
--
--  Curve parametrs should be /PEM-encoded/ strings
--
-- > ecP256KeyPair =
-- >   let private = C8.pack $ unlines
-- >         [ "-----BEGIN EC PRIVATE KEY-----"
-- >         , "MHcCAQEEINQ0e0KOa3EZSB5RTd2xBuO3O7NNFietDIWl+B+R38LuoAoGCCqGSM49"
-- >         , "AwEHoUQDQgAEKZL0X84AvdnGZdsIdAS60OnvF3FNlsrCnaXRoJUVdOYZldzb4po2"
-- >         , "uDXF5W58DS8C31fV+z+0lTG5RvuAqfkdbA=="
-- >         , "-----END EC PRIVATE KEY-----"
-- >         ]
-- >       public = C8.pack $ unlines
-- >         [ "-----BEGIN PUBLIC KEY-----"
-- >         , "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKZL0X84AvdnGZdsIdAS60OnvF3FN"
-- >         , "lsrCnaXRoJUVdOYZldzb4po2uDXF5W58DS8C31fV+z+0lTG5RvuAqfkdbA=="
-- >         , "-----END PUBLIC KEY-----"
-- >         ]
-- >   in  FromEcPem { ecPrivKey = private, ecPubKey = public }
data EcKeyPair = FromEcPem { EcKeyPair -> ByteString
ecPrivKey :: ByteString, EcKeyPair -> ByteString
ecPubKey :: ByteString }
  deriving stock (Int -> EcKeyPair -> ShowS
[EcKeyPair] -> ShowS
EcKeyPair -> String
(Int -> EcKeyPair -> ShowS)
-> (EcKeyPair -> String)
-> ([EcKeyPair] -> ShowS)
-> Show EcKeyPair
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EcKeyPair] -> ShowS
$cshowList :: [EcKeyPair] -> ShowS
show :: EcKeyPair -> String
$cshow :: EcKeyPair -> String
showsPrec :: Int -> EcKeyPair -> ShowS
$cshowsPrec :: Int -> EcKeyPair -> ShowS
Show, EcKeyPair -> EcKeyPair -> Bool
(EcKeyPair -> EcKeyPair -> Bool)
-> (EcKeyPair -> EcKeyPair -> Bool) -> Eq EcKeyPair
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EcKeyPair -> EcKeyPair -> Bool
$c/= :: EcKeyPair -> EcKeyPair -> Bool
== :: EcKeyPair -> EcKeyPair -> Bool
$c== :: EcKeyPair -> EcKeyPair -> Bool
Eq)