Skip to content

Commit

Permalink
Working on rescue and other hash implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
samuael committed Oct 17, 2024
1 parent 2ca31f1 commit b3eea17
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 31 deletions.
207 changes: 207 additions & 0 deletions internal/utils/hash/rescue_hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package hash

import (
"crypto/cipher"
"encoding/binary"
"errors"
"fmt"
"log"
"math/big"

"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/chacha20poly1305"
)

const PAD_MSG_BEFORE_HASH_BITS_LEN = 736

func RescueHashTransactionMsg(message *big.Int) (interface{}, error) {
// msgBits := BytesIntoBits(message)

Check failure on line 18 in internal/utils/hash/rescue_hash.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)
if len(message.Bits()) <= PAD_MSG_BEFORE_HASH_BITS_LEN {
return nil, errors.New("invalid message")
}
// bits := BytesIntoBits(message.Bytes())

Check failure on line 22 in internal/utils/hash/rescue_hash.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)
return nil, nil
}

func BytesIntoBits(message []byte) []bool {
msg := make([]bool, len(message)*8)
for _, b := range message {
x := b
for i := range 8 {
msg = append(msg, (x&(1<<i)) != 0)
}
}
return msg
}

// PackBitsIntoBytes packas slice of bool to slice of bytes
func PackBitsIntoBytes(bits []bool) []byte {
if len(bits)%8 > 0 {
bits = append(make([]bool, 8-(len(bits)%8)), bits...)
}
bytesMsg := make([]byte, int64(float64(len(bits)/8)))
start := 0
for i := 0; i < len(bits); i += 8 {
var val uint8
for _, b := range bits[start : i+8] {
if b {
val |= 1
}
}
start += 8
bytesMsg = append(bytesMsg, byte(val))
}
return bytesMsg
}

func RescueHashFr(input []bool) *big.Int {
// packed := ComputeMultiPacking(input)

Check failure on line 58 in internal/utils/hash/rescue_hash.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)
// spotgeOutput := RescueHash()
return nil
}

func ComputeMultiPacking(input []bool) []*big.Int {
if len(input)%8 > 0 {
input = append(make([]bool, 8-(len(input)%8)), input...)
}
result := []*big.Int{}
start := 0
for i := 0; i < len(input); i += 8 {
cur := big.NewInt(0)
coeff := big.NewInt(1)

sample := input[start : i+8]

for _, b := range sample {
if b {
cur.Add(cur, coeff)
}
coeff.Mul(coeff, coeff)
}
result = append(result, cur)
start += 8
}
return result
}

func (b *Bn256RescueParams) NewCheck2Into1() (*Bn256RescueParams, error) {
c := uint32(1)
r := uint32(2)
round := uint32(22)
securityLevel := uint32(12)
return b.NewForParams(c, r, round, securityLevel)
}

func (b *Bn256RescueParams) NewForParams(c, r, rounds, securityLevel uint32) (*Bn256RescueParams, error) {
stateWidth := c + r
numRoundConstants := int((1 + rounds*2) * stateWidth)

roundConstants, err := func() ([]*big.Int, error) {
tag := []byte("Rescue_f")
roundConstants := make([]*big.Int, numRoundConstants)
nonce := uint32(0)
var nonceBytes []byte

for {
binary.BigEndian.PutUint32(nonceBytes[:], nonce)

Check failure on line 106 in internal/utils/hash/rescue_hash.go

View workflow job for this annotation

GitHub Actions / lint

unslice: could simplify nonceBytes[:] to nonceBytes (gocritic)
hasher, err := blake2s.New256(nil)
if err != nil {
return nil, err
}
// nonceBytes = []byte()

Check failure on line 111 in internal/utils/hash/rescue_hash.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)
hasher.Write(tag)
hasher.Write(GH_FIRST_BLOCK)
hasher.Write(nonceBytes)

hashData := hasher.Sum(nil)
if len(hashData) != 32 {
return nil, fmt.Errorf("expecting a hash length of 32 bytes, got a hash with length %d", len(hashData))
}

constantRepr := big.NewInt(0).SetBytes(hashData)
constant := constantRepr
if constant.Cmp(big.NewInt(0)) != 0 {
roundConstants = append(roundConstants, constant)
}

if len(roundConstants) == numRoundConstants {
break
}
nonce += 1
}
return roundConstants, nil
}()
if err != nil {
return nil, err
}

