    -- 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 Crypto.Hash (Digest, hashlazy)
    import Crypto.Hash.Algorithms (MD5, SHA1)
    import Crypto.Number.Serialize (i2osp)
    import qualified Crypto.PubKey.RSA as RSA
    import Data.Binary.Put (runPut)
    import qualified Data.ByteArray as BA
    import qualified Data.ByteString.Lazy as BL

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

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

    fingerprint :: PKPayload -> TwentyOctetFingerprint
    fingerprint :: PKPayload -> TwentyOctetFingerprint
    fingerprint p3 :: PKPayload
    p3@(PKPayload DeprecatedV3 _ _ _ _) =
      (ByteString -> TwentyOctetFingerprint
    TwentyOctetFingerprint (ByteString -> TwentyOctetFingerprint)
    -> (ByteString -> ByteString)
    -> ByteString
    -> TwentyOctetFingerprint
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
       ByteString -> ByteString
    BL.fromStrict (ByteString -> ByteString)
    -> (ByteString -> ByteString) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Digest MD5 -> ByteString
    forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    bin -> bout
    BA.convert (Digest MD5 -> ByteString)
    -> (ByteString -> Digest MD5) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ByteString -> Digest MD5
    forall a. HashAlgorithm a => ByteString -> Digest a
    hashlazy :: BL.ByteString -> Digest MD5))
        (Put -> ByteString
    runPut (Put -> ByteString) -> Put -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Pkt -> Put
    putPKPforFingerprinting (PKPayload -> Pkt
    PublicKeyPkt PKPayload
    p3))
    fingerprint p4 :: PKPayload
    p4@(PKPayload V4 _ _ _ _) =
      (ByteString -> TwentyOctetFingerprint
    TwentyOctetFingerprint (ByteString -> TwentyOctetFingerprint)
    -> (ByteString -> ByteString)
    -> ByteString
    -> TwentyOctetFingerprint
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
       ByteString -> ByteString
    BL.fromStrict (ByteString -> ByteString)
    -> (ByteString -> ByteString) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Digest SHA1 -> ByteString
    forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    bin -> bout
    BA.convert (Digest SHA1 -> ByteString)
    -> (ByteString -> Digest SHA1) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ByteString -> Digest SHA1
    forall a. HashAlgorithm a => ByteString -> Digest a
    hashlazy :: BL.ByteString -> Digest SHA1))
        (Put -> ByteString
    runPut (Put -> ByteString) -> Put -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Pkt -> Put
    putPKPforFingerprinting (PKPayload -> Pkt
    PublicKeyPkt PKPayload
    p4))