{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Crypto.JOSE.JWA.JWE
( Enc(..)
, AlgWithParams(..)
, AESGCMParameters(AESGCMParameters)
, ECDHParameters(ECDHParameters)
, PBES2Parameters(PBES2Parameters)
) where
import Data.Maybe (catMaybes)
import Crypto.JOSE.JWK
import Crypto.JOSE.TH
import Crypto.JOSE.Types
import Crypto.JOSE.Types.Internal (insertToObject)
import Data.Aeson
import qualified Data.Aeson.KeyMap as M
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
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
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 = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Encryption alg and params" forall a b. (a -> b) -> a -> b
$ \Object
o ->
case forall v. Key -> KeyMap v -> Maybe v
M.lookup Key
"alg" Object
o of
Maybe Value
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"\"alg\" parameter is required"
Just Value
"RSA1_5" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
RSA1_5
Just Value
"RSA-OAEP" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
RSA_OAEP
Just Value
"RSA-OAEP-256" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
RSA_OAEP_256
Just Value
"A128KW" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
A128KW
Just Value
"A192KW" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
A192KW
Just Value
"A256KW" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
A256KW
Just Value
"dir" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure AlgWithParams
Dir
Just Value
"ECDH-ES" -> ECDHParameters -> AlgWithParams
ECDH_ES forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"ECDH-ES+A128KW" -> ECDHParameters -> AlgWithParams
ECDH_ES_A128KW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"ECDH-ES+A192KW" -> ECDHParameters -> AlgWithParams
ECDH_ES_A192KW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"ECDH-ES+A256KW" -> ECDHParameters -> AlgWithParams
ECDH_ES_A256KW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"A128GCMKW" -> AESGCMParameters -> AlgWithParams
A128GCMKW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"A192GCMKW" -> AESGCMParameters -> AlgWithParams
A192GCMKW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"A256GCMKW" -> AESGCMParameters -> AlgWithParams
A256GCMKW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"PBES2-HS256+A128KW" -> PBES2Parameters -> AlgWithParams
PBES2_HS256_A128KW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"PBES2-HS384+A192KW" -> PBES2Parameters -> AlgWithParams
PBES2_HS384_A192KW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Just Value
"PBES2-HS512+A256KW" -> PBES2Parameters -> AlgWithParams
PBES2_HS512_A256KW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
Maybe Value
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"unrecognised value; expected: "
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 [(Key
"alg", Value
s)]
algWithParamsObject :: ToJSON a => a -> Value -> Value
algWithParamsObject :: forall a. ToJSON a => a -> Value -> Value
algWithParamsObject a
a Value
s = forall v. ToJSON v => Key -> v -> Value -> Value
insertToObject Key
"alg" Value
s (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) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES"
toJSON (ECDH_ES_A128KW ECDHParameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES+A128KW"
toJSON (ECDH_ES_A192KW ECDHParameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES+A192KW"
toJSON (ECDH_ES_A256KW ECDHParameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject ECDHParameters
params Value
"ECDH-ES+A256KW"
toJSON (A128GCMKW AESGCMParameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject AESGCMParameters
params Value
"A128GCMKW"
toJSON (A192GCMKW AESGCMParameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject AESGCMParameters
params Value
"A192GCMKW"
toJSON (A256GCMKW AESGCMParameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject AESGCMParameters
params Value
"A256GCMKW"
toJSON (PBES2_HS256_A128KW PBES2Parameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject PBES2Parameters
params Value
"PBES2-HS256+A128KW"
toJSON (PBES2_HS384_A192KW PBES2Parameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject PBES2Parameters
params Value
"PBES2-HS384+A192KW"
toJSON (PBES2_HS512_A256KW PBES2Parameters
params) = forall a. ToJSON a => a -> Value -> Value
algWithParamsObject PBES2Parameters
params Value
"PBES2-HS512+A256KW"
data ECDHParameters = ECDHParameters
{ ECDHParameters -> JWK
_epk :: JWK
, ECDHParameters -> Maybe Base64Octets
_apu :: Maybe Base64Octets
, ECDHParameters -> Maybe Base64Octets
_apv :: Maybe Base64Octets
} deriving (ECDHParameters -> ECDHParameters -> Bool
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
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 = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"ECDH Parameters" forall a b. (a -> b) -> a -> b
$ \Object
o -> JWK -> Maybe Base64Octets -> Maybe Base64Octets -> ECDHParameters
ECDHParameters
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"epk"
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"apu"
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"apv"
instance ToJSON ECDHParameters where
toJSON :: ECDHParameters -> Value
toJSON (ECDHParameters JWK
epk Maybe Base64Octets
apu Maybe Base64Octets
apv) = [Pair] -> Value
object forall a b. (a -> b) -> a -> b
$ forall a. [Maybe a] -> [a]
catMaybes
[ forall a. a -> Maybe a
Just (Key
"epk" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= JWK
epk)
, forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Key
"apu" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.=) Maybe Base64Octets
apu
, forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Key
"apu" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.=) Maybe Base64Octets
apv
]
data AESGCMParameters = AESGCMParameters
{ AESGCMParameters -> Base64Octets
_iv :: Base64Octets
, AESGCMParameters -> Base64Octets
_tag :: Base64Octets
} deriving (AESGCMParameters -> AESGCMParameters -> Bool
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
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 = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"AES-GCM Parameters" forall a b. (a -> b) -> a -> b
$ \Object
o -> Base64Octets -> Base64Octets -> AESGCMParameters
AESGCMParameters
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"iv"
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"tag"
instance ToJSON AESGCMParameters where
toJSON :: AESGCMParameters -> Value
toJSON (AESGCMParameters Base64Octets
iv Base64Octets
tag) = [Pair] -> Value
object [Key
"iv" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Base64Octets
iv, Key
"tag" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Base64Octets
tag]
data PBES2Parameters = PBES2Parameters
{ PBES2Parameters -> Base64Octets
_p2s :: Base64Octets
, PBES2Parameters -> Int
_p2c :: Int
} deriving (PBES2Parameters -> PBES2Parameters -> Bool
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
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 = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"AES-GCM Parameters" forall a b. (a -> b) -> a -> b
$ \Object
o -> Base64Octets -> Int -> PBES2Parameters
PBES2Parameters
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"p2s"
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"p2c"
instance ToJSON PBES2Parameters where
toJSON :: PBES2Parameters -> Value
toJSON (PBES2Parameters Base64Octets
p2s Int
p2c) = [Pair] -> Value
object [Key
"p2s" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Base64Octets
p2s, Key
"p2c" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Int
p2c]
$(deriveJOSEType "Enc" [
"A128CBC-HS256"
, "A192CBC-HS384"
, "A256CBC-HS512"
, "A128GCM"
, "A192GCM"
, "A256GCM"
])