65 lines
1.9 KiB
Haskell
65 lines
1.9 KiB
Haskell
{-# language RecordWildCards #-}
|
|
|
|
module Fedi.Crypto where
|
|
|
|
import Crypto.Hash qualified as Crypto
|
|
import Data.ByteArray qualified as BA
|
|
import Crypto.PubKey.RSA.PKCS15 qualified as Crypto
|
|
import Crypto.Store.X509 qualified as Crypto
|
|
import Crypto.Store.PKCS8 qualified as Crypto
|
|
import Data.X509 qualified as Crypto
|
|
import Fedi.Helpers
|
|
import Data.ByteString.Base64 qualified as Base64
|
|
import Data.Base64.Types qualified as Base64
|
|
import Data.Text qualified as T
|
|
|
|
verifyPub :: MonadThrow m => ByteString -> ByteString -> ByteString -> m Bool
|
|
verifyPub pubkeypem sig message = do
|
|
pubkey <-
|
|
case Crypto.readPubKeyFileFromMemory pubkeypem of
|
|
[Crypto.PubKeyRSA pubkey'] -> pure pubkey'
|
|
_ -> throw "failed to read pubkey pem"
|
|
pure $ Crypto.verify (Just Crypto.SHA256) pubkey message sig
|
|
|
|
sign :: FilePath -> ByteString -> IO Signed
|
|
sign privatePemFile message = do
|
|
-- get private key
|
|
privkeypem <- Crypto.readKeyFile privatePemFile
|
|
privateKey <- case privkeypem of
|
|
[Crypto.Unprotected (Crypto.PrivKeyRSA privkey)] -> pure privkey
|
|
_ -> throw $ "error reading local private key from '" <> privatePemFile <> "'."
|
|
|
|
-- sign message
|
|
signedMessage <-
|
|
Crypto.sign Nothing (Just Crypto.SHA256) privateKey message
|
|
& either (throw . show) pure
|
|
|
|
-- return
|
|
pure Signed{..}
|
|
|
|
newtype Signed
|
|
= Signed
|
|
{ signedMessage :: ByteString
|
|
}
|
|
deriving Show
|
|
|
|
ppSigned :: Signed -> String
|
|
ppSigned signed =
|
|
unlines
|
|
[ "Signature"
|
|
, "{ signedMessage = " <> encodeBase64String signed.signedMessage
|
|
, "}"
|
|
]
|
|
|
|
encodeBase64 :: ByteString -> ByteString
|
|
encodeBase64 = Base64.extractBase64 . Base64.encodeBase64'
|
|
|
|
encodeBase64String :: ByteString -> String
|
|
encodeBase64String = T.unpack . Base64.extractBase64 . Base64.encodeBase64
|
|
|
|
decodeBase64 :: ByteString -> ByteString
|
|
decodeBase64 = Base64.decodeBase64Lenient
|
|
|
|
makeDigest :: ByteString -> ByteString
|
|
makeDigest message =
|
|
BA.convert (Crypto.hash message :: Crypto.Digest Crypto.SHA256)
|