api-yoti (empty) → 0.1.0.0
raw patch · 6 files changed
+224/−0 lines, 6 filesdep +aesondep +basedep +base64-bytestringsetup-changed
Dependencies added: aeson, base, base64-bytestring, bytestring, containers, crypto-pubkey-openssh, crypto-pubkey-types, crypto-simple, cryptonite, directory, hashable, memory, mtl, pem, text, time, transformers, wreq
Files
- LICENSE +30/−0
- README.md +32/−0
- Setup.hs +2/−0
- api-yoti.cabal +52/−0
- src/Api.hs +89/−0
- test/Spec.hs +19/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Sergey Bushnyak (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Sergey Bushnyak nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,32 @@+# Haskell client for Yoti++Haskell client https://yoti.com+++## Integration++### With Elm++### With PureScript++## Testing++### Basic functionality++### Servant Integration++Test folder contains minimalistic servant app that handled all Yoti related methods, as an example of Yoti Haskell SDK integrated into web service.++To run, move to `test/servant`, build app++```+stack build+```++and run with++```+stack exec -- yoti-servant-api -p 3000 -d+```++open `index.html` and it will handle localhost redirections when you used Yoti mobile application for verification
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ api-yoti.cabal view
@@ -0,0 +1,52 @@+name: api-yoti+version: 0.1.0.0+synopsis: Api bindings for Yoti services+description: Api bindings for https://www.yoti.com/ digital identity service+homepage: https://github.com/sigrlami/api-yoti#readme+license: MIT+license-file: LICENSE+author: Sergey Bushnyak+maintainer: sergey.bushnyak@sigrlami.eu+copyright: Copyright: (c) 2018 Kelecorix Inc., Sergey Bushnyak+category: Web+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: Api+ build-depends: base >= 4.7 && < 5+ , bytestring+ , cryptonite+ , crypto-simple+ , crypto-pubkey-openssh+ , crypto-pubkey-types+ , text+ , aeson+ , mtl+ , transformers+ , containers+ , time+ , memory+ , wreq+ , pem+ , hashable+ , directory+ , base64-bytestring++ default-language: Haskell2010++test-suite yoti-test+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Spec.hs+ build-depends: base+ , bytestring+ , text+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/sigrlami/api-yoti
+ src/Api.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Api+ ( getProfileActivity+ ) where++import Control.Monad.IO.Class+import Crypto.Cipher.AES (AES256)+import Crypto.Cipher.Types (BlockCipher (..), Cipher (..),+ IV, KeySizeSpecifier (..),+ cipherInit, ctrCombine, makeIV,+ nullIV)+import Crypto.Error (CryptoError, CryptoFailable (..),+ eitherCryptoError)+import Crypto.PubKey.OpenSsh (OpenSshPrivateKey (..),+ decodePrivate, encodePrivate)+import qualified Crypto.PubKey.OpenSsh.Decode as D+import qualified Crypto.PubKey.OpenSsh.Types as T+import Crypto.PubKey.RSA (PrivateKey (..), PublicKey (..),+ generate)+import Crypto.PubKey.RSA.PKCS15+import qualified Crypto.Random.Types as CRT+import qualified Crypto.Simple.CBC as SC+import qualified Crypto.Types.PubKey.RSA as CRSA+import Data.ByteArray (ByteArray)+import qualified Data.ByteString as B+import qualified Data.ByteString.Base64 as BBS64+import qualified Data.ByteString.Char8 as BS+import Data.Hashable+import Data.Maybe+import Data.PEM+import qualified Data.Text as T+import GHC.Generics+import System.Directory++----------------------------------------------------------------------------------++endpoint = "https://api.yoti.com/api/v1"+authKeyHeader = "X-Yoti-Auth-Key"+digestHeader = "X-Yoti-Auth-Digest"+sdkHeader = "X-Yoti-SDK"++----------------------------------------------------------------------------------++getProfileActivity :: BS.ByteString+ -> String+ -> IO ()+getProfileActivity token pathToKeyPair = do+ privKeyE <- readPemRsaKey' pathToKeyPair -- by default: test/keys/test.pem+ case privKeyE of+ Left error -> do+ putStrLn $ " | ERR: " ++ error+ return $ ()+ Right privKey -> do+ putStrLn $ show $ privKey+ let tknE = BBS64.decode token+ case tknE of+ Left err -> do+ putStrLn $ " | ERR: " ++ (err)+ Right tkn -> do+ let decryptedMsg = decrypt Nothing privKey tkn+ case decryptedMsg of+ Left err -> putStrLn $ " | ERR: " ++ (show $ err)+ Right msg -> do+ putStrLn $ show $ msg+ return $ ()+++-- |Read private RSA Key in PEM format+readPemRsaKey' :: MonadIO m => FilePath -- ^file path to read key from; must be PEM+ -> m (Either String PrivateKey)+readPemRsaKey' path = do+ exists <- liftIO $ doesFileExist path+ case exists of+ False -> return $ Left $ "File not found!"+ True -> do+ eKey <- liftIO $ D.decodePrivate <$> B.readFile path+ return $ case eKey of+ Right (T.OpenSshPrivateKeyRsa k) -> Right k+ Right other -> Left " | Not RSA"+ Left err -> Left $ " | " ++ ( show $ err)++main :: IO ()+main =+ putStrLn "--"
+ test/Spec.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE OverloadedStrings #-}++module Spec where++import Control.Concurrent (forkIO, threadDelay)+import Control.Concurrent.STM.TVar+import Control.Monad (forever)+import qualified Data.Text as T+import Data.Time.Clock+import System.Environment++import Yoti++--------------------------------------------------------------------------------+++main :: IO ()+main =+ putStrLn "--"