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
Next Next commit
WIP hash
  • Loading branch information
vks4git committed Apr 14, 2024
commit 279914c48b11ac51bc7fe932d084e8dcd3d99898
2 changes: 1 addition & 1 deletion .stylish-haskell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ steps:
# Set this to null to disable all line wrapping.
#
# Default: 80.
columns: null
columns: 120 # null

# By default, line endings are converted according to the OS. You can override
# preferred format here.
Expand Down
3 changes: 3 additions & 0 deletions src/ZkFold/Base/Algebra/Basic/Field.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ residue = (`mod` fromIntegral (value @p))
toZp :: forall p . KnownNat p => Integer -> Zp p
toZp = Zp . residue @p

instance ToConstant (Zp p) Natural where
toConstant = fromZp

instance KnownNat p => Finite (Zp p) where
type Order (Zp p) = p

Expand Down
3 changes: 3 additions & 0 deletions src/ZkFold/Symbolic/Algorithms/Hash.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module ZkFold.Symbolic.Algorithms.Hash () where


1 change: 1 addition & 0 deletions src/ZkFold/Symbolic/Algorithms/Hash/MiMC.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module ZkFold.Symbolic.Algorithms.Hash.MiMC () where
195 changes: 195 additions & 0 deletions src/ZkFold/Symbolic/Algorithms/Hash/SHA2.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

module ZkFold.Symbolic.Algorithms.Hash.SHA2 (sha2) where

import Control.Monad (forM_)
import qualified Data.STRef as ST
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import GHC.TypeLits (Symbol)
import GHC.TypeNats (Div, Natural, type (*), type (+), type (-))
import Prelude (Int, id, pure, undefined, zip, ($), (>>=))
import qualified Prelude as P

import ZkFold.Base.Algebra.Basic.Class
import ZkFold.Symbolic.Algorithms.Hash.SHA2.Constants (sha224InitialHashes, sha256InitialHashes,
sha384InitialHashes, sha512InitialHashes,
word32RoundConstants, word64RoundConstants)
import ZkFold.Symbolic.Data.Bool (BoolType (..))
import ZkFold.Symbolic.Data.ByteString (Append (..), ByteString (..), ShiftBits (..),
ToWords (..), Truncate (..))

class AlgorithmSetup (algorithm :: Symbol) a where
TurtlePU marked this conversation as resolved.
Show resolved Hide resolved
type WordSize algorithm :: Natural
type ChunkSize algorithm :: Natural
type ResultSize algorithm :: Natural
initialHashes :: V.Vector (ByteString (WordSize algorithm) a)
roundConstants :: V.Vector (ByteString (WordSize algorithm) a)
truncateResult :: ByteString (8 * WordSize algorithm) a -> ByteString (ResultSize algorithm) a
sigmaShifts :: (Natural, Natural, Natural, Natural, Natural, Natural)
sumShifts :: (Natural, Natural, Natural, Natural, Natural, Natural)

instance (Finite a, FromConstant Natural a) => AlgorithmSetup "SHA256" a where
type WordSize "SHA256" = 32
type ChunkSize "SHA256" = 512
type ResultSize "SHA256" = 256
initialHashes = sha256InitialHashes
roundConstants = word32RoundConstants
truncateResult = id
sigmaShifts = (7, 18, 3, 17, 19, 10)
sumShifts = (2, 13, 22, 6, 11, 25)


instance (Finite a, FromConstant Natural a, Truncate (ByteString 256 a) (ByteString 224 a)) => AlgorithmSetup "SHA224" a where
type WordSize "SHA224" = 32
type ChunkSize "SHA224" = 512
type ResultSize "SHA224" = 224
initialHashes = sha224InitialHashes
roundConstants = word32RoundConstants
truncateResult = truncate
sigmaShifts = (7, 18, 3, 17, 19, 10)
sumShifts = (2, 13, 22, 6, 11, 25)

instance (Finite a, FromConstant Natural a) => AlgorithmSetup "SHA512" a where
type WordSize "SHA512" = 64
type ChunkSize "SHA512" = 1024
type ResultSize "SHA512" = 512
initialHashes = sha512InitialHashes
roundConstants = word64RoundConstants
truncateResult = id
sigmaShifts = (1, 8, 7, 19, 61, 6)
sumShifts = (28, 34, 39, 14, 18, 41)

