-- Copyright (C) 2013, 2014, 2015, 2016  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 #-}

{-|

Data types for the JOSE library.

-}
module Crypto.JOSE.Types
  (
    Base64Integer(..)
  , _Base64Integer
  , SizedBase64Integer(..)
  , makeSizedBase64Integer
  , genSizedBase64IntegerOf
  , checkSize
  , Base64Octets(..)
  , Base64SHA1(..)
  , Base64SHA256(..)
  , Base64X509(..)
  , SignedCertificate
  , URI
  , base64url
  ) where

import Data.Word (Word8)

import Control.Lens
import Data.Aeson
import Data.Aeson.Types (Parser)
import qualified Data.ByteString as B
import Data.X509
import Network.URI (URI)
import Test.QuickCheck
import Test.QuickCheck.Instances ()

import Crypto.Number.Basic (log2)
import Crypto.JOSE.Types.Internal
import Crypto.JOSE.Types.Orphans ()


-- | A base64url encoded octet sequence interpreted as an integer.
--
-- The value is encoded in the minimum number of octets (no leading
-- zeros) with the exception of @0@ which is encoded as @AA@.
-- A leading zero when decoding is an error.
--
newtype Base64Integer = Base64Integer Integer
  deriving (Base64Integer -> Base64Integer -> Bool
(Base64Integer -> Base64Integer -> Bool)
-> (Base64Integer -> Base64Integer -> Bool) -> Eq Base64Integer
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64Integer -> Base64Integer -> Bool
$c/= :: Base64Integer -> Base64Integer -> Bool
== :: Base64Integer -> Base64Integer -> Bool
$c== :: Base64Integer -> Base64Integer -> Bool
Eq, Int -> Base64Integer -> ShowS
[Base64Integer] -> ShowS
Base64Integer -> String
(Int -> Base64Integer -> ShowS)
-> (Base64Integer -> String)
-> ([Base64Integer] -> ShowS)
-> Show Base64Integer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Base64Integer] -> ShowS
$cshowList :: [Base64Integer] -> ShowS
show :: Base64Integer -> String
$cshow :: Base64Integer -> String
showsPrec :: Int -> Base64Integer -> ShowS
$cshowsPrec :: Int -> Base64Integer -> ShowS
Show)
makePrisms ''Base64Integer

instance FromJSON Base64Integer where
  parseJSON :: Value -> Parser Base64Integer
parseJSON = String
-> (Text -> Parser Base64Integer) -> Value -> Parser Base64Integer
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"base64url integer" ((Text -> Parser Base64Integer) -> Value -> Parser Base64Integer)
-> (Text -> Parser Base64Integer) -> Value -> Parser Base64Integer
forall a b. (a -> b) -> a -> b
$ (ByteString -> Parser Base64Integer)
-> Text -> Parser Base64Integer
forall a. (ByteString -> Parser a) -> Text -> Parser a
parseB64Url
    ((Integer -> Base64Integer)
-> Parser Integer -> Parser Base64Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> Base64Integer
Base64Integer (Parser Integer -> Parser Base64Integer)
-> (ByteString -> Parser Integer)
-> ByteString
-> Parser Base64Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Parser Integer
parseOctets)

-- | Parse an octet sequence into an integer.
--
-- This function deals with ugly special cases from
-- <https://tools.ietf.org/html/rfc7518#section-2>, specifically
--
-- * The empty sequence is invalid
-- * Leading null byte is invalid (unless it is the only byte)
--
parseOctets :: B.ByteString -> Parser Integer
parseOctets :: ByteString -> Parser Integer
parseOctets ByteString
s
  | ByteString -> Bool
B.null ByteString
s      = String -> Parser Integer
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"empty octet sequence"
  | ByteString
s ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
"\NUL"   = Integer -> Parser Integer
forall (f :: * -> *) a. Applicative f => a -> f a
pure Integer
0
  | ByteString -> Word8
B.head ByteString
s Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0 = String -> Parser Integer
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"leading null byte"
  | Bool
otherwise     = Integer -> Parser Integer
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Integer
bsToInteger ByteString
s)

instance ToJSON Base64Integer where
  -- Urgh, special case: https://tools.ietf.org/html/rfc7518#section-2
  toJSON :: Base64Integer -> Value
toJSON (Base64Integer Integer
0) = Value
"AA"
  toJSON (Base64Integer Integer
x) = ByteString -> Value
encodeB64Url (ByteString -> Value) -> ByteString -> Value
forall a b. (a -> b) -> a -> b
$ Integer -> ByteString
forall a. Integral a => a -> ByteString
integerToBS Integer
x


