-
Notifications
You must be signed in to change notification settings - Fork 206
feat: Options for custom hash function and randomness source in MPC setup ceremonies #678
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
Open
crStiv
wants to merge
22
commits into
Consensys:master
Choose a base branch
from
crStiv:fix-issue-626
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
4c24d30
Create hash_interface.go.tmpl
crStiv 9ee67e1
Update doc.go.tmpl
crStiv 6b0b795
Create element.go
crStiv 7a69b20
Update generator_field.go
crStiv 1f579c8
Create contents.go.tmpl
crStiv 439beec
Update generate.go
crStiv 4533dd1
Create custom_options_test.go.tmpl
crStiv 4b23735
Update mpcsetup.go.tmpl
crStiv 6939b12
Create custom_random.go.tmpl
crStiv b014e15
Update hash_interface.go.tmpl
crStiv 55cf3be
Create hash_interface.go.templ
crStiv e322c13
Update multiexp.go.tmpl
crStiv fd700c4
Update marshal.go.tmpl
crStiv be30024
Update marshal.go.tmpl
crStiv 1712603
Update multiexp_jacobian.go.tmpl
crStiv bfe3de0
Update multiexp_affine.go.tmpl
crStiv f769d1d
Update multiexp.go.tmpl
crStiv b5c985a
Update mpcsetup.go
crStiv acc484d
Update element.go
crStiv 3644907
Update custom_options_test.go.tmpl
crStiv ac4a256
Update custom_random.go.tmpl
crStiv 45a2558
Update mpcsetup.go.tmpl
crStiv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package element | ||
|
||
const CustomRandom = ` | ||
// SetRandomWithSource sets z to a uniform random value in [0, q) using the provided random source. | ||
// | ||
// This might error only if reading from source errors, | ||
// in which case, value of z is undefined. | ||
func (z *{{.ElementName}}) SetRandomWithSource(source io.Reader, l, k int, b uint) (*{{.ElementName}}, error) { | ||
// l is total number of bytes needed to reconstruct z | ||
// k is the maximum byte length needed to encode a value < q | ||
// b is the number of bits in the most significant byte of q-1 | ||
|
||
var bytes [{{mul 8 .NbWords}}]byte | ||
|
||
for { | ||
// note that bytes[k:l] is always 0 | ||
if _, err := io.ReadFull(source, bytes[:k]); err != nil { | ||
return nil, err | ||
} | ||
|
||
// Clear unused bits in in the most significant byte to increase probability | ||
// that the candidate is < q. | ||
bytes[k-1] &= uint8(int(1<<b) - 1) | ||
{{- range $i := .NbWordsIndexesFull}} | ||
{{- $k := add $i 1}} | ||
z[{{$i}}] = binary.LittleEndian.{{$.Word.TypeUpper}}(bytes[{{mul $i $.Word.ByteSize}}:{{mul $k $.Word.ByteSize}}]) | ||
{{- end}} | ||
|
||
if !z.smallerThanModulus() { | ||
continue // ignore the candidate and re-sample | ||
} | ||
|
||
return z, nil | ||
} | ||
} | ||
` |
15 changes: 15 additions & 0 deletions
15
internal/generator/field/template/element/contents.go.tmpl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package element | ||
|
||
const Contents = ` | ||
element.Base | ||
element.Reduce | ||
element.Exp | ||
element.Conv | ||
element.MulDoc | ||
element.MulCIOS | ||
element.MulNoCarry | ||
element.Sqrt | ||
element.Inverse | ||
element.BigNum | ||
element.CustomRandom | ||
` |
32 changes: 32 additions & 0 deletions
32
internal/generator/field/template/element/custom_random.go.tmpl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// SetRandomWithSource sets z to a uniform random value in [0, q) using the provided random source. | ||
// | ||
// This might error only if reading from source errors, | ||
// in which case, value of z is undefined. | ||
func (z *{{.ElementName}}) SetRandomWithSource(source io.Reader, l, k int, b uint) (*{{.ElementName}}, error) { | ||
// l is total number of bytes needed to reconstruct z | ||
// k is the maximum byte length needed to encode a value < q | ||
// b is the number of bits in the most significant byte of q-1 | ||
|
||
var bytes [{{mul 8 .NbWords}}]byte | ||
|
||
for { | ||
// note that bytes[k:l] is always 0 | ||
if _, err := io.ReadFull(source, bytes[:k]); err != nil { | ||
return nil, err | ||
} | ||
|
||
// Clear unused bits in in the most significant byte to increase probability | ||
// that the candidate is < q. | ||
bytes[k-1] &= uint8(int(1<<b) - 1) | ||
{{- range $i := .NbWordsIndexesFull}} | ||
{{- $k := add $i 1}} | ||
z[{{$i}}] = binary.LittleEndian.{{$.Word.TypeUpper}}(bytes[{{mul $i $.Word.ByteSize}}:{{mul $k $.Word.ByteSize}}]) | ||
{{- end}} | ||
|
||
if !z.smallerThanModulus() { | ||
continue // ignore the candidate and re-sample | ||
} | ||
|
||
return z, nil | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,19 @@ | ||
package mpcsetup | ||
|
||
import ( | ||
"path/filepath" | ||
|
||
"github.com/consensys/bavard" | ||
"github.com/consensys/gnark-crypto/internal/generator/config" | ||
"path/filepath" | ||
) | ||
|
||
func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) error { | ||
entries := []bavard.Entry{ | ||
{File: filepath.Join(baseDir, "doc.go"), Templates: []string{"doc.go.tmpl"}}, | ||
{File: filepath.Join(baseDir, "mpcsetup.go"), Templates: []string{"mpcsetup.go.tmpl"}}, | ||
{File: filepath.Join(baseDir, "hash_interface.go"), Templates: []string{"hash_interface.go.tmpl"}}, | ||
{File: filepath.Join(baseDir, "mpcsetup_test.go"), Templates: []string{"tests/mpcsetup.go.tmpl"}}, | ||
{File: filepath.Join(baseDir, "custom_options_test.go"), Templates: []string{"tests/custom_options_test.go.tmpl"}}, | ||
} | ||
return bgen.Generate(conf, "mpcsetup", "./mpcsetup/template", entries...) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,15 @@ | ||
// Package mpcsetup provides tools for multiparty setup ceremonies for various protocols, | ||
// based on the MMPORPG paper https://eprint.iacr.org/2017/1050.pdf | ||
package mpcsetup | ||
// | ||
// The package supports customization of hash functions and randomness sources: | ||
// | ||
// To use a custom hash function: | ||
// customHashFunc := func(msg, dst []byte) (curve.G2Affine, error) { ... } | ||
// mpcsetup.ConfigureMPC(mpcsetup.WithHashToG2(customHashFunc)) | ||
// | ||
// To use a custom randomness source: | ||
// customRandomSource := func() (io.Reader, error) { ... } | ||
// mpcsetup.ConfigureMPC(mpcsetup.WithRandomSource(customRandomSource)) | ||
// | ||
// These options can be combined and are thread-safe. | ||
package mpcsetup |
111 changes: 111 additions & 0 deletions
111
internal/generator/mpcsetup/template/hash_interface.go.tmpl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package mpcsetup | ||
|
||
import ( | ||
"crypto/rand" | ||
"io" | ||
"sync" | ||
|
||
curve "github.com/consensys/gnark-crypto/ecc/{{.Name}}" | ||
"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" | ||
) | ||
|
||
// HashToG2Func defines a custom hash function interface for MPC setup ceremonies | ||
type HashToG2Func func(msg, dst []byte) (curve.G2Affine, error) | ||
|
||
// RandomSourceFunc defines a custom random source interface for generating random values | ||
type RandomSourceFunc func() (io.Reader, error) | ||
|
||
// MPCOptions holds configuration options for MPC operations | ||
type MPCOptions struct { | ||
hashToG2Func HashToG2Func | ||
randomSourceFunc RandomSourceFunc | ||
} | ||
|
||
// defaultRandomSource returns crypto/rand.Reader as the default source of randomness | ||
func defaultRandomSource() (io.Reader, error) { | ||
return rand.Reader, nil | ||
} | ||
|
||
var ( | ||
// defaultHashToG2 uses the standard curve.HashToG2 function | ||
defaultHashToG2 = curve.HashToG2 | ||
|
||
// thread-safe global option defaults | ||
globalMPCOptions = MPCOptions{ | ||
hashToG2Func: defaultHashToG2, | ||
randomSourceFunc: defaultRandomSource, | ||
} | ||
|
||
// mutex to protect global options during updates | ||
optionsMutex sync.RWMutex | ||
) | ||
|
||
// MPCOption defines a function that can configure MPC options | ||
type MPCOption func(*MPCOptions) | ||
|
||
// WithHashToG2 configures a custom hash-to-G2 function for MPC operations | ||
func WithHashToG2(hashFunc HashToG2Func) MPCOption { | ||
return func(opts *MPCOptions) { | ||
opts.hashToG2Func = hashFunc | ||
} | ||
} | ||
|
||
// WithRandomSource configures a custom random source for MPC operations | ||
func WithRandomSource(randFunc RandomSourceFunc) MPCOption { | ||
return func(opts *MPCOptions) { | ||
opts.randomSourceFunc = randFunc | ||
} | ||
} | ||
|
||
// mpcHash implements HashToG2 using the configured hash function | ||
func mpcHash(msg, dst []byte) (curve.G2Affine, error) { | ||
optionsMutex.RLock() | ||
hashFunc := globalMPCOptions.hashToG2Func | ||
optionsMutex.RUnlock() | ||
|
||
return hashFunc(msg, dst) | ||
} | ||
|
||
// getRandomSource returns the configured random source | ||
func getRandomSource() (io.Reader, error) { | ||
optionsMutex.RLock() | ||
randFunc := globalMPCOptions.randomSourceFunc | ||
optionsMutex.RUnlock() | ||
|
||
return randFunc() | ||
} | ||
|
||
// ConfigureMPC applies the provided options to the global MPC configuration | ||
func ConfigureMPC(opts ...MPCOption) { | ||
optionsMutex.Lock() | ||
defer optionsMutex.Unlock() | ||
|
||
for _, opt := range opts { | ||
opt(&globalMPCOptions) | ||
} | ||
} | ||
|
||
// setElementRandom sets an fr.Element to a random value using the configured random source | ||
func setElementRandom(e *fr.Element) (*fr.Element, error) { | ||
reader, err := getRandomSource() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// l is number of limbs * 8; the number of bytes needed to reconstruct the fr.Element | ||
const l = {{ if eq .FrNbWords 6 }}48{{ else if eq .FrNbWords 5 }}40{{ else if eq .FrNbWords 4 }}32{{ else }}32{{ end }} | ||
|
||
// bitLen is the maximum bit length needed to encode a value < q | ||
const bitLen = {{ .Fr.NbBits }} | ||
|
||
// k is the maximum byte length needed to encode a value < q | ||
const k = (bitLen + 7) / 8 | ||
|
||
// b is the number of bits in the most significant byte of q-1 | ||
b := uint(bitLen % 8) | ||
if b == 0 { | ||
b = 8 | ||
} | ||
|
||
return e.SetRandomWithSource(reader, l, k, b) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use
fieldPackage.Bytes
instead of the multiplication here.