Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vks4git hash #80

Merged
merged 11 commits into from
Apr 15, 2024
Prev Previous commit
Next Next commit
Bytestring summation via UInt; removed unnecessary constraints; fixed…
… a typo
  • Loading branch information
vks4git committed Apr 14, 2024
commit 4949d83501e8dded0a7f609b70fecb2dd06fcf42
50 changes: 29 additions & 21 deletions src/ZkFold/Symbolic/Algorithms/Hash/SHA2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import ZkFold.Symbolic.Algorithms.Hash.SHA2.Constants (sha224InitialHa
import ZkFold.Symbolic.Data.Bool (BoolType (..))
import ZkFold.Symbolic.Data.ByteString (ByteString (..), Concat (..), Extend (..),
ShiftBits (..), ToWords (..), Truncate (..))
import ZkFold.Symbolic.Data.Combinators (Iso (..))
import ZkFold.Symbolic.Data.UInt (UInt)

-- | SHA2 is a family of hashing functions with almost identical implementations but different constants and parameters.
-- This class links these varying parts with the appropriate algorithm.
Expand Down Expand Up @@ -150,12 +152,14 @@ type SHA2 algorithm element k =
, KnownNat (ChunkSize algorithm)
, KnownNat (WordSize algorithm)
, KnownNat (PaddedLength k (ChunkSize algorithm) (2 * WordSize algorithm))
, AdditiveSemigroup (ByteString (WordSize algorithm) element)
, Iso (UInt (WordSize algorithm) element) (ByteString (WordSize algorithm) element)
, Iso (ByteString (WordSize algorithm) element) (UInt (WordSize algorithm) element)
, AdditiveSemigroup (UInt (WordSize algorithm) element)
, BoolType (ByteString (WordSize algorithm) element)
, ShiftBits (ByteString (WordSize algorithm) element)
, ShiftBits (ByteString (PaddedLength k (ChunkSize algorithm) (2 * WordSize algorithm)) element)
, BoolType (ByteString (PaddedLength k (ChunkSize algorithm) (2 * WordSize algorithm)) element)
, Extend (ByteString k element) (ByteString (PaddedLength k (ChunkSize algorithm) (2 * WordSize algorithm)) element)
, AdditiveSemigroup (ByteString (PaddedLength k (ChunkSize algorithm) (2 * WordSize algorithm)) element)
, ToWords (ByteString (ChunkSize algorithm) element) (ByteString (WordSize algorithm) element)
, Concat (ByteString (WordSize algorithm) element) (ByteString (8 * WordSize algorithm) element)
, ToWords (ByteString (PaddedLength k (ChunkSize algorithm) (2 * WordSize algorithm)) element) (ByteString (ChunkSize algorithm) element)
Expand All @@ -180,17 +184,18 @@ sha2 messageBits = sha2Blocks @algorithm @element chunks
chunks = toWords paddedMessage

-- | Pad the input bytestring according to the rules described in @PaddedLength@
--
sha2Pad
:: forall (padTo :: Natural) (lenBits :: Natural) (k :: Natural) element
. KnownNat k
=> KnownNat (PaddedLength k padTo lenBits)
=> Finite element
=> FromConstant Natural element
=> ShiftBits (ByteString (PaddedLength k padTo lenBits) element)
=> AdditiveSemigroup (ByteString (PaddedLength k padTo lenBits) element)
=> BoolType (ByteString (PaddedLength k padTo lenBits) element)
=> Extend (ByteString k element) (ByteString (PaddedLength k padTo lenBits) element)
=> ByteString k element -> ByteString (PaddedLength k padTo lenBits) element
sha2Pad bs = grown + fromConstant padValue
sha2Pad bs = grown || fromConstant padValue
where
l :: Natural
l = natVal $ Proxy @k
Expand Down Expand Up @@ -229,7 +234,9 @@ type SHA2N algorithm element =
, FromConstant Natural element
, KnownNat (ChunkSize algorithm)
, KnownNat (WordSize algorithm)
, AdditiveSemigroup (ByteString (WordSize algorithm) element)
, Iso (UInt (WordSize algorithm) element) (ByteString (WordSize algorithm) element)
, Iso (ByteString (WordSize algorithm) element) (UInt (WordSize algorithm) element)
, AdditiveSemigroup (UInt (WordSize algorithm) element)
, BoolType (ByteString (WordSize algorithm) element)
, ShiftBits (ByteString (WordSize algorithm) element)
, ToWords (ByteString (ChunkSize algorithm) element) (ByteString (WordSize algorithm) element)
Expand Down Expand Up @@ -271,14 +278,15 @@ sha2Natural numBits messageBits = sha2Blocks @algorithm @element chunks

-- | Internal loop of the SHA2 family algorithms.
--
-- A note on @force@: it is really necessary, otherwise the algorithm keeps piling up thunks.
-- A note on @force@: it is really necessary, otherwise the algorithm keeps piling up thunks.
-- Even 16 GB of RAM is not enough.
--
sha2Blocks
:: forall algorithm element
. AlgorithmSetup algorithm element
=> NFData element
=> AdditiveSemigroup (ByteString (WordSize algorithm) element)
=> Iso (ByteString (WordSize algorithm) element) (UInt (WordSize algorithm) element)
=> AdditiveSemigroup (UInt (WordSize algorithm) element)
=> BoolType (ByteString (WordSize algorithm) element)
=> ShiftBits (ByteString (WordSize algorithm) element)
=> ToWords (ByteString (ChunkSize algorithm) element) (ByteString (WordSize algorithm) element)
Expand Down Expand Up @@ -306,7 +314,7 @@ sha2Blocks chunks = truncateResult @algorithm @element $ concat $ V.toList hashP
let (sh0, sh1, sh2, sh3, sh4, sh5) = sigmaShifts @algorithm @element
s0 = force $ (w15 `rotateBitsR` sh0) `xor` (w15 `rotateBitsR` sh1) `xor` (w15 `shiftBitsR` sh2)
s1 = force $ (w2 `rotateBitsR` sh3) `xor` (w2 `rotateBitsR` sh4) `xor` (w2 `shiftBitsR` sh5)
VM.write messageSchedule ix $! w16 + s0 + w7 + s1
VM.write messageSchedule ix $! from (from w16 + from s0 + from w7 + from s1 :: UInt (WordSize algorithm) element)

!aRef <- hn `VM.read` 0 >>= ST.newSTRef
!bRef <- hn `VM.read` 1 >>= ST.newSTRef
Expand All @@ -327,25 +335,25 @@ sha2Blocks chunks = truncateResult @algorithm @element $ concat $ V.toList hashP
!g <- ST.readSTRef gRef
!h <- ST.readSTRef hRef

let ki = roundConstants @algorithm V.! ix
let ki = roundConstants @algorithm @element V.! ix
wi <- messageSchedule `VM.read` ix

let (sh0, sh1, sh2, sh3, sh4, sh5) = sumShifts @algorithm @element
s1 = force $ (e `rotateBitsR` sh3) `xor` (e `rotateBitsR` sh4) `xor` (e `rotateBitsR` sh5)
ch = force $ (e && f) `xor` (not e && g)
temp1 = force $ h + s1 + ch + ki + wi
temp1 = force $ from (from h + from s1 + from ch + from ki + from wi :: UInt (WordSize algorithm) element) :: ByteString (WordSize algorithm) element
s0 = force $ (a `rotateBitsR` sh0) `xor` (a `rotateBitsR` sh1) `xor` (a `rotateBitsR` sh2)
maj = force $ (a && b) `xor` (a && c) `xor` (b && c)
temp2 = force $ s0 + maj
temp2 = force $ from (from s0 + from maj :: UInt (WordSize algorithm) element) :: ByteString (WordSize algorithm) element

ST.writeSTRef hRef g
ST.writeSTRef gRef f
ST.writeSTRef fRef e
ST.writeSTRef eRef $ d + temp1
ST.writeSTRef eRef $ from (from d + from temp1 :: UInt (WordSize algorithm) element)
ST.writeSTRef dRef c
ST.writeSTRef cRef b
ST.writeSTRef bRef a
ST.writeSTRef aRef $ temp1 + temp2
ST.writeSTRef aRef $ from (from temp1 + from temp2 :: UInt (WordSize algorithm) element)

!a <- ST.readSTRef aRef
!b <- ST.readSTRef bRef
Expand All @@ -356,13 +364,13 @@ sha2Blocks chunks = truncateResult @algorithm @element $ concat $ V.toList hashP
!g <- ST.readSTRef gRef
!h <- ST.readSTRef hRef

VM.modify hn (+a) 0
VM.modify hn (+b) 1
VM.modify hn (+c) 2
VM.modify hn (+d) 3
VM.modify hn (+e) 4
VM.modify hn (+f) 5
VM.modify hn (+g) 6
VM.modify hn (+h) 7
VM.modify hn (\w -> from (from w + from a :: UInt (WordSize algorithm) element)) 0
VM.modify hn (\w -> from (from w + from b :: UInt (WordSize algorithm) element)) 1
VM.modify hn (\w -> from (from w + from c :: UInt (WordSize algorithm) element)) 2
VM.modify hn (\w -> from (from w + from d :: UInt (WordSize algorithm) element)) 3
VM.modify hn (\w -> from (from w + from e :: UInt (WordSize algorithm) element)) 4
VM.modify hn (\w -> from (from w + from f :: UInt (WordSize algorithm) element)) 5
VM.modify hn (\w -> from (from w + from g :: UInt (WordSize algorithm) element)) 6
VM.modify hn (\w -> from (from w + from h :: UInt (WordSize algorithm) element)) 7

pure hn
Loading