-- Copyright (C) 2013  Fraser Tweedale
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

{-|

JSON Web Encryption data types specified under JSON Web Algorithms.

-}
module Crypto.JOSE.JWA.JWE where

import Data.Maybe (catMaybes)

import qualified Data.HashMap.Strict as M

import Crypto.JOSE.JWK
import Crypto.JOSE.TH
import Crypto.JOSE.Types
import Crypto.JOSE.Types.Internal (objectPairs)

import Data.Aeson


-- | RFC 7518 §4.  Cryptographic Algorithms for Key Management
--
data AlgWithParams
  = RSA1_5
  | RSA_OAEP
  | RSA_OAEP_256
  | A128KW
  | A192KW
  | A256KW
  | Dir
  | ECDH_ES ECDHParameters
  | ECDH_ES_A128KW ECDHParameters
  | ECDH_ES_A192KW ECDHParameters
  | ECDH_ES_A256KW ECDHParameters
  | A128GCMKW AESGCMParameters
  | A192GCMKW AESGCMParameters
  | A256GCMKW AESGCMParameters
  | PBES2_HS256_A128KW PBES2Parameters
  | PBES2_HS384_A192KW PBES2Parameters
  | PBES2_HS512_A256KW PBES2Parameters
  deriving (AlgWithParams -> AlgWithParams -> Bool
(AlgWithParams -> AlgWithParams -> Bool)
-> (AlgWithParams -> AlgWithParams -> Bool) -> Eq AlgWithParams
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AlgWithParams -> AlgWithParams -> Bool
$c/= :: AlgWithParams -> AlgWithParams -> Bool
== :: AlgWithParams -> AlgWithParams -> Bool
$c== :: AlgWithParams -> AlgWithParams -> Bool
Eq, Int -> AlgWithParams -> ShowS
[AlgWithParams] -> ShowS
AlgWithParams -> String
(Int -> AlgWithParams -> ShowS)
-> (AlgWithParams -> String)
-> ([AlgWithParams] -> ShowS)
-> Show AlgWithParams
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AlgWithParams] -> ShowS
$cshowList :: [AlgWithParams] -> ShowS
show :: AlgWithParams -> String
$cshow :: AlgWithParams -> String
showsPrec :: Int -> AlgWithParams -> ShowS
$cshowsPrec :: Int -> AlgWithParams -> ShowS
Show)

instance FromJSON AlgWithParams where
  parseJSON :: Value -> Parser AlgWithParams
parseJSON = String
-> (Object -> Parser AlgWithParams)
-> Value
-> Parser AlgWithParams
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Encryption alg and params" ((Object -> Parser AlgWithParams) -> Value -> Parser AlgWithParams)
-> (Object -> Parser AlgWithParams)
-> Value
-> Parser AlgWithParams
forall a b. (a -> b) -> a -> b
$ \Object
o ->
    case Text -> Object -> Maybe Value
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
M.lookup Text
"alg" Object
o of
      Maybe Value
Nothing -> String -> Parser AlgWithParams
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"\"alg\" parameter is required"
      Just Value
"RSA1_5"             -> AlgWithParams -> Parser AlgWithParams
forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
RSA1_5
      Just Value
"RSA-OAEP"           -> AlgWithParams -> Parser AlgWithParams
forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
RSA_OAEP
      Just Value
"RSA-OAEP-256"       -> AlgWithParams -> Parser AlgWithParams
forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
RSA_OAEP_256
      Just Value
"A128KW"             -> AlgWithParams -> Parser AlgWithParams
forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
A128KW
      Just Value
"A192KW"             -> AlgWithParams -> Parser AlgWithParams
forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
A192KW
      Just Value
"A256KW"             -> AlgWithParams -> Parser AlgWithParams
forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
A256KW
      Just Value
"dir"                -> AlgWithParams -> Parser AlgWithParams
forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
Dir
      Just Value