instance (Finite a, FromConstant Natural a, Truncate (ByteString 512 a) (ByteString 384 a)) => AlgorithmSetup "SHA384" a where
type WordSize "SHA384" = 64
type ChunkSize "SHA384" = 1024
type ResultSize "SHA384" = 384
initialHashes = sha384InitialHashes
roundConstants = word64RoundConstants
truncateResult = truncate
sigmaShifts = (1, 8, 7, 19, 61, 6)
sumShifts = (28, 34, 39, 14, 18, 41)

instance (Finite a, FromConstant Natural a, Truncate (ByteString 512 a) (ByteString 224 a)) => AlgorithmSetup "SHA512/224" a where
type WordSize "SHA512/224" = 64
type ChunkSize "SHA512/224" = 1024
type ResultSize "SHA512/224" = 224
initialHashes = sha512InitialHashes
roundConstants = word64RoundConstants
truncateResult = truncate
sigmaShifts = (1, 8, 7, 19, 61, 6)
sumShifts = (28, 34, 39, 14, 18, 41)

instance (Finite a, FromConstant Natural a, Truncate (ByteString 512 a) (ByteString 256 a)) => AlgorithmSetup "SHA512/256" a where
type WordSize "SHA512/256" = 64
type ChunkSize "SHA512/256" = 1024
type ResultSize "SHA512/256" = 256
initialHashes = sha512InitialHashes
roundConstants = word64RoundConstants
truncateResult = truncate
sigmaShifts = (1, 8, 7, 19, 61, 6)
sumShifts = (28, 34, 39, 14, 18, 41)

sha2Pad :: forall (padTo :: Natural) (k :: Natural) a . ByteString k a -> ByteString (padTo * Div (padTo + k - 1) padTo) a
sha2Pad = undefined

sha2
:: forall algorithm element k
. AlgorithmSetup algorithm element
=> AdditiveSemigroup (ByteString (WordSize algorithm) element)
=> BoolType (ByteString (WordSize algorithm) element)
=> ShiftBits (ByteString (WordSize algorithm) element)
=> ToWords (ByteString (ChunkSize algorithm) element) (ByteString (WordSize algorithm) element)
=> Append (ByteString (WordSize algorithm) element) (ByteString (8 * WordSize algorithm) element)
=> ToWords (ByteString (ChunkSize algorithm * Div ((ChunkSize algorithm + k) - 1) (ChunkSize algorithm)) element) (ByteString (ChunkSize algorithm) element)
=> ByteString k element -> ByteString (ResultSize algorithm) element
sha2 messageBits = truncateResult @algorithm @element $ append $ V.toList hashParts
where
paddedMessage = sha2Pad @(ChunkSize algorithm) messageBits

chunks :: [ByteString (ChunkSize algorithm) element]
chunks = toWords paddedMessage

rounds :: Int
rounds = V.length $ roundConstants @algorithm @element

hashParts :: V.Vector (ByteString (WordSize algorithm) element)
hashParts = V.create $ do
hn <- V.thaw $ initialHashes @algorithm @element

forM_ chunks $ \chunk -> do
let words = toWords @(ByteString (ChunkSize algorithm) element) @(ByteString (WordSize algorithm) element) chunk
messageSchedule <- VM.unsafeNew @_ @(ByteString (WordSize algorithm) element) rounds
forM_ (zip [0..] words) $ \(ix, w) -> VM.write messageSchedule ix w

forM_ [16 .. rounds P.- 1] $ \ix -> do
w16 <- messageSchedule `VM.read` (ix P.- 16)
w15 <- messageSchedule `VM.read` (ix P.- 15)
w7 <- messageSchedule `VM.read` (ix P.- 7)
w2 <- messageSchedule `VM.read` (ix P.- 2)
let (sh0, sh1, sh2, sh3, sh4, sh5) = sigmaShifts @algorithm @element
s0 = (w15 `rotateBitsR` sh0) `xor` (w15 `rotateBitsR` sh1) `xor` (w15 `shiftBitsR` sh2)
s1 = (w2 `rotateBitsR` sh3) `xor` (w15 `rotateBitsR` sh4) `xor` (w15 `shiftBitsR` sh5)
VM.write messageSchedule ix $ w16 + s0 + w7 + s1

