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