-- 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))