arbitraryBigInteger :: Gen Integer
arbitraryBigInteger :: Gen Integer
arbitraryBigInteger = do
  Integer
size <- Gen Integer
forall a. Integral a => Gen a
arbitrarySizedNatural  -- number of octets
  Integer -> Integer -> Gen Integer
go (Integer
size Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1) Integer
0
  where
    go :: Integer -> Integer -> Gen Integer
    go :: Integer -> Integer -> Gen Integer
go Integer
0 Integer
n = Integer -> Gen Integer
forall (f :: * -> *) a. Applicative f => a -> f a
pure Integer
n
    go Integer
k Integer
n =
      (Gen Word8
forall a. (Bounded a, Integral a) => Gen a
arbitraryBoundedIntegral :: Gen Word8)
      Gen Word8 -> (Word8 -> Gen Integer) -> Gen Integer
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Integer -> Integer -> Gen Integer
go (Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1) (Integer -> Gen Integer)
-> (Word8 -> Integer) -> Word8 -> Gen Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
256 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+) (Integer -> Integer) -> (Word8 -> Integer) -> Word8 -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral


instance Arbitrary Base64Integer where
  arbitrary :: Gen Base64Integer
arbitrary = Integer -> Base64Integer
Base64Integer (Integer -> Base64Integer) -> Gen Integer -> Gen Base64Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Integer
arbitraryBigInteger


-- | A base64url encoded octet sequence interpreted as an integer
-- and where the number of octets carries explicit bit-length
-- information.
--
data SizedBase64Integer = SizedBase64Integer Int Integer
  deriving (Int -> SizedBase64Integer -> ShowS
[SizedBase64Integer] -> ShowS
SizedBase64Integer -> String
(Int -> SizedBase64Integer -> ShowS)
-> (SizedBase64Integer -> String)
-> ([SizedBase64Integer] -> ShowS)
-> Show SizedBase64Integer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SizedBase64Integer] -> ShowS
$cshowList :: [SizedBase64Integer] -> ShowS
show :: SizedBase64Integer -> String
$cshow :: SizedBase64Integer -> String
showsPrec :: Int -> SizedBase64Integer -> ShowS
$cshowsPrec :: Int -> SizedBase64Integer -> ShowS
Show)

instance Eq SizedBase64Integer where
  SizedBase64Integer Int
_ Integer
n == :: SizedBase64Integer -> SizedBase64Integer -> Bool
== SizedBase64Integer Int
_ Integer
m = Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
m

instance Arbitrary SizedBase64Integer where
  arbitrary :: Gen SizedBase64Integer
arbitrary = do
    Integer
x <- Gen Integer
arbitraryBigInteger
    Int
l <- [Int] -> Gen Int
forall a. [a] -> Gen a
Test.QuickCheck.elements [Int
0,Int
1,Int
2]  -- number of leading zero-bytes
    SizedBase64Integer -> Gen SizedBase64Integer
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SizedBase64Integer -> Gen SizedBase64Integer)
-> SizedBase64Integer -> Gen SizedBase64Integer
forall a b. (a -> b) -> a -> b
$ Int -> Integer -> SizedBase64Integer
SizedBase64Integer ((Integer -> Int
log2 Integer
x Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
8) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
l) Integer
x

genByteStringOf :: Int -> Gen B.ByteString
genByteStringOf :: Int -> Gen ByteString
genByteStringOf Int
n = [Word8] -> ByteString
B.pack ([Word8] -> ByteString) -> Gen [Word8] -> Gen ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen Word8 -> Gen [Word8]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
n Gen Word8
forall a. Arbitrary a => Gen a
arbitrary

-- | Generate a 'SizedBase64Integer' of the given number of bytes
--
genSizedBase64IntegerOf :: Int -> Gen SizedBase64Integer
genSizedBase64IntegerOf :: Int -> Gen SizedBase64Integer
genSizedBase64IntegerOf Int
n =
  Int -> Integer -> SizedBase64Integer
SizedBase64Integer Int
n (Integer -> SizedBase64Integer)
-> (ByteString -> Integer) -> ByteString -> SizedBase64Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Integer
bsToInteger (ByteString -> SizedBase64Integer)
-> Gen ByteString -> Gen SizedBase64Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen ByteString
genByteStringOf Int
n

-- | Create a 'SizedBase64Integer'' from an 'Integer'.
makeSizedBase64Integer :: Integer -> SizedBase64Integer
makeSizedBase64Integer :: Integer -> SizedBase64Integer
makeSizedBase64Integer Integer
x = Int -> Integer -> SizedBase64Integer
SizedBase64Integer (Integer -> Int
intBytes Integer
x) Integer
x

