-- KeyInfo.hs: OpenPGP (RFC9580) fingerprinting methods
-- Copyright © 2012-2026  Clint Adams
-- This software is released under the terms of the Expat license.
-- (See the LICENSE file).

module Codec.Encryption.OpenPGP.KeyInfo
    ( pubkeySize
    , pkalgoAbbrev
    ) where

import qualified Crypto.PubKey.DSA as DSA
import qualified Crypto.PubKey.ECC.ECDSA as ECDSA
import qualified Crypto.PubKey.ECC.Types as ECCT
import qualified Crypto.PubKey.RSA as RSA
import Data.Bits (shiftR)
import Data.List (unfoldr)

import Codec.Encryption.OpenPGP.Types
import qualified Codec.Encryption.OpenPGP.Types.Internal.Base as BaseTypes

pubkeySize :: PKey -> Either String Int
pubkeySize (RSAPubKey (RSA_PublicKey x)) = Right (RSA.public_size x * 8)
pubkeySize (DSAPubKey (DSA_PublicKey x)) =
    Right (bitcount . DSA.params_p . DSA.public_params $ x)
pubkeySize (ElGamalPubKey p _ _) = Right (bitcount p)
pubkeySize (ECDSAPubKey (ECDSA_PublicKey (ECDSA.PublicKey curve _))) =
    Right (fromIntegral (ECCT.curveSizeBits curve))
pubkeySize
    ( ECDHPubKey
            (ECDSAPubKey (ECDSA_PublicKey (ECDSA.PublicKey curve _)))
            _
            _
        ) =
        Right (fromIntegral (ECCT.curveSizeBits curve))
pubkeySize (ECDHPubKey (EdDSAPubKey EdSigningCurve25519 _) _ _) = Right 256
pubkeySize (ECDHPubKey (EdDSAPubKey EdSigningCurve448 _) _ _) = Right 448
pubkeySize (EdDSAPubKey EdSigningCurve25519 _) = Right 256
pubkeySize (EdDSAPubKey EdSigningCurve448 _) = Right 448
pubkeySize x = Left $ "Unable to calculate size of " ++ show x

bitcount :: Integer -> Int
bitcount =
    (* 8)
        . length
        . unfoldr
            ( \x ->
                if x == 0
                    then Nothing
                    else Just (True, x `shiftR` 8)
            )

pkalgoAbbrev :: PubKeyAlgorithm -> String
pkalgoAbbrev RSA = "rsa"
pkalgoAbbrev DSA = "dsa"
pkalgoAbbrev ElgamalEncryptOnly = "elg"
pkalgoAbbrev DeprecatedRSAEncryptOnly = "-re"
pkalgoAbbrev DeprecatedRSASignOnly = "-rs"
pkalgoAbbrev ECDH = "ecdh"
pkalgoAbbrev ECDSA = "ecd"
pkalgoAbbrev ForbiddenElgamal = "-eg"
pkalgoAbbrev DH = "dh"
pkalgoAbbrev EdDSA = "edd"
pkalgoAbbrev BaseTypes.X25519 = "x25"
pkalgoAbbrev BaseTypes.X448 = "x448"
pkalgoAbbrev BaseTypes.Ed25519 = "e25"
pkalgoAbbrev BaseTypes.Ed448 = "e448"
pkalgoAbbrev (OtherPKA _) = "."
