qr-imager 1.0.1.7 → 1.0.1.8
raw patch · 6 files changed
+67/−68 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- qr-imager.cabal +3/−3
- src/Data/QRCodes.hs +25/−25
- src/Data/QRCodes/Exe.hs +1/−1
- src/Data/QRCodes/Image.hs +14/−14
- src/Data/QRCodes/Signature.hs +12/−13
- test/Spec.hs +12/−12
qr-imager.cabal view
@@ -1,10 +1,10 @@ cabal-version: >=1.10 name: qr-imager-version: 1.0.1.7+version: 1.0.1.8 license: BSD3 license-file: LICENSE-copyright: Copyright: (c) 2016 Vanessa McHale-maintainer: vanessa.mchale@reconfigure.io+copyright: Copyright: (c) 2016-2018 Vanessa McHale+maintainer: vamchale@gmail.com author: Vanessa McHale stability: stable homepage: https://github.com/vmchale/QRImager#readme
src/Data/QRCodes.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE GADTs #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-} -- | Module providing several functions for creating QR codes and their signed counterparts module Data.QRCodes (-- * Functions on objects@@ -14,22 +14,22 @@ , readQRStrSec' ) where -import Data.Aeson-import Codec.Picture.Png (writePng)-import Data.ByteString.Lazy (toStrict)-import qualified Data.ByteString.Char8 as BS+import Codec.Picture.Png (writePng)+import Control.Applicative ((<$>))+import Crypto.PubKey.RSA+import Data.Aeson+import qualified Data.ByteString.Char8 as BS+import Data.ByteString.Lazy (toStrict) import qualified Data.ByteString.Lazy.Char8 as BSL-import Data.Char (toLower)-import Data.Maybe-import Lens.Micro -import Lens.Micro.Extras-import Control.Applicative ((<$>))-import System.Process-import Data.QRCodes.Utils-import Data.QRCodes.Signature-import Data.QRCodes.Image-import Data.Word (Word8)-import Crypto.PubKey.RSA+import Data.Char (toLower)+import Data.Maybe+import Data.QRCodes.Image+import Data.QRCodes.Signature+import Data.QRCodes.Utils+import Data.Word (Word8)+import Lens.Micro+import Lens.Micro.Extras+import System.Process -- | Creates a signed QR code from a strict bytestring and path to keyfile/path. -- If the keyfile does not already exist it will be generated, otherwise it will be read.@@ -38,13 +38,13 @@ -- -- > byteStringToQRSec (BS.pack "hello") ".key.hk" "qrcode.png" byteStringToQRSec :: BS.ByteString -> FilePath -> FilePath -> IO ()-byteStringToQRSec string keyfile filepath = (flip byteStringToQR filepath) =<< (((fmap preserveUpper) . (flip mkSigFile keyfile)) string)+byteStringToQRSec string keyfile filepath = flip byteStringToQR filepath =<< (fmap preserveUpper . flip mkSigFile keyfile) string -- | Create a signed QR code from a strict `ByteString` and a key -- -- > byteStringToQRSec' (BS.pack "Vanessa") (generate 256 0x10001) byteStringToQRSec' :: BS.ByteString -> (PublicKey, PrivateKey) -> FilePath -> IO ()-byteStringToQRSec' string key filepath = (flip byteStringToQR filepath) =<< (((fmap preserveUpper) . (flip mkSig key)) string)+byteStringToQRSec' string key filepath = flip byteStringToQR filepath =<< (fmap preserveUpper . flip mkSig key) string -- | Creates a signed QR code from an object that is part of the ToJSON class createSecureQRCode :: (ToJSON a) => a -> FilePath -> FilePath -> IO ()@@ -60,26 +60,26 @@ createQRCode :: (ToJSON a) => a -> FilePath -> IO () createQRCode object filepath = let input = toStrict $ encode object in byteStringToQR input filepath --- | Creates a QR code from a strict bytestring+-- | Create a QR code, writing an image to the given 'FilePath' byteStringToQR :: BS.ByteString -> FilePath -> IO ()-byteStringToQR input filepath = (bsToImg input) >>= writePng filepath+byteStringToQR input filepath = bsToImg input >>= writePng filepath -- | given a filepath, read the QR code as a string in all lowercase -- -- > readQRString "picture.jpg" readQRString :: FilePath -> IO String-readQRString filepath = (map toLower) . init . (drop 8 . view _2) <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""+readQRString filepath = map toLower . init . (drop 8 . view _2) <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) "" -- | given a filepath pointing to a QR code, get the contents & verify signature with the keyfile -- -- > readQRStrSec "output.png" ".key.hk" readQRStrSec :: (FromJSON a) => FilePath -> FilePath -> IO a readQRStrSec filepath keyfile = fromJust . decode . BSL.pack <$> do- enc <- (map toLower) . init . (drop 8) . (view _2) <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""- (fmap $ liftEither BS.unpack) . (flip checkSigFile keyfile) . resolveUpper $ (BS.pack) enc+ enc <- map toLower . init . drop 8 . view _2 <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""+ fmap (liftEither BS.unpack) . flip checkSigFile keyfile . resolveUpper $ BS.pack enc -- | Read an image containing a QR code, decode and verify the signature using the given key. readQRStrSec' :: (FromJSON a) => FilePath -> (PublicKey, PrivateKey) -> IO a readQRStrSec' filepath key = fromJust . decode . BSL.pack <$> do- enc <- (map toLower) . init . (drop 8) . (view _2) <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""- (fmap $ liftEither BS.unpack) . (flip checkSig key) . resolveUpper $ (BS.pack) enc+ enc <- map toLower . init . drop 8 . view _2 <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""+ fmap (liftEither BS.unpack) . flip checkSig key . resolveUpper $ BS.pack enc
src/Data/QRCodes/Exe.hs view
@@ -38,7 +38,7 @@ readQRString filepath >>= print act (Prog Output True False filepath) = do pipeIn <- getContents- createSecureQRCode (pipeIn) ".key.hk" filepath+ createSecureQRCode pipeIn ".key.hk" filepath act (Prog Output False False filepath) = do pipeIn <- B.getContents byteStringToQR pipeIn filepath
src/Data/QRCodes/Image.hs view
@@ -10,30 +10,30 @@ , objToImgSec' ) where -import Data.Word (Word8)-import Codec.Picture.Types as T-import Prelude as P-import qualified Data.Vector.Storable as V-import qualified Data.ByteString as BS-import Data.ByteString.Lazy (toStrict)-import Data.QRCode-import Data.Aeson-import Data.QRCodes.Utils-import Data.QRCodes.Signature-import Crypto.PubKey.RSA+import Codec.Picture.Types as T+import Crypto.PubKey.RSA+import Data.Aeson+import qualified Data.ByteString as BS+import Data.ByteString.Lazy (toStrict)+import Data.QRCode+import Data.QRCodes.Signature+import Data.QRCodes.Utils+import qualified Data.Vector.Storable as V+import Data.Word (Word8)+import Prelude as P -- | Creates a signed QR code from a strict bytestring and path to keyfile/path where the keyfile should be generated, yielding a JuicyPixels `Image`. -- Note that QR codes may only contain a small number of characters, so encrypting can sometimes make an object too big to encode. -- -- > bsToImgSec (BS.pack "hello") ".key.hk" bsToImgSec :: BS.ByteString -> FilePath -> IO (T.Image Word8)-bsToImgSec string keyfile = bsToImg =<< (((fmap preserveUpper) . (flip mkSigFile keyfile)) string)+bsToImgSec string keyfile = bsToImg =<< (fmap preserveUpper . flip mkSigFile keyfile) string -- | Sign a byteString with a given key -- -- > bsToImgSec' (BS.pack "str") (generate 256 0x10001) bsToImgSec' :: BS.ByteString -> (PublicKey, PrivateKey) -> IO (T.Image Word8)-bsToImgSec' string key = bsToImg =<< (((fmap preserveUpper) . (flip mkSig key)) string)+bsToImgSec' string key = bsToImg =<< (fmap preserveUpper . flip mkSig key) string -- | Encode an object as a JuicyPixels `Image` with a key in a given file. objToImgSec :: (ToJSON a) => a -> FilePath -> IO (T.Image Word8)@@ -66,4 +66,4 @@ -- -- to scale @smallMatrix :: [[Word8]]@ by a factor of 8 fattenList :: Int -> [a] -> [a]-fattenList i l = P.concat $ P.foldr ((:) . (P.replicate i)) [] l+fattenList i l = P.concat $ P.foldr ((:) . P.replicate i) [] l
src/Data/QRCodes/Signature.hs view
@@ -1,15 +1,16 @@ -- | Functions associated with signing the JSON records module Data.QRCodes.Signature where -import Jose.Jws+import Control.Monad+import Crypto.PubKey.RSA import qualified Data.ByteString.Char8 as BS-import Jose.Jwt (unJwt, JwtError)-import Crypto.PubKey.RSA-import Lens.Micro -import Lens.Micro.Extras-import System.Directory-import Jose.Jwa (JwsAlg (RS256))-import Data.QRCodes.Utils+import Data.QRCodes.Utils+import Jose.Jwa (JwsAlg (RS256))+import Jose.Jws+import Jose.Jwt (JwtError, unJwt)+import Lens.Micro+import Lens.Micro.Extras+import System.Directory -- | Verify a signed token with a key checkSigFile :: BS.ByteString -> FilePath -> IO (Either JwtError BS.ByteString)@@ -23,17 +24,15 @@ let jws = rsaDecode (view _1 key) tok return $ fmap (view _2) jws --- | Sign a token. +-- | 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- if not switch then do+ unless switch $ do putStrLn "generating key..." key <- generate 256 0x10001 writeFile filepath (show key)- else- return () key' <- read <$> readFile filepath :: IO (PublicKey, PrivateKey) mkSig string key' @@ -46,4 +45,4 @@ signedToken <- rsaEncode RS256 (view _2 key) string let signed = fmap unJwt signedToken liftEither id (return <$> signed)- +
test/Spec.hs view
@@ -1,16 +1,16 @@-{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedStrings #-} -import Data.QRCodes-import Test.Hspec+import Data.QRCodes+import Test.Hspec main :: IO ()-main = hspec $ do+main = hspec $ describe "Data.QRCodes" $ do- it "writes a QR code" $ do- byteStringToQR "hello world" "qrcode.png" >>= (`shouldBe` ())- it "reads a QR code" $ do- readQRString "qrcode.png" >>= (`shouldBe` "hello world")- it "writes a secure QR code" $ do- createSecureQRCode ("small" :: String) ".key.hk" "qrcode-sec.png" >>= (`shouldBe` ())- it "reads a secure QR code" $ do- (readQRStrSec "qrcode-sec.png" ".key.hk" :: IO String) >>= (`shouldBe` "small")+ it "writes a QR code" $+ byteStringToQR "hello world" "qrcode.png" >>= (`shouldBe` ())+ it "reads a QR code" $+ readQRString "qrcode.png" >>= (`shouldBe` "hello world")+ it "writes a secure QR code" $+ createSecureQRCode ("small" :: String) ".key.hk" "qrcode-sec.png" >>= (`shouldBe` ())+ it "reads a secure QR code" $+ (readQRStrSec "qrcode-sec.png" ".key.hk" :: IO String) >>= (`shouldBe` "small")