instance FromJSON SizedBase64Integer where
  parseJSON :: Value -> Parser SizedBase64Integer
parseJSON = String
-> (Text -> Parser SizedBase64Integer)
-> Value
-> Parser SizedBase64Integer
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"full size base64url integer" ((Text -> Parser SizedBase64Integer)
 -> Value -> Parser SizedBase64Integer)
-> (Text -> Parser SizedBase64Integer)
-> Value
-> Parser SizedBase64Integer
forall a b. (a -> b) -> a -> b
$ (ByteString -> Parser SizedBase64Integer)
-> Text -> Parser SizedBase64Integer
forall a. (ByteString -> Parser a) -> Text -> Parser a
parseB64Url (\ByteString
bytes ->
    SizedBase64Integer -> Parser SizedBase64Integer
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SizedBase64Integer -> Parser SizedBase64Integer)
-> SizedBase64Integer -> Parser SizedBase64Integer
forall a b. (a -> b) -> a -> b
$ Int -> Integer -> SizedBase64Integer
SizedBase64Integer (ByteString -> Int
B.length ByteString
bytes) (ByteString -> Integer
bsToInteger ByteString
bytes))

instance ToJSON SizedBase64Integer where
  toJSON :: SizedBase64Integer -> Value
toJSON (SizedBase64Integer Int
w Integer
n) = ByteString -> Value
encodeB64Url (ByteString -> Value) -> ByteString -> Value
forall a b. (a -> b) -> a -> b
$ Int -> Integer -> ByteString
forall a. Integral a => Int -> a -> ByteString
sizedIntegerToBS Int
w Integer
n

-- | Parsed a 'SizedBase64Integer' with an expected number of /bytes/.
--
checkSize :: Int -> SizedBase64Integer -> Parser SizedBase64Integer
checkSize :: Int -> SizedBase64Integer -> Parser SizedBase64Integer
checkSize Int
n a :: SizedBase64Integer
a@(SizedBase64Integer Int
m Integer
_) = if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
m
  then SizedBase64Integer -> Parser SizedBase64Integer
forall (m :: * -> *) a. Monad m => a -> m a
return SizedBase64Integer
a
  else String -> Parser SizedBase64Integer
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser SizedBase64Integer)
-> String -> Parser SizedBase64Integer
forall a b. (a -> b) -> a -> b
$ String
"expected " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" octets, found " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
m


-- | A base64url encoded octet sequence.  Used for payloads,
-- signatures, symmetric keys, salts, initialisation vectors, etc.
--
newtype Base64Octets = Base64Octets B.ByteString
  deriving (Base64Octets -> Base64Octets -> Bool
(Base64Octets -> Base64Octets -> Bool)
-> (Base64Octets -> Base64Octets -> Bool) -> Eq Base64Octets
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64Octets -> Base64Octets -> Bool
$c/= :: Base64Octets -> Base64Octets -> Bool
== :: Base64Octets -> Base64Octets -> Bool
$c== :: Base64Octets -> Base64Octets -> Bool
Eq, Int -> Base64Octets -> ShowS
[Base64Octets] -> ShowS
Base64Octets -> String
(Int -> Base64Octets -> ShowS)
-> (Base64Octets -> String)
-> ([Base64Octets] -> ShowS)
-> Show Base64Octets
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Base64Octets] -> ShowS
$cshowList :: [Base64Octets] -> ShowS
show :: Base64Octets -> String
$cshow :: Base64Octets -> String
showsPrec :: Int -> Base64Octets -> ShowS
$cshowsPrec :: Int -> Base64Octets -> ShowS
Show)

instance FromJSON Base64Octets where
  parseJSON :: Value -> Parser Base64Octets
parseJSON = String
-> (Text -> Parser Base64Octets) -> Value -> Parser Base64Octets
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"Base64Octets" ((Text -> Parser Base64Octets) -> Value -> Parser Base64Octets)
-> (Text -> Parser Base64Octets) -> Value -> Parser Base64Octets
forall a b. (a -> b) -> a -> b
$ (ByteString -> Parser Base64Octets) -> Text -> Parser Base64Octets
forall a. (ByteString -> Parser a) -> Text -> Parser a
parseB64Url (Base64Octets -> Parser Base64Octets
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Base64Octets -> Parser Base64Octets)
-> (ByteString -> Base64Octets)
-> ByteString
-> Parser Base64Octets
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Base64Octets
Base64Octets)

instance ToJSON Base64Octets where
  toJSON :: Base64Octets -> Value
toJSON (Base64Octets ByteString
bytes) = ByteString -> Value
encodeB64Url ByteString
bytes

