packages feed

hOpenPGP-3.7: Codec/Encryption/OpenPGP/KeySelection.hs

-- KeySelection.hs: OpenPGP (RFC9580) ways to ask for keys
-- Copyright © 2014-2026  Clint Adams
-- This software is released under the terms of the Expat license.
-- (See the LICENSE file).
{-# LANGUAGE OverloadedStrings #-}

module Codec.Encryption.OpenPGP.KeySelection
    ( parseEightOctetKeyId
    , parseFingerprint
    ) where

import Control.Applicative (optional, (<|>))
import Crypto.Number.Serialize (i2osp)
import Data.Attoparsec.Text
    ( Parser
    , asciiCI
    , count
    , hexadecimal
    , inClass
    , parseOnly
    , satisfy
    )
import Data.Bifunctor (bimap)
import qualified Data.ByteString as B
import Data.Text (Text, toUpper)
import qualified Data.Text as T

import Codec.Encryption.OpenPGP.Types

parseEightOctetKeyId
    :: Text -> Either KeySelectionError EightOctetKeyId
parseEightOctetKeyId input =
    let upper = toUpper input
     in bimap
            (const (KeySelectionParseError upper))
            EightOctetKeyId
            (parseOnly (hexPrefix *> hexen 16) upper >>= parseOnly hexes)

parseFingerprint :: Text -> Either KeySelectionError Fingerprint
parseFingerprint input =
    let filtered = toUpper (T.filter (/= ' ') input)
     in bimap
            (const (KeySelectionParseError filtered))
            Fingerprint
            ( parseOnly (hexen 64 <|> hexen 40 <|> hexen 32) filtered
                >>= parseOnly hexes
            )

hexPrefix :: Parser (Maybe Text)
hexPrefix = optional (asciiCI "0x")

hexen :: Int -> Parser Text
hexen n = T.pack <$> count n (satisfy (inClass "A-F0-9"))

hexes :: Parser B.ByteString
hexes = i2osp <$> hexadecimal