mdsMatrix, err := func() ([]*big.Int, error) {
// This tag is a first one in a sequence of b"ResMxxxx"
// that produces MDS matrix without eigenvalues for rate = 2,
// capacity = 1 variant over Bn254 curve
tag := []byte("ResM0003")
rng, err := func() (cipher.AEAD, error) {
hasher, err := blake2s.New256(nil)
if err != nil {
return nil, err
}
// nonceBytes = []byte()

Check failure on line 148 in internal/utils/hash/rescue_hash.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)
hasher.Write(tag)
hasher.Write(GH_FIRST_BLOCK)
hashData := hasher.Sum(nil)
if len(hashData) != 32 {
return nil, fmt.Errorf("expecting a hash length of 32 bytes, got a hash with length %d", len(hashData))
}
var seed [8]uint32
if len(hashData) < 32 {
return nil, errors.New("digest is not large enough")
}
// Populate the seed array from the byte slice
for i := 0; i < 8; i++ {
seed[i] = binary.BigEndian.Uint32(hashData[i*4 : i*4+4])
}

// Convert uint32 array to a byte slice for the seed
var byteSeed []byte
buf := make([]byte, 4)
for _, v := range seed {
binary.BigEndian.PutUint32(buf, v)
byteSeed = append(byteSeed, buf...)
}

// Create a ChaCha20-Poly1305 cipher
aead, err := chacha20poly1305.NewX(byteSeed)
if err != nil {
log.Fatal("failed to create cipher:", err)
}
return aead, nil
}()
if err != nil {
return nil, err
}
// return rng, nil
//
// TODO: ...
// generatemdsMatrix()
println(rng)
return nil, nil
}()
return &Bn256RescueParams{
C: c,
R: r,
Rounds: rounds,
SecurityLevel: securityLevel,
RoundConstants: roundConstants,
MDSMatrix: mdsMatrix,
CustomGatesAllowed: false,
}, nil
}

type PowerSBox struct {
Power *big.Int
Inv uint64
}

type QuinticSBox struct {
Marker *big.Int
}
1 change: 1 addition & 0 deletions internal/utils/hash/rescue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package hash
20 changes: 20 additions & 0 deletions internal/utils/hash/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ package hash

import "math/big"

// / First 64 bytes of the BLAKE2s input during group hash.
// / This is chosen to be some random string that we couldn't have anticipated when we designed
// / the algorithm, for rigidity purposes.
// / We deliberately use an ASCII hex string of 32 bytes here.
var GH_FIRST_BLOCK = []byte("096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0")

// PedersenCfg represents a pedersen hash configuration options
type PedersenCfg struct {
Comment string `json:"_comment"`
Expand All @@ -12,3 +18,17 @@ type PedersenCfg struct {
BETA *big.Int `json:"BETA"`
ConstantPoints [][2]*big.Int `json:"CONSTANT_POINTS"`
}

// Bn256RescueParams represents capacity, rate of hash, and other details of the rescue hash algorithm
type Bn256RescueParams struct {
C uint32
R uint32
Rounds uint32
SecurityLevel uint32
RoundConstants []*big.Int
MDSMatrix []*big.Int
SBox0 *PowerSBox
SBox1 *QuinticSBox

CustomGatesAllowed bool
}
26 changes: 25 additions & 1 deletion internal/utils/jubjub/jubjub.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,31 @@ type AltJubJubBn256 struct {
Montgometry2A *big.Int
Scale *big.Int

// PedersenHashGenerators
PedersenHashGenerators []interface{}
PedersenHashExp []interface{}
PedersenCircuitGenerators []interface{}
FixedBaseGenerators []interface{}
FixedBaseCircuitGenerators []interface{}
}

func NewAltJubJubBn256() *AltJubJubBn256 {
edwardsD, _ := big.NewInt(0).SetString("12181644023421730124874158521699555681764249180949974110617291017600649128846", 0)
montegomeryA := big.NewInt(168698)

doubleMontgomery2A := new(big.Int).Mul(montegomeryA, montegomeryA)
scale, _ := big.NewInt(0).SetString("6360561867910373094066688120553762416144456282423235903351243436111059670888", 0)

return &AltJubJubBn256{
MontgometryA: montegomeryA,
EdwardsD: edwardsD,
Montgometry2A: doubleMontgomery2A,
Scale: scale,
PedersenHashGenerators: make([]interface{}, 0),
PedersenHashExp: make([]interface{}, 0),
PedersenCircuitGenerators: make([]interface{}, 0),
FixedBaseGenerators: make([]interface{}, 0),
FixedBaseCircuitGenerators: make([]interface{}, 0),
}
}

// const defaultJubjubConfigsPath = "internal/utils/hash/elliptic_curve_config/"
Expand Down
20 changes: 0 additions & 20 deletions internal/utils/mathutils/math_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"math/big"
)
Expand Down Expand Up @@ -182,22 +181,3 @@ func GenerateKRfc6979(msgHash, priKey, ecOrder *big.Int, seed int) *big.Int {
}
return GenerateSecret(ecOrder, priKey, sha256.New, msgHash.Bytes(), extra)
}

const PAD_MSG_BEFORE_HASH_BITS_LEN = 736

func RescueHashTransactionMsg(message *big.Int) (interface{}, error) {
// msgBits := BytesIntoBits(message)
if len(message.Bits()) <= PAD_MSG_BEFORE_HASH_BITS_LEN {
return nil, errors.New("invalid message")
}
return nil, nil
}

func BytesIntoBits(message []byte) *big.Int {
msg := new(big.Int)
for _, b := range message {
msg.Add(msg, big.NewInt(int64(b)))
msg.Lsh(msg, 8)
}
return msg
}
10 changes: 0 additions & 10 deletions internal/utils/zklink/zklink_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,3 @@ type TransferBuilder struct {
Nonce *big.Int
Timestamp *big.Int
}

// Bn256RescueParams
type Bn256RescueParams struct {
C uint64
R uint64
Rounds uint64
SecurityLevel uint64

CustomGatesAllowed bool
}

0 comments on commit b3eea17

Please sign in to comment.