aRef <- hn `VM.read` 0 >>= ST.newSTRef
bRef <- hn `VM.read` 1 >>= ST.newSTRef
cRef <- hn `VM.read` 2 >>= ST.newSTRef
dRef <- hn `VM.read` 3 >>= ST.newSTRef
eRef <- hn `VM.read` 4 >>= ST.newSTRef
fRef <- hn `VM.read` 5 >>= ST.newSTRef
gRef <- hn `VM.read` 6 >>= ST.newSTRef
hRef <- hn `VM.read` 7 >>= ST.newSTRef

forM_ [0 .. rounds P.- 1] $ \ix -> do
a <- ST.readSTRef aRef
b <- ST.readSTRef bRef
c <- ST.readSTRef cRef
d <- ST.readSTRef dRef
e <- ST.readSTRef eRef
f <- ST.readSTRef fRef
g <- ST.readSTRef gRef
h <- ST.readSTRef hRef

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

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

ST.writeSTRef hRef g
ST.writeSTRef gRef f
ST.writeSTRef fRef e
ST.writeSTRef eRef $ d + temp1
ST.writeSTRef dRef c
ST.writeSTRef cRef b
ST.writeSTRef bRef a
ST.writeSTRef aRef $ temp1 + temp2

a <- ST.readSTRef aRef
b <- ST.readSTRef bRef
c <- ST.readSTRef cRef
d <- ST.readSTRef dRef
e <- ST.readSTRef eRef
f <- ST.readSTRef fRef
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

pure hn
69 changes: 69 additions & 0 deletions src/ZkFold/Symbolic/Algorithms/Hash/SHA2/Constants.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{-# LANGUAGE TypeApplications #-}

module ZkFold.Symbolic.Algorithms.Hash.SHA2.Constants
( sha256InitialHashes
, sha224InitialHashes
, word32RoundConstants
, sha512InitialHashes
, sha384InitialHashes
, word64RoundConstants
) where

import qualified Data.Vector as V
import GHC.TypeNats (Natural)
import Prelude (($), (<$>))

import ZkFold.Base.Algebra.Basic.Class (FromConstant (..))

sha256InitialHashes :: FromConstant Natural a => V.Vector a
sha256InitialHashes = V.fromList $ fromConstant @Natural <$>
[0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]

sha224InitialHashes :: FromConstant Natural a => V.Vector a
sha224InitialHashes = V.fromList $ fromConstant @Natural <$>
[0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]

word32RoundConstants :: FromConstant Natural a => V.Vector a
word32RoundConstants = V.fromList $ fromConstant @Natural <$>
[
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]

sha512InitialHashes :: FromConstant Natural a => V.Vector a
sha512InitialHashes = V.fromList $ fromConstant @Natural <$>
[ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
]

sha384InitialHashes :: FromConstant Natural a => V.Vector a
sha384InitialHashes = V.fromList $ fromConstant @Natural <$>
[ 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4 ]

word64RoundConstants :: FromConstant Natural a => V.Vector a
word64RoundConstants = V.fromList $ fromConstant @Natural <$>
[
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
]
6 changes: 6 additions & 0 deletions src/ZkFold/Symbolic/Data/Bool.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class BoolType b where

(||) :: b -> b -> b

xor :: b -> b -> b

instance BoolType Haskell.Bool where
true = True

Expand All @@ -33,6 +35,8 @@ instance BoolType Haskell.Bool where

(||) = (Haskell.||)

xor = xor

-- TODO (Issue #18): hide this constructor
newtype Bool x = Bool x
deriving (Eq)
Expand All @@ -50,6 +54,8 @@ instance Field x => BoolType (Bool x) where

(||) (Bool b1) (Bool b2) = Bool $ b1 + b2 - b1 * b2

xor (Bool b1) (Bool b2) = Bool $ b1 + b2 - (b1 * b2 + b1 * b2)
vlasin marked this conversation as resolved.
Show resolved Hide resolved

all :: (BoolType b, Foldable t) => (x -> b) -> t x -> b
all f = foldr ((&&) . f) true

Expand Down
Loading