"ECDH-ES"            -> ECDHParameters -> AlgWithParams
ECDH_ES            (ECDHParameters -> AlgWithParams)
-> Parser ECDHParameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser ECDHParameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"ECDH-ES+A128KW"     -> ECDHParameters -> AlgWithParams
ECDH_ES_A128KW     (ECDHParameters -> AlgWithParams)
-> Parser ECDHParameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser ECDHParameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"ECDH-ES+A192KW"     -> ECDHParameters -> AlgWithParams
ECDH_ES_A192KW     (ECDHParameters -> AlgWithParams)
-> Parser ECDHParameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser ECDHParameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"ECDH-ES+A256KW"     -> ECDHParameters -> AlgWithParams
ECDH_ES_A256KW     (ECDHParameters -> AlgWithParams)
-> Parser ECDHParameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser ECDHParameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"A128GCMKW"          -> AESGCMParameters -> AlgWithParams
A128GCMKW          (AESGCMParameters -> AlgWithParams)
-> Parser AESGCMParameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser AESGCMParameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"A192GCMKW"          -> AESGCMParameters -> AlgWithParams
A192GCMKW          (AESGCMParameters -> AlgWithParams)
-> Parser AESGCMParameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser AESGCMParameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"A256GCMKW"          -> AESGCMParameters -> AlgWithParams
A256GCMKW          (AESGCMParameters -> AlgWithParams)
-> Parser AESGCMParameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser AESGCMParameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"PBES2-HS256+A128KW" -> PBES2Parameters -> AlgWithParams
PBES2_HS256_A128KW (PBES2Parameters -> AlgWithParams)
-> Parser PBES2Parameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser PBES2Parameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"PBES2-HS384+A192KW" -> PBES2Parameters -> AlgWithParams
PBES2_HS384_A192KW (PBES2Parameters -> AlgWithParams)
-> Parser PBES2Parameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser PBES2Parameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Just Value
"PBES2-HS512+A256KW" -> PBES2Parameters -> AlgWithParams
PBES2_HS512_A256KW (PBES2Parameters -> AlgWithParams)
-> Parser PBES2Parameters -> Parser AlgWithParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser PBES2Parameters
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      Maybe Value
_ -> String -> Parser AlgWithParams
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser AlgWithParams) -> String -> Parser AlgWithParams
forall a b. (a -> b) -> a -> b
$ String
"unrecognised value; expected: "
         String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"[\"RSA1_5\",\"RSA-OAEP\",\"RSA-OAEP-256\",\"A128KW\",\"A192KW\",\"A256KW\",\"dir\",\"ECDH-ES\",\"ECDH-ES+A128KW\",\"ECDH-ES+A192KW\",\"ECDH-ES+A256KW\",\"A128GCMKW\",\"A192GCMKW\",\"A256GCMKW\",\"PBES2-HS256+A128KW\",\"PBES2-HS384+A128KW\",\"PBES2-HS512+A128KW\"]"

algObject :: Value -> Value
algObject :: Value -> Value
algObject Value
s = [Pair] -> Value
object [(Text
"alg", Value
s)]

algWithParamsObject :: ToJSON a => a -> Value -> Value
algWithParamsObject :: a -> Value -> Value
algWithParamsObject a
a Value
s = [Pair] -> Value
object ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ (Text
"alg", Value
s) Pair -> [Pair] -> [Pair]
forall a. a -> [a] -> [a]
: Value -> [Pair]
objectPairs (a -> Value
forall a. ToJSON a => a -> Value
toJSON a
a)

instance ToJSON AlgWithParams where
  toJSON :: AlgWithParams -> Value
toJSON AlgWithParams
RSA1_5       = Value -> Value
algObject Value
"RSA1_5"
  toJSON AlgWithParams
RSA_OAEP     = Value -> Value
algObject Value
"RSA-OAEP"
  toJSON AlgWithParams
RSA_OAEP_256 = Value -> Value
algObject Value
"RSA-OAEP-256"
  toJSON AlgWithParams
A128KW       = Value -> Value
algObject Value
"A128KW"
  toJSON AlgWithParams
