-- 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
"."