instance Arbitrary Base64Octets where
  arbitrary :: Gen Base64Octets
arbitrary = ByteString -> Base64Octets
Base64Octets (ByteString -> Base64Octets) -> Gen ByteString -> Gen Base64Octets
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen ByteString
forall a. Arbitrary a => Gen a
arbitrary


-- | A base64url encoded SHA-1 digest.  Used for X.509 certificate
-- thumbprints.
--
newtype Base64SHA1 = Base64SHA1 B.ByteString
  deriving (Base64SHA1 -> Base64SHA1 -> Bool
(Base64SHA1 -> Base64SHA1 -> Bool)
-> (Base64SHA1 -> Base64SHA1 -> Bool) -> Eq Base64SHA1
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64SHA1 -> Base64SHA1 -> Bool
$c/= :: Base64SHA1 -> Base64SHA1 -> Bool
== :: Base64SHA1 -> Base64SHA1 -> Bool
$c== :: Base64SHA1 -> Base64SHA1 -> Bool
Eq, Int -> Base64SHA1 -> ShowS
[Base64SHA1] -> ShowS
Base64SHA1 -> String
(Int -> Base64SHA1 -> ShowS)
-> (Base64SHA1 -> String)
-> ([Base64SHA1] -> ShowS)
-> Show Base64SHA1
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Base64SHA1] -> ShowS
$cshowList :: [Base64SHA1] -> ShowS
show :: Base64SHA1 -> String
$cshow :: Base64SHA1 -> String
showsPrec :: Int -> Base64SHA1 -> ShowS
$cshowsPrec :: Int -> Base64SHA1 -> ShowS
Show)

instance FromJSON Base64SHA1 where
  parseJSON :: Value -> Parser Base64SHA1
parseJSON = String -> (Text -> Parser Base64SHA1) -> Value -> Parser Base64SHA1
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"base64url SHA-1" ((Text -> Parser Base64SHA1) -> Value -> Parser Base64SHA1)
-> (Text -> Parser Base64SHA1) -> Value -> Parser Base64SHA1
forall a b. (a -> b) -> a -> b
$ (ByteString -> Parser Base64SHA1) -> Text -> Parser Base64SHA1
forall a. (ByteString -> Parser a) -> Text -> Parser a
parseB64Url (\ByteString
bytes ->
    case ByteString -> Int
B.length ByteString
bytes of
      Int
20 -> Base64SHA1 -> Parser Base64SHA1
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Base64SHA1 -> Parser Base64SHA1)
-> Base64SHA1 -> Parser Base64SHA1
forall a b. (a -> b) -> a -> b
$ ByteString -> Base64SHA1
Base64SHA1 ByteString
bytes
      Int
_  -> String -> Parser Base64SHA1
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"incorrect number of bytes")

instance ToJSON Base64SHA1 where
  toJSON :: Base64SHA1 -> Value
toJSON (Base64SHA1 ByteString
bytes) = ByteString -> Value
encodeB64Url ByteString
bytes

instance Arbitrary Base64SHA1 where
  arbitrary :: Gen Base64SHA1
arbitrary = ByteString -> Base64SHA1
Base64SHA1 (ByteString -> Base64SHA1) -> Gen ByteString -> Gen Base64SHA1
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen ByteString
genByteStringOf Int
20


-- | A base64url encoded SHA-256 digest.  Used for X.509 certificate
-- thumbprints.
--
newtype Base64SHA256 = Base64SHA256 B.ByteString
  deriving (Base64SHA256 -> Base64SHA256 -> Bool
(Base64SHA256 -> Base64SHA256 -> Bool)
-> (Base64SHA256 -> Base64SHA256 -> Bool) -> Eq Base64SHA256
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64SHA256 -> Base64SHA256 -> Bool
$c/= :: Base64SHA256 -> Base64SHA256 -> Bool
== :: Base64SHA256 -> Base64SHA256 -> Bool
$c== :: Base64SHA256 -> Base64SHA256 -> Bool
Eq, Int -> Base64SHA256 -> ShowS
[Base64SHA256] -> ShowS
Base64SHA256 -> String
(Int -> Base64SHA256 -> ShowS)
-> (Base64SHA256 -> String)
-> ([Base64SHA256] -> ShowS)
-> Show Base64SHA256
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Base64SHA256] -> ShowS
$cshowList :: [Base64SHA256] -> ShowS
show :: Base64SHA256 -> String
$cshow :: Base64SHA256 -> String
showsPrec :: Int -> Base64SHA256 -> ShowS
$cshowsPrec :: Int -> Base64SHA256 -> ShowS
Show)

