packages feed

htalkat-0.1.1: Certificate.hs

-- This file is part of htalkat
-- Copyright (C) 2021 Martin Bays <mbays@sdf.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of version 3 of the GNU General Public License as
-- published by the Free Software Foundation, or any later version.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see http://www.gnu.org/licenses/.

module Certificate where

import           Crypto.Hash
import           Data.ASN1.BinaryEncoding (DER (..))
import           Data.ASN1.Encoding       (encodeASN1')
import           Data.ASN1.Types          (ASN1Object (..))
import           Data.ByteArray           (convert)

import qualified Data.ByteString          as BS
import qualified Data.Text                as TS
import qualified Data.Text.Encoding       as TS
import qualified Data.X509                as X

import           Fingerprint

newtype Certificate = Certificate X.SignedCertificate
    deriving (Eq, Show)

takeTailCert :: X.CertificateChain -> Maybe Certificate
takeTailCert (X.CertificateChain (c:_)) = Just $ Certificate c
takeTailCert _                          = Nothing

-- |First 16 bytes of sha256 hash of DER encoding of SPKI field
-- (as suggested by RFC7469).
spkiFingerprint :: Certificate -> Fingerprint
spkiFingerprint (Certificate signed) = truncateFP 16 . Fingerprint . convert . hashWith SHA256 .
        encodeDER . X.certPubKey . X.signedObject $ X.getSigned signed
    where
    truncateFP :: Int -> Fingerprint -> Fingerprint
    truncateFP n (Fingerprint fp) = Fingerprint $ BS.take n fp
    encodeDER :: ASN1Object o => o -> BS.ByteString
    encodeDER = encodeASN1' DER . (`toASN1` [])

certCN :: Certificate -> String
certCN (Certificate signed) = maybe "" (TS.unpack . TS.decodeUtf8 . X.getCharacterStringRawData)
    . X.getDnElement X.DnCommonName . X.certIssuerDN $ X.getCertificate signed