    -- KeyInfo.hs: OpenPGP (RFC4880) fingerprinting methods
    -- Copyright © 2012-2018  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

    pubkeySize :: PKey -> Either String Int
    pubkeySize :: PKey -> Either String Int
    pubkeySize (RSAPubKey (RSA_PublicKey PublicKey
    x)) = Int -> Either String Int
    forall a b. b -> Either a b
    Right (PublicKey -> Int
    RSA.public_size PublicKey
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    8)
    pubkeySize (DSAPubKey (DSA_PublicKey PublicKey
    x)) =
      Int -> Either String Int
    forall a b. b -> Either a b
    Right (Integer -> Int
    bitcount (Integer -> Int) -> (PublicKey -> Integer) -> PublicKey -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Params -> Integer
    DSA.params_p (Params -> Integer)
    -> (PublicKey -> Params) -> PublicKey -> Integer
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PublicKey -> Params
    DSA.public_params (PublicKey -> Int) -> PublicKey -> Int
    forall a b. (a -> b) -> a -> b
    $ PublicKey
    x)
    pubkeySize (ElGamalPubKey Integer
    p Integer
    _ Integer
    _) = Int -> Either String Int
    forall a b. b -> Either a b
    Right (Integer -> Int
    bitcount Integer
    p)
    pubkeySize (ECDSAPubKey (ECDSA_PublicKey (ECDSA.PublicKey Curve
    curve PublicPoint
    _))) =
      Int -> Either String Int
    forall a b. b -> Either a b
    Right (Int -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Curve -> Int
    ECCT.curveSizeBits Curve
    curve))
    pubkeySize (ECDHPubKey (ECDSAPubKey (ECDSA_PublicKey (ECDSA.PublicKey Curve
    curve PublicPoint
    _))) HashAlgorithm
    _ SymmetricAlgorithm
    _) =
      Int -> Either String Int
    forall a b. b -> Either a b
    Right (Int -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Curve -> Int
    ECCT.curveSizeBits Curve
    curve))
    pubkeySize (ECDHPubKey (EdDSAPubKey EdSigningCurve
    Ed25519 EPoint
    _) HashAlgorithm
    _ SymmetricAlgorithm
    _) = Int -> Either String Int
    forall a b. b -> Either a b
    Right Int
    256
    pubkeySize (EdDSAPubKey EdSigningCurve
    Ed25519 EPoint
    _) = Int -> Either String Int
    forall a b. b -> Either a b
    Right Int
    256
    pubkeySize PKey
    x = String -> Either String Int
    forall a b. a -> Either a b
    Left (String -> Either String Int) -> String -> Either String Int
    forall a b. (a -> b) -> a -> b
    $ String
    "Unable to calculate size of " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ PKey -> String
    forall a. Show a => a -> String
    show PKey
    x

    bitcount :: Integer -> Int
    bitcount :: Integer -> Int
    bitcount =
      (Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    8) (Int -> Int) -> (Integer -> Int) -> Integer -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
      [Bool] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length ([Bool] -> Int) -> (Integer -> [Bool]) -> Integer -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
      (Integer -> Maybe (Bool, Integer)) -> Integer -> [Bool]
    forall b a. (b -> Maybe (a, b)) -> b -> [a]
    unfoldr
        (\Integer
    x ->
           if Integer
    x Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == Integer
    0
             then Maybe (Bool, Integer)
    forall a. Maybe a
    Nothing
             else (Bool, Integer) -> Maybe (Bool, Integer)
    forall a. a -> Maybe a
    Just (Bool
    True, Integer
    x Integer -> Int -> Integer
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    8))

    -- FIXME: redo these for hOpenPGP 3
    pkalgoAbbrev :: PubKeyAlgorithm -> String
    pkalgoAbbrev :: PubKeyAlgorithm -> String
    pkalgoAbbrev PubKeyAlgorithm
    RSA = String
    "R"
    pkalgoAbbrev PubKeyAlgorithm
    DSA = String
    "D"
    pkalgoAbbrev PubKeyAlgorithm
    ElgamalEncryptOnly = String
    "g"
    pkalgoAbbrev PubKeyAlgorithm
    DeprecatedRSAEncryptOnly = String
    "-"
    pkalgoAbbrev PubKeyAlgorithm
    DeprecatedRSASignOnly = String
    "_"
    pkalgoAbbrev PubKeyAlgorithm
    ECDH = String
    "e"
    pkalgoAbbrev PubKeyAlgorithm
    ECDSA = String
    "E"
    pkalgoAbbrev PubKeyAlgorithm
    ForbiddenElgamal = String
    "f"
    pkalgoAbbrev PubKeyAlgorithm
    DH = String
    "d"
    pkalgoAbbrev PubKeyAlgorithm
    EdDSA = String
    "w"
    pkalgoAbbrev (OtherPKA Word8
    _) = String
    "."