{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module BLAKE3
(
hash
, BIO.Digest(..)
, BIO.Key
, BIO.key
, derive
, BIO.Hasher
, init
, update
, finalize
, finalizeSeek
, BIO.KEY_LEN
, BIO.BLOCK_SIZE
, BIO.DEFAULT_DIGEST_LEN
)
where
import qualified Data.ByteArray as BA
import qualified Data.ByteArray.Sized as BAS
import Data.Proxy
import Data.Word
import Prelude hiding (init)
import System.IO.Unsafe (unsafeDupablePerformIO)
import qualified BLAKE3.IO as BIO
hash
:: forall len digest bin
. (BAS.ByteArrayN len digest, BA.ByteArrayAccess bin)
=> Maybe BIO.Key
-> [bin]
-> digest
hash :: forall (len :: Nat) digest bin.
(ByteArrayN len digest, ByteArrayAccess bin) =>
Maybe Key -> [bin] -> digest
hash Maybe Key
yk = forall a. IO a -> a
unsafeDupablePerformIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (len :: Nat) digest bin.
(ByteArrayN len digest, ByteArrayAccess bin) =>
Maybe Key -> [bin] -> IO digest
BIO.hash Maybe Key
yk
{-# NOINLINE hash #-}
derive
:: forall len okm ikm context
. (BAS.ByteArrayN len okm,
BA.ByteArrayAccess ikm,
BA.ByteArrayAccess context)
=> context
-> [ikm]
-> okm
derive :: forall (len :: Nat) okm ikm context.
(ByteArrayN len okm, ByteArrayAccess ikm,
ByteArrayAccess context) =>
context -> [ikm] -> okm
derive context
ctx [ikm]
ikms = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$ do
(okm
dig, Hasher
_ :: BIO.Hasher) <- forall (n :: Nat) c p a.
ByteArrayN n c =>
Proxy n -> (Ptr p -> IO a) -> IO (a, c)
BAS.allocRet forall {k} (t :: k). Proxy t
Proxy forall a b. (a -> b) -> a -> b
$ \Ptr Hasher
ph -> do
forall context.
ByteArrayAccess context =>
Ptr Hasher -> context -> IO ()
BIO.initDerive Ptr Hasher
ph context
ctx
forall bin. ByteArrayAccess bin => Ptr Hasher -> [bin] -> IO ()
BIO.update Ptr Hasher
ph [ikm]
ikms
forall (len :: Nat) output.
ByteArrayN len output =>
Ptr Hasher -> IO output
BIO.finalize Ptr Hasher
ph
forall (f :: * -> *) a. Applicative f => a -> f a
pure okm
dig
{-# NOINLINE derive #-}
init
:: Maybe BIO.Key
-> BIO.Hasher
init :: Maybe Key -> Hasher
init Maybe Key
yk =
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
BAS.allocAndFreeze forall a b. (a -> b) -> a -> b
$ \Ptr Hasher
ph ->
Ptr Hasher -> Maybe Key -> IO ()
BIO.init Ptr Hasher
ph Maybe Key
yk
update
:: forall bin
. BA.ByteArrayAccess bin
=> BIO.Hasher
-> [bin]
-> BIO.Hasher
update :: forall bin. ByteArrayAccess bin => Hasher -> [bin] -> Hasher
update Hasher
h0 [bin]
bins =
forall (n :: Nat) bs1 bs2 p.
(ByteArrayN n bs1, ByteArrayN n bs2, ByteArrayAccess bs1,
KnownNat n) =>
bs1 -> (Ptr p -> IO ()) -> bs2
BAS.copyAndFreeze Hasher
h0 forall a b. (a -> b) -> a -> b
$ \Ptr Hasher
ph1 ->
forall bin. ByteArrayAccess bin => Ptr Hasher -> [bin] -> IO ()
BIO.update Ptr Hasher
ph1 [bin]
bins
finalize
:: forall len output
. BAS.ByteArrayN len output
=> BIO.Hasher
-> output
finalize :: forall (len :: Nat) output.
ByteArrayN len output =>
Hasher -> output
finalize Hasher
h0 = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$ do
(output
dig, Hasher
_ :: BIO.Hasher) <- forall (n :: Nat) bs1 bs2 p a.
(ByteArrayN n bs1, ByteArrayN n bs2, ByteArrayAccess bs1,
KnownNat n) =>
bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
BAS.copyRet Hasher
h0 forall (len :: Nat) output.
ByteArrayN len output =>
Ptr Hasher -> IO output
BIO.finalize
forall (f :: * -> *) a. Applicative f => a -> f a
pure output
dig
{-# NOINLINE finalize #-}
finalizeSeek
:: forall len output
. BAS.ByteArrayN len output
=> BIO.Hasher
-> Word64
-> output
finalizeSeek :: forall (len :: Nat) output.
ByteArrayN len output =>
Hasher -> Word64 -> output
finalizeSeek Hasher
h0 Word64
pos = forall a. IO a -> a
unsafeDupablePerformIO forall a b. (a -> b) -> a -> b
$ do
(output
dig, Hasher
_ :: BIO.Hasher) <- forall (n :: Nat) bs1 bs2 p a.
(ByteArrayN n bs1, ByteArrayN n bs2, ByteArrayAccess bs1,
KnownNat n) =>
bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
BAS.copyRet Hasher
h0 forall a b. (a -> b) -> a -> b
$ \Ptr Hasher
ph -> forall (len :: Nat) output.
ByteArrayN len output =>
Ptr Hasher -> Word64 -> IO output
BIO.finalizeSeek Ptr Hasher
ph Word64
pos
forall (f :: * -> *) a. Applicative f => a -> f a
pure output
dig
{-# NOINLINE finalizeSeek #-}