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

    module Codec.Encryption.OpenPGP.Fingerprint (
       eightOctetKeyID
     , fingerprint
    ) where

    import qualified Crypto.PubKey.RSA as RSA
    import Crypto.Hash (hashlazy, Digest)
    import Crypto.Hash.Algorithms (MD5, SHA1)
    import Crypto.Number.Serialize (i2osp)
    import qualified Data.ByteArray as BA
    import qualified Data.ByteString.Lazy as BL
    import Data.Binary.Put (runPut)

    import Codec.Encryption.OpenPGP.SerializeForSigs (putPKPforFingerprinting)
    import Codec.Encryption.OpenPGP.Types

    eightOctetKeyID :: PKPayload -> Either String EightOctetKeyId
    eightOctetKeyID (PKPayload DeprecatedV3 _ _ RSA (RSAPubKey (RSA_PublicKey rp))) = (Right . EightOctetKeyId . BL.reverse . BL.take 4 . BL.reverse . BL.fromStrict . i2osp . RSA.public_n) rp
    eightOctetKeyID (PKPayload DeprecatedV3 _ _ DeprecatedRSAEncryptOnly (RSAPubKey (RSA_PublicKey rp))) = (Right . EightOctetKeyId . BL.reverse . BL.take 4 . BL.reverse . BL.fromStrict . i2osp . RSA.public_n) rp
    eightOctetKeyID (PKPayload DeprecatedV3 _ _ DeprecatedRSASignOnly (RSAPubKey (RSA_PublicKey rp))) = (Right . EightOctetKeyId . BL.reverse . BL.take 4 . BL.reverse . BL.fromStrict . i2osp . RSA.public_n) rp
    eightOctetKeyID (PKPayload DeprecatedV3 _ _ _ _) = Left "Cannot calculate the key ID of a non-RSA V3 key"
    eightOctetKeyID p4@(PKPayload V4 _ _ _ _) = (Right . EightOctetKeyId . BL.drop 12 . unTOF . fingerprint) p4

    fingerprint :: PKPayload -> TwentyOctetFingerprint
    fingerprint p3@(PKPayload DeprecatedV3 _ _ _ _) = (TwentyOctetFingerprint . BL.fromStrict . BA.convert . (hashlazy :: BL.ByteString -> Digest MD5)) (runPut $ putPKPforFingerprinting (PublicKeyPkt p3))
    fingerprint p4@(PKPayload V4 _ _ _ _) = (TwentyOctetFingerprint . BL.fromStrict . BA.convert . (hashlazy :: BL.ByteString -> Digest SHA1)) (runPut $ putPKPforFingerprinting (PublicKeyPkt p4))