-- 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 KeyVersion
DeprecatedV3 ThirtyTwoBitTimeStamp
_ V3Expiration
_ PubKeyAlgorithm
RSA (RSAPubKey (RSA_PublicKey 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 Int64
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 KeyVersion
DeprecatedV3 ThirtyTwoBitTimeStamp
_ V3Expiration
_ PubKeyAlgorithm
DeprecatedRSAEncryptOnly (RSAPubKey (RSA_PublicKey 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 Int64
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 KeyVersion
DeprecatedV3 ThirtyTwoBitTimeStamp
_ V3Expiration
_ PubKeyAlgorithm
DeprecatedRSASignOnly (RSAPubKey (RSA_PublicKey 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 Int64
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 KeyVersion
DeprecatedV3 ThirtyTwoBitTimeStamp
_ V3Expiration
_ PubKeyAlgorithm
_ PKey
_) =
  String -> Either String EightOctetKeyId
forall a b. a -> Either a b
Left String
"Cannot calculate the key ID of a non-RSA V3 key"
eightOctetKeyID p4 :: PKPayload
p4@(PKPayload KeyVersion
V4 ThirtyTwoBitTimeStamp
_ V3Expiration
_ PubKeyAlgorithm
_ PKey
_) =
  (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 Int64
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 KeyVersion
DeprecatedV3 ThirtyTwoBitTimeStamp
_ V3Expiration
_ PubKeyAlgorithm
_ PKey
_) =
  (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 KeyVersion
V4 ThirtyTwoBitTimeStamp
_ V3Expiration
_ PubKeyAlgorithm
_ PKey
_) =
  (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))