A192KW       = Value -> Value
algObject Value
"A192KW"
  toJSON AlgWithParams
A256KW       = Value -> Value
algObject Value
"A256KW"
  toJSON AlgWithParams
Dir          = Value -> Value
algObject Value
"Dir"
  toJSON (ECDH_ES ECDHParameters
params)             = ECDHParameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES"
  toJSON (ECDH_ES_A128KW ECDHParameters
params)      = ECDHParameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES+A128KW"
  toJSON (ECDH_ES_A192KW ECDHParameters
params)      = ECDHParameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES+A192KW"
  toJSON (ECDH_ES_A256KW ECDHParameters
params)      = ECDHParameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES+A256KW"
  toJSON (A128GCMKW AESGCMParameters
params)           = AESGCMParameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject AESGCMParameters
params Value
"A128GCMKW"
  toJSON (A192GCMKW AESGCMParameters
params)           = AESGCMParameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject AESGCMParameters
params Value
"A192GCMKW"
  toJSON (A256GCMKW AESGCMParameters
params)           = AESGCMParameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject AESGCMParameters
params Value
"A256GCMKW"
  toJSON (PBES2_HS256_A128KW PBES2Parameters
params)  = PBES2Parameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject PBES2Parameters
params Value
"PBES2-HS256+A128KW"
  toJSON (PBES2_HS384_A192KW PBES2Parameters
params)  = PBES2Parameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject PBES2Parameters
params Value
"PBES2-HS384+A192KW"
  toJSON (PBES2_HS512_A256KW PBES2Parameters
params)  = PBES2Parameters -> Value -> Value
forall a. ToJSON a => a -> Value -> Value
algWithParamsObject PBES2Parameters
params Value
"PBES2-HS512+A256KW"


-- | RFC 7518 §4.6.1.  Header Parameters Used for ECDH Key Agreement
--
data ECDHParameters = ECDHParameters
  { ECDHParameters -> JWK
_epk :: JWK                 -- ^ Ephemeral Public Key ; a JWK PUBLIC key
  , ECDHParameters -> Maybe Base64Octets
_apu :: Maybe Base64Octets  -- ^ Agreement PartyUInfo
  , ECDHParameters -> Maybe Base64Octets
_apv :: Maybe Base64Octets  -- ^ Agreement PartyVInfo
  } deriving (ECDHParameters -> ECDHParameters -> Bool
(ECDHParameters -> ECDHParameters -> Bool)
-> (ECDHParameters -> ECDHParameters -> Bool) -> Eq ECDHParameters
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ECDHParameters -> ECDHParameters -> Bool
$c/= :: ECDHParameters -> ECDHParameters -> Bool
== :: ECDHParameters -> ECDHParameters -> Bool
$c== :: ECDHParameters -> ECDHParameters -> Bool
Eq, Int -> ECDHParameters -> ShowS
[ECDHParameters] -> ShowS
ECDHParameters -> String
(Int -> ECDHParameters -> ShowS)
-> (ECDHParameters -> String)
-> ([ECDHParameters] -> ShowS)
-> Show ECDHParameters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ECDHParameters] -> ShowS
$cshowList :: [ECDHParameters] -> ShowS
show :: ECDHParameters -> String
$cshow :: ECDHParameters -> String
showsPrec :: Int -> ECDHParameters -> ShowS
$cshowsPrec :: Int -> ECDHParameters -> ShowS
Show)

instance FromJSON ECDHParameters where
  parseJSON :: Value -> Parser ECDHParameters
parseJSON = String
-> (Object -> Parser ECDHParameters)
-> Value
-> Parser ECDHParameters
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"ECDH Parameters" ((Object -> Parser ECDHParameters)
 -> Value -> Parser ECDHParameters)
-> (Object -> Parser ECDHParameters)
-> Value
-> Parser ECDHParameters
forall a b. (a -> b) -> a -> b
$ \Object
o -> JWK -> Maybe Base64Octets -> Maybe Base64Octets -> ECDHParameters
ECDHParameters
    (JWK -> Maybe Base64Octets -> Maybe Base64Octets -> ECDHParameters)
