module Ssb.Types.Key (
PublicKey(..),
parsePublicKey,
parseEd25519PublicKey,
formatPublicKey,
) where
import Data.ByteString
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
import qualified Data.Text as T
import qualified Data.ByteString.Base64 as B64
import qualified Data.Aeson as Aeson
import qualified Crypto.Sign.Ed25519 as Ed
import GHC.Generics
import Data.Monoid
newtype PublicKey = Ed25519PublicKey { ed25519Key :: Ed.PublicKey }
deriving (Eq, Ord, Generic)
instance Aeson.FromJSON PublicKey where
parseJSON = Aeson.withText "PublicKey" $ \t ->
case parsePublicKey (encodeUtf8 t) of
Just pk -> return pk
Nothing -> fail ("public key decode failure: " ++ T.unpack t)
instance Aeson.ToJSON PublicKey where
toJSON = Aeson.String . decodeUtf8 . formatPublicKey
instance Show PublicKey where
show = T.unpack . decodeUtf8 . formatPublicKey
parsePublicKey :: ByteString -> Maybe PublicKey
parsePublicKey b = do
b' <- stripPrefix "@" b
case stripSuffix ".ed25519" b' of
Just b'' -> parseEd25519PublicKey b''
Nothing -> Nothing
parseEd25519PublicKey :: ByteString -> Maybe PublicKey
parseEd25519PublicKey b = Ed25519PublicKey <$> maybeEd25519PublicKey
where
decodedPublicKey = B64.decode b
maybeEd25519PublicKey = either
(const Nothing)
(Just . Ed.PublicKey)
decodedPublicKey
formatPublicKey :: PublicKey -> ByteString
formatPublicKey (Ed25519PublicKey { ed25519Key = k }) =
"@" <> B64.encode (Ed.unPublicKey k) <> ".ed25519"