{-# LANGUAGE TypeApplications #-}
module Sel.Scrypt
(
ScryptHash
, scryptHashPassword
, scryptVerifyPassword
, scryptHashToByteString
, scryptHashToText
, asciiTextToScryptHash
, asciiByteStringToScryptHash
)
where
import Control.Monad (void)
import Data.ByteString (StrictByteString)
import qualified Data.ByteString.Internal as BS
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.Text as Text
import Data.Text.Display
import qualified Data.Text.Encoding as Text
import qualified Data.Text.Lazy.Builder as Builder
import Foreign hiding (void)
import Foreign.C
import LibSodium.Bindings.Scrypt
import Sel.Internal
import System.IO.Unsafe (unsafeDupablePerformIO)
newtype ScryptHash = ScryptHash (ForeignPtr CChar)
instance Eq ScryptHash where
(ScryptHash ForeignPtr CChar
sh1) == :: ScryptHash -> ScryptHash -> Bool
== (ScryptHash ForeignPtr CChar
sh2) =
IO Bool -> Bool
forall a. IO a -> a
unsafeDupablePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
ForeignPtr CChar -> ForeignPtr CChar -> CSize -> IO Bool
forall a. ForeignPtr a -> ForeignPtr a -> CSize -> IO Bool
foreignPtrEq ForeignPtr CChar
sh1 ForeignPtr CChar
sh2 CSize
cryptoPWHashScryptSalsa208SHA256StrBytes
instance Ord ScryptHash where
compare :: ScryptHash -> ScryptHash -> Ordering
compare (ScryptHash ForeignPtr CChar
sh1) (ScryptHash ForeignPtr CChar
sh2) =
IO Ordering -> Ordering
forall a. IO a -> a
unsafeDupablePerformIO (IO Ordering -> Ordering) -> IO Ordering -> Ordering
forall a b. (a -> b) -> a -> b
$
ForeignPtr CChar -> ForeignPtr CChar -> CSize -> IO Ordering
forall a. ForeignPtr a -> ForeignPtr a -> CSize -> IO Ordering
foreignPtrOrd ForeignPtr CChar
sh1 ForeignPtr CChar
sh2 CSize
cryptoPWHashScryptSalsa208SHA256StrBytes
instance Show ScryptHash where
show :: ScryptHash -> String
show = Text -> String
Text.unpack (Text -> String) -> (ScryptHash -> Text) -> ScryptHash -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScryptHash -> Text
scryptHashToText
instance Display ScryptHash where
displayBuilder :: ScryptHash -> Builder
displayBuilder = Text -> Builder
Builder.fromText (Text -> Builder) -> (ScryptHash -> Text) -> ScryptHash -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScryptHash -> Text
scryptHashToText
scryptHashPassword :: StrictByteString -> IO ScryptHash
scryptHashPassword :: StrictByteString -> IO ScryptHash
scryptHashPassword StrictByteString
bytestring = do
StrictByteString -> (CStringLen -> IO ScryptHash) -> IO ScryptHash
forall a. StrictByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen StrictByteString
bytestring ((CStringLen -> IO ScryptHash) -> IO ScryptHash)
-> (CStringLen -> IO ScryptHash) -> IO ScryptHash
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
cString, Int
cStringLen) -> do
ForeignPtr CChar
hashForeignPtr <- Int -> IO (ForeignPtr CChar)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
cryptoPWHashScryptSalsa208SHA256StrBytes)
ForeignPtr CChar -> (Ptr CChar -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CChar
hashForeignPtr ((Ptr CChar -> IO ()) -> IO ()) -> (Ptr CChar -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
hashPtr ->
IO CInt -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$
Ptr CChar -> Ptr CChar -> CULLong -> CULLong -> CSize -> IO CInt
cryptoPWHashScryptSalsa208SHA256Str
Ptr CChar
hashPtr
Ptr CChar
cString
(Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
cStringLen)
(CSize -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
cryptoPWHashScryptSalsa208SHA256OpsLimitInteractive)
CSize
cryptoPWHashScryptSalsa208SHA256MemLimitInteractive
ScryptHash -> IO ScryptHash
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ScryptHash -> IO ScryptHash) -> ScryptHash -> IO ScryptHash
forall a b. (a -> b) -> a -> b
$ ForeignPtr CChar -> ScryptHash
ScryptHash ForeignPtr CChar
hashForeignPtr
scryptVerifyPassword :: StrictByteString -> ScryptHash -> IO Bool
scryptVerifyPassword :: StrictByteString -> ScryptHash -> IO Bool
scryptVerifyPassword StrictByteString
bytestring (ScryptHash ForeignPtr CChar
sh) = do
StrictByteString -> (CStringLen -> IO Bool) -> IO Bool
forall a. StrictByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen StrictByteString
bytestring ((CStringLen -> IO Bool) -> IO Bool)
-> (CStringLen -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
cString, Int
cStringLen) -> do
ForeignPtr CChar -> (Ptr CChar -> IO Bool) -> IO Bool
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CChar
sh ((Ptr CChar -> IO Bool) -> IO Bool)
-> (Ptr CChar -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
scryptHash -> do
CInt
result <-
Ptr CChar -> Ptr CChar -> CULLong -> IO CInt
cryptoPWHashScryptSalsa208SHA256StrVerify
Ptr CChar
scryptHash
Ptr CChar
cString
(Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
cStringLen)
Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt
result CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0)
scryptHashToByteString :: ScryptHash -> StrictByteString
scryptHashToByteString :: ScryptHash -> StrictByteString
scryptHashToByteString (ScryptHash ForeignPtr CChar
fPtr) =
ForeignPtr Word8 -> Int -> StrictByteString
BS.fromForeignPtr0 (ForeignPtr CChar -> ForeignPtr Word8
forall a b. ForeignPtr a -> ForeignPtr b
Foreign.castForeignPtr ForeignPtr CChar
fPtr) (forall a b. (Integral a, Num b) => a -> b
fromIntegral @CSize @Int CSize
cryptoPWHashScryptSalsa208SHA256StrBytes)
scryptHashToText :: ScryptHash -> Text
scryptHashToText :: ScryptHash -> Text
scryptHashToText = StrictByteString -> Text
Text.decodeASCII (StrictByteString -> Text)
-> (ScryptHash -> StrictByteString) -> ScryptHash -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScryptHash -> StrictByteString
scryptHashToByteString
asciiByteStringToScryptHash :: StrictByteString -> ScryptHash
asciiByteStringToScryptHash :: StrictByteString -> ScryptHash
asciiByteStringToScryptHash StrictByteString
textualHash =
let (ForeignPtr Word8
fPtr, Int
_length) = StrictByteString -> (ForeignPtr Word8, Int)
BS.toForeignPtr0 StrictByteString
textualHash
in ForeignPtr CChar -> ScryptHash
ScryptHash (forall a b. ForeignPtr a -> ForeignPtr b
castForeignPtr @Word8 @CChar ForeignPtr Word8
fPtr)
asciiTextToScryptHash :: Text -> ScryptHash
asciiTextToScryptHash :: Text -> ScryptHash
asciiTextToScryptHash = StrictByteString -> ScryptHash
asciiByteStringToScryptHash (StrictByteString -> ScryptHash)
-> (Text -> StrictByteString) -> Text -> ScryptHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> StrictByteString
Text.encodeUtf8