-> Parser JWK
-> Parser
     (Maybe Base64Octets -> Maybe Base64Octets -> ECDHParameters)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser JWK
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"epk"
    Parser (Maybe Base64Octets -> Maybe Base64Octets -> ECDHParameters)
-> Parser (Maybe Base64Octets)
-> Parser (Maybe Base64Octets -> ECDHParameters)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Base64Octets)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"apu"
    Parser (Maybe Base64Octets -> ECDHParameters)
-> Parser (Maybe Base64Octets) -> Parser ECDHParameters
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Base64Octets)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"apv"

instance ToJSON ECDHParameters where
  toJSON :: ECDHParameters -> Value
toJSON (ECDHParameters JWK
epk Maybe Base64Octets
apu Maybe Base64Octets
apv) = [Pair] -> Value
object ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$ [Maybe Pair] -> [Pair]
forall a. [Maybe a] -> [a]
catMaybes
    [ Pair -> Maybe Pair
forall a. a -> Maybe a
Just (Text
"epk" Text -> JWK -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= JWK
epk)
    , (Base64Octets -> Pair) -> Maybe Base64Octets -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text
"apu" Text -> Base64Octets -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=) Maybe Base64Octets
apu
    , (Base64Octets -> Pair) -> Maybe Base64Octets -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text
"apu" Text -> Base64Octets -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=) Maybe Base64Octets
apv
    ]


-- | RFC 7518 §4.7.1.  Header Parameters Used for AES GCM Key Encryption
--
data AESGCMParameters = AESGCMParameters
  { AESGCMParameters -> Base64Octets
_iv :: Base64Octets  -- ^ Initialization Vector  (must be 96 bits?)
  , AESGCMParameters -> Base64Octets
_tag :: Base64Octets -- ^ Authentication Tag (must be 128 bits?)
  } deriving (AESGCMParameters -> AESGCMParameters -> Bool
(AESGCMParameters -> AESGCMParameters -> Bool)
-> (AESGCMParameters -> AESGCMParameters -> Bool)
-> Eq AESGCMParameters
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AESGCMParameters -> AESGCMParameters -> Bool
$c/= :: AESGCMParameters -> AESGCMParameters -> Bool
== :: AESGCMParameters -> AESGCMParameters -> Bool
$c== :: AESGCMParameters -> AESGCMParameters -> Bool
Eq, Int -> AESGCMParameters -> ShowS
[AESGCMParameters] -> ShowS
AESGCMParameters -> String
(Int -> AESGCMParameters -> ShowS)
-> (AESGCMParameters -> String)
-> ([AESGCMParameters] -> ShowS)
-> Show AESGCMParameters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AESGCMParameters] -> ShowS
$cshowList :: [AESGCMParameters] -> ShowS
show :: AESGCMParameters -> String
$cshow :: AESGCMParameters -> String
showsPrec :: Int -> AESGCMParameters -> ShowS
$cshowsPrec :: Int -> AESGCMParameters -> ShowS
Show)

instance FromJSON AESGCMParameters where
  parseJSON :: Value -> Parser AESGCMParameters
parseJSON = String
-> (Object -> Parser AESGCMParameters)
-> Value
-> Parser AESGCMParameters
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"AES-GCM Parameters" ((Object -> Parser AESGCMParameters)
 -> Value -> Parser AESGCMParameters)
-> (Object -> Parser AESGCMParameters)
-> Value
-> Parser AESGCMParameters
forall a b. (a -> b) -> a -> b
$ \Object
o -> Base64Octets -> Base64Octets -> AESGCMParameters
AESGCMParameters
    (Base64Octets -> Base64Octets -> AESGCMParameters)
-> Parser Base64Octets -> Parser (Base64Octets -> AESGCMParameters)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser Base64Octets
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"iv"
    Parser (Base64Octets -> AESGCMParameters)
