-- | Functions associated with signing the JSON records module Data.QRCodes.Signature where import Control.Monad import Crypto.PubKey.RSA import qualified Data.ByteString.Char8 as BS import Data.QRCodes.Utils import Jose.Jwa (JwsAlg (RS256)) import Jose.Jws import Jose.Jwt (JwtError, unJwt) import System.Directory -- | Verify a signed token with a key checkSigFile :: BS.ByteString -> FilePath -> IO (Either JwtError BS.ByteString) checkSigFile tok filepath = do key <- read <$> readFile filepath :: IO (PublicKey, PrivateKey) checkSig tok key -- | Verify a signed token with a key from a given filepath checkSig :: BS.ByteString -> (PublicKey, PrivateKey) -> IO (Either JwtError BS.ByteString) checkSig tok key = do let jws = rsaDecode (fst key) tok pure $ fmap snd jws -- | Sign a token. -- If the key file does not exist, a new key will be generated. mkSigFile :: BS.ByteString -> FilePath -> IO BS.ByteString mkSigFile string filepath = do switch <- doesFileExist filepath unless switch $ do putStrLn "generating key..." key <- generate 256 0x10001 writeFile filepath (show key) key' <- read <$> readFile filepath :: IO (PublicKey, PrivateKey) mkSig string key' -- | Sign a token with a key. -- (note that we must pass in a processed token since there is no uppercase/lowercase for QR codes) -- -- > mkSig (BS.pack "hello") (generate 256 0x10001) mkSig :: BS.ByteString -> (PublicKey, PrivateKey) -> IO BS.ByteString mkSig string key = do signedToken <- rsaEncode RS256 (snd key) string let signed = fmap unJwt signedToken liftEither id (return <$> signed)