{-# LANGUAGE CPP #-} module Data.OpenPGP.Util.Fingerprint (fingerprint,Fingerprint(..),hex) where import qualified Data.OpenPGP as OpenPGP import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LZ import Data.Char (toUpper) import Data.Word (Word8) import Numeric (showHex) #if defined(VERSION_cryptonite) import Crypto.Hash.Algorithms import Crypto.Hash import qualified Data.ByteArray as Bytes #else import Crypto.Hash.MD5 as MD5 import Crypto.Hash.SHA1 as SHA1 #endif oo :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c oo = (.) . (.) newtype Fingerprint = Fingerprint BS.ByteString instance Show Fingerprint where show fp = hex fp hex :: Fingerprint -> String hex (Fingerprint bs) = hexify bs where hexify = map toUpper . hexString . BS.unpack hexString :: [Word8] -> String hexString = foldr (pad `oo` showHex) "" where pad s | odd $ length s = '0':s | otherwise = s -- | Generate a key fingerprint from a PublicKeyPacket or SecretKeyPacket -- fingerprint :: OpenPGP.Packet -> Fingerprint fingerprint p | OpenPGP.version p == 5 = Fingerprint $ sha256 material | OpenPGP.version p == 4 = Fingerprint $ sha1 material | OpenPGP.version p `elem` [2, 3] = Fingerprint $ md5 material | otherwise = error "Unsupported Packet version or type in fingerprint" where #if defined(VERSION_cryptonite) sha256 x = Bytes.convert (hashlazy x :: Digest SHA256) sha1 x = Bytes.convert (hashlazy x :: Digest SHA1) md5 x = Bytes.convert (hashlazy x :: Digest MD5) #else -- TODO: SHA256 (or drop support for non-cryptonite) sha1 = SHA1.hashlazy md5 = MD5.hashlazy #endif material = LZ.concat $ OpenPGP.fingerprint_material p