-> Parser Base64Octets -> Parser AESGCMParameters
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Base64Octets
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"tag"

instance ToJSON AESGCMParameters where
  toJSON :: AESGCMParameters -> Value
toJSON (AESGCMParameters Base64Octets
iv Base64Octets
tag) = [Pair] -> Value
object [Text
"iv" Text -> Base64Octets -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Base64Octets
iv, Text
"tag" Text -> Base64Octets -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Base64Octets
tag]


-- | RFC 7518 §4.8.1.  Header Parameters Used for PBES2 Key Encryption
--
data PBES2Parameters =  PBES2Parameters
  { PBES2Parameters -> Base64Octets
_p2s :: Base64Octets   -- ^ PBKDF2 salt input
  , PBES2Parameters -> Int
_p2c :: Int            -- ^ PBKDF2 iteration count ; POSITIVE integer
  } deriving (PBES2Parameters -> PBES2Parameters -> Bool
(PBES2Parameters -> PBES2Parameters -> Bool)
-> (PBES2Parameters -> PBES2Parameters -> Bool)
-> Eq PBES2Parameters
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PBES2Parameters -> PBES2Parameters -> Bool
$c/= :: PBES2Parameters -> PBES2Parameters -> Bool
== :: PBES2Parameters -> PBES2Parameters -> Bool
$c== :: PBES2Parameters -> PBES2Parameters -> Bool
Eq, Int -> PBES2Parameters -> ShowS
[PBES2Parameters] -> ShowS
PBES2Parameters -> String
(Int -> PBES2Parameters -> ShowS)
-> (PBES2Parameters -> String)
-> ([PBES2Parameters] -> ShowS)
-> Show PBES2Parameters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PBES2Parameters] -> ShowS
$cshowList :: [PBES2Parameters] -> ShowS
show :: PBES2Parameters -> String
$cshow :: PBES2Parameters -> String
showsPrec :: Int -> PBES2Parameters -> ShowS
$cshowsPrec :: Int -> PBES2Parameters -> ShowS
Show)

instance FromJSON PBES2Parameters where
  parseJSON :: Value -> Parser PBES2Parameters
parseJSON = String
-> (Object -> Parser PBES2Parameters)
-> Value
-> Parser PBES2Parameters
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"AES-GCM Parameters" ((Object -> Parser PBES2Parameters)
 -> Value -> Parser PBES2Parameters)
-> (Object -> Parser PBES2Parameters)
-> Value
-> Parser PBES2Parameters
forall a b. (a -> b) -> a -> b
$ \Object
o -> Base64Octets -> Int -> PBES2Parameters
PBES2Parameters
    (Base64Octets -> Int -> PBES2Parameters)
-> Parser Base64Octets -> Parser (Int -> PBES2Parameters)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser Base64Octets
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"p2s"  -- TODO salt input value must be >= 8 octets
    Parser (Int -> PBES2Parameters)
-> Parser Int -> Parser PBES2Parameters
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Int
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"p2c"

instance ToJSON PBES2Parameters where
  toJSON :: PBES2Parameters -> Value
toJSON (PBES2Parameters Base64Octets
p2s Int
p2c) = [Pair] -> Value
object [Text
"p2s" Text -> Base64Octets -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Base64Octets
p2s, Text
"p2c" Text -> Int -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Int
p2c]


-- | RFC 7518 §5  Cryptographic Algorithms for Content Encryption
--
$(deriveJOSEType "Enc" [
  "A128CBC-HS256"   -- AES HMAC SHA authenticated encryption  Required
  , "A192CBC-HS384" -- AES HMAC SHA authenticated encryption  Optional
  , "A256CBC-HS512" -- AES HMAC SHA authenticated encryption  Required
  , "A128GCM"       -- AES in Galois/Counter Mode             Recommended
  , "A192GCM"       -- AES in Galois/Counter Mode             Optional
  , "A256GCM"       -- AES in Galois/Counter Mode             Recommended
  ])