{-# 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 = IO digest -> digest
forall a. IO a -> a
unsafeDupablePerformIO (IO digest -> digest) -> ([bin] -> IO digest) -> [bin] -> digest
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Key -> [bin] -> IO digest
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 = IO okm -> okm
forall a. IO a -> a
unsafeDupablePerformIO (IO okm -> okm) -> IO okm -> okm
forall a b. (a -> b) -> a -> b
$ do
(dig, _ :: BIO.Hasher) <- Proxy HASHER_SIZE -> (Ptr Hasher -> IO okm) -> IO (okm, Hasher)
forall (n :: Nat) c p a.
ByteArrayN n c =>
Proxy n -> (Ptr p -> IO a) -> IO (a, c)
forall p a. Proxy HASHER_SIZE -> (Ptr p -> IO a) -> IO (a, Hasher)
BAS.allocRet Proxy HASHER_SIZE
forall {k} (t :: k). Proxy t
Proxy ((Ptr Hasher -> IO okm) -> IO (okm, Hasher))
-> (Ptr Hasher -> IO okm) -> IO (okm, Hasher)
forall a b. (a -> b) -> a -> b
$ \Ptr Hasher
ph -> do
Ptr Hasher -> context -> IO ()
forall context.
ByteArrayAccess context =>
Ptr Hasher -> context -> IO ()
BIO.initDerive Ptr Hasher
ph context
ctx
Ptr Hasher -> [ikm] -> IO ()
forall bin. ByteArrayAccess bin => Ptr Hasher -> [bin] -> IO ()
BIO.update Ptr Hasher
ph [ikm]
ikms
Ptr Hasher -> IO okm
forall (len :: Nat) output.
ByteArrayN len output =>
Ptr Hasher -> IO output
BIO.finalize Ptr Hasher
ph
pure dig
{-# NOINLINE derive #-}
init
:: Maybe BIO.Key
-> BIO.Hasher
init :: Maybe Key -> Hasher
init Maybe Key
yk =
(Ptr Hasher -> IO ()) -> Hasher
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
BAS.allocAndFreeze ((Ptr Hasher -> IO ()) -> Hasher)
-> (Ptr Hasher -> IO ()) -> Hasher
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 =
Hasher -> (Ptr Hasher -> IO ()) -> Hasher
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 ((Ptr Hasher -> IO ()) -> Hasher)
-> (Ptr Hasher -> IO ()) -> Hasher
forall a b. (a -> b) -> a -> b
$ \Ptr Hasher
ph1 ->
Ptr Hasher -> [bin] -> IO ()
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 = IO output -> output
forall a. IO a -> a
unsafeDupablePerformIO (IO output -> output) -> IO output -> output
forall a b. (a -> b) -> a -> b
$ do
(dig, _ :: BIO.Hasher) <- Hasher -> (Ptr Hasher -> IO output) -> IO (output, 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 Ptr Hasher -> IO output
forall (len :: Nat) output.
ByteArrayN len output =>
Ptr Hasher -> IO output
BIO.finalize
pure 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 = IO output -> output
forall a. IO a -> a
unsafeDupablePerformIO (IO output -> output) -> IO output -> output
forall a b. (a -> b) -> a -> b
$ do
(dig, _ :: BIO.Hasher) <- Hasher -> (Ptr Hasher -> IO output) -> IO (output, 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 ((Ptr Hasher -> IO output) -> IO (output, Hasher))
-> (Ptr Hasher -> IO output) -> IO (output, Hasher)
forall a b. (a -> b) -> a -> b
$ \Ptr Hasher
ph -> Ptr Hasher -> Word64 -> IO output
forall (len :: Nat) output.
ByteArrayN len output =>
Ptr Hasher -> Word64 -> IO output
BIO.finalizeSeek Ptr Hasher
ph Word64
pos
pure dig
{-# NOINLINE finalizeSeek #-}