instance FromJSON Base64SHA256 where
  parseJSON :: Value -> Parser Base64SHA256
parseJSON = String
-> (Text -> Parser Base64SHA256) -> Value -> Parser Base64SHA256
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"base64url SHA-256" ((Text -> Parser Base64SHA256) -> Value -> Parser Base64SHA256)
-> (Text -> Parser Base64SHA256) -> Value -> Parser Base64SHA256
forall a b. (a -> b) -> a -> b
$ (ByteString -> Parser Base64SHA256) -> Text -> Parser Base64SHA256
forall a. (ByteString -> Parser a) -> Text -> Parser a
parseB64Url (\ByteString
bytes ->
    case ByteString -> Int
B.length ByteString
bytes of
      Int
32 -> Base64SHA256 -> Parser Base64SHA256
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Base64SHA256 -> Parser Base64SHA256)
-> Base64SHA256 -> Parser Base64SHA256
forall a b. (a -> b) -> a -> b
$ ByteString -> Base64SHA256
Base64SHA256 ByteString
bytes
      Int
_  -> String -> Parser Base64SHA256
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"incorrect number of bytes")

instance ToJSON Base64SHA256 where
  toJSON :: Base64SHA256 -> Value
toJSON (Base64SHA256 ByteString
bytes) = ByteString -> Value
encodeB64Url ByteString
bytes

instance Arbitrary Base64SHA256 where
  arbitrary :: Gen Base64SHA256
arbitrary = ByteString -> Base64SHA256
Base64SHA256 (ByteString -> Base64SHA256) -> Gen ByteString -> Gen Base64SHA256
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen ByteString
genByteStringOf Int
32


-- | A base64 encoded X.509 certificate.
--
newtype Base64X509 = Base64X509 SignedCertificate
  deriving (Base64X509 -> Base64X509 -> Bool
(Base64X509 -> Base64X509 -> Bool)
-> (Base64X509 -> Base64X509 -> Bool) -> Eq Base64X509
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64X509 -> Base64X509 -> Bool
$c/= :: Base64X509 -> Base64X509 -> Bool
== :: Base64X509 -> Base64X509 -> Bool
$c== :: Base64X509 -> Base64X509 -> Bool
Eq, Int -> Base64X509 -> ShowS
[Base64X509] -> ShowS
Base64X509 -> String
(Int -> Base64X509 -> ShowS)
-> (Base64X509 -> String)
-> ([Base64X509] -> ShowS)
-> Show Base64X509
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Base64X509] -> ShowS
$cshowList :: [Base64X509] -> ShowS
show :: Base64X509 -> String
$cshow :: Base64X509 -> String
showsPrec :: Int -> Base64X509 -> ShowS
$cshowsPrec :: Int -> Base64X509 -> ShowS
Show)

instance FromJSON Base64X509 where
  parseJSON :: Value -> Parser Base64X509
parseJSON = String -> (Text -> Parser Base64X509) -> Value -> Parser Base64X509
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"base64url X.509 certificate" ((Text -> Parser Base64X509) -> Value -> Parser Base64X509)
-> (Text -> Parser Base64X509) -> Value -> Parser Base64X509
forall a b. (a -> b) -> a -> b
$ (ByteString -> Parser Base64X509) -> Text -> Parser Base64X509
forall a. (ByteString -> Parser a) -> Text -> Parser a
parseB64 ((ByteString -> Parser Base64X509) -> Text -> Parser Base64X509)
-> (ByteString -> Parser Base64X509) -> Text -> Parser Base64X509
forall a b. (a -> b) -> a -> b
$
    (String -> Parser Base64X509)
-> (SignedCertificate -> Parser Base64X509)
-> Either String SignedCertificate
-> Parser Base64X509
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser Base64X509
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (Base64X509 -> Parser Base64X509
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Base64X509 -> Parser Base64X509)
-> (SignedCertificate -> Base64X509)
-> SignedCertificate
-> Parser Base64X509
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SignedCertificate -> Base64X509
Base64X509) (Either String SignedCertificate -> Parser Base64X509)
-> (ByteString -> Either String SignedCertificate)
-> ByteString
-> Parser Base64X509
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String SignedCertificate
decodeSignedCertificate

instance ToJSON Base64X509 where
  toJSON :: Base64X509 -> Value
toJSON (Base64X509 SignedCertificate
x509) = ByteString -> Value
encodeB64 (ByteString -> Value) -> ByteString -> Value
forall a b. (a -> b) -> a -> b
$ SignedCertificate -> ByteString
forall a.
(Show a, Eq a, ASN1Object a) =>
SignedExact a -> ByteString
encodeSignedObject SignedCertificate
x509