packages feed

data-rfc5280-0.1.0.0: src/Data/Rfc5280/AuthorityKeyIdentifier.hs

{-# LANGUAGE OverloadedStrings #-}

{- |
Module      : Data.Rfc5280.AuthorityKeyIdentifier
Copyright   : (c) 2026 Tim Emiola
Maintainer  : Tim Emiola <adetokunbo@emio.la>
SPDX-License-Identifier: BSD3

Provides the 'AuthorityKeyIdentifier' extension type and its smart constructor.
-}
module Data.Rfc5280.AuthorityKeyIdentifier
  ( AuthorityKeyIdentifier (..)
  , mkAuthorityKeyIdentifier
  )
where

import Data.List.NonEmpty (NonEmpty (..))
import Data.Rfc5280.HasOID (HasOID (..))
import Data.Rfc5280.Internal (RenderConfig (..), intersperseCommas)


{- | Represents the AuthorityKeyIdentifier extension

See <https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.1 RFC 5280 §4.2.1.1>.
-}
data AuthorityKeyIdentifier = AuthorityKeyIdentifier
  { akiKeyId :: !Bool
  -- ^ include key ID
  , akiKeyIdAlways :: !Bool
  {- ^ always include the key identifier, even if the issuer certificate
  has no SubjectKeyIdentifier extension
  -}
  , akiIssuer :: !Bool
  -- ^ include issuer name + serial
  , akiIssuerAlways :: !Bool
  {- ^ always include the issuer name and serial, even if the issuer certificate
  has no SubjectKeyIdentifier extension
  -}
  }
  deriving (Eq, Show)


{- | Construct an 'AuthorityKeyIdentifier', normalising the @always@ flags:
if @keyIdAlways@ is 'True', @keyId@ is set to 'True'; if @issuerAlways@ is
'True', @issuer@ is set to 'True'.
-}
mkAuthorityKeyIdentifier :: Bool -> Bool -> Bool -> Bool -> AuthorityKeyIdentifier
mkAuthorityKeyIdentifier keyId keyIdAlways issuer issuerAlways =
  AuthorityKeyIdentifier
    { akiKeyId = keyId || keyIdAlways
    , akiKeyIdAlways = keyIdAlways
    , akiIssuer = issuer || issuerAlways
    , akiIssuerAlways = issuerAlways
    }


instance HasOID AuthorityKeyIdentifier where
  extensionOID _ = 2 :| [5, 29, 35]


instance RenderConfig AuthorityKeyIdentifier where
  renderBuilder aki =
    let keyId
          | akiKeyIdAlways aki = Just "keyid:always"
          | akiKeyId aki = Just "keyid"
          | otherwise = Nothing
        issuer
          | akiIssuerAlways aki = Just "issuer:always"
          | akiIssuer aki = Just "issuer"
          | otherwise = Nothing
     in case (keyId, issuer) of
          (Nothing, Nothing) -> mempty
          (Nothing, Just x) -> x
          (Just x, Nothing) -> x
          (Just x, Just y) -> intersperseCommas (x :| [y])