pedersen

package
v0.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2024 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package pedersen allows to compute and verify Pedersen vector commitments

Pedersen vector commitments are a type of homomorphic commitments that allow to commit to a vector of values and prove knowledge of the committed values. The commitments can be batched and verified in a single operation.

The commitments are computed using a set of basis elements. The proving key contains the basis elements and their exponentiations by a random value. The verifying key contains the G2 generator and its exponentiation by the inverse of the random value.

The setup process is a trusted setup and must be done securely, preferably using MPC. After the setup, the proving key does not have to be secret, but the randomness used during the setup must be discarded.

Example (SingleProof)

This example demonstrates how to use the Pedersen commitment scheme to commit to a set of values and prove knowledge of the committed values.

Does not perform any batching or multi-proof optimization.

const nbElem = 4
// create a proving key with independent basis elements
var buf [32]byte
basis := make([]curve.G1Affine, nbElem)
for i := range basis {
	_, err := rand.Read(buf[:])
	if err != nil {
		panic(err)
	}
	// we use hash-to-curve to avoid linear dependencies between basis elements
	basis[i], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i)))
	if err != nil {
		panic(err)
	}
}
// create a proving and verifying key. NB! Must be done using MPC
pks, vk, err := Setup([][]curve.G1Affine{basis})
if err != nil {
	panic(err)
}
// currently we only have a single proving key
pk := pks[0]
toCommit := make([]fr.Element, nbElem)
for i := range toCommit {
	toCommit[i].SetRandom()
}
// commit to the values
commitment, err := pk.Commit(toCommit)
if err != nil {
	panic(err)
}
// prove knowledge of the committed values
pok, err := pk.ProveKnowledge(toCommit)
if err != nil {
	panic(err)
}
// verify the proof
if err := vk.Verify(commitment, pok); err != nil {
	panic(err)
}

fmt.Println("verified")
Output:

verified

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func BatchProve added in v0.11.2

func BatchProve(pk []ProvingKey, values [][]fr.Element, combinationCoeff fr.Element) (pok curve.G1Affine, err error)

BatchProve computes a single proof of knowledge for multiple commitments. The single PoK can be verified with a single call to VerifyingKey.Verify with folded commitments. The commitments can be folded into one using curve.G1Affine.Fold.

The argument combinationCoeff is used as a linear combination coefficient to fold separate proofs into one. It must be the same for batch proving and when folding commitments. This means that in an interactive setting, it must be randomly generated by the verifier and sent to the prover. Otherwise, it must be generated via Fiat-Shamir.

Example

This example shows how to batch the commitment and proof generation.

const nbPks = 3
const nbElem = 4
// create a proving key with independent basis elements
var buf [32]byte
basis := make([][]curve.G1Affine, nbPks)
for i := range basis {
	basis[i] = make([]curve.G1Affine, nbElem)
	for j := range basis[i] {
		_, err := rand.Read(buf[:])
		if err != nil {
			panic(err)
		}
		// we use hash-to-curve to avoid linear dependencies between basis elements
		basis[i][j], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i)))
		if err != nil {
			panic(err)
		}
	}
}
// create a proving and verifying key. NB! Must be done using MPC
pks, vk, err := Setup(basis)
if err != nil {
	panic(err)
}
// generate random values to commit to
toCommit := make([][]fr.Element, nbPks)
for i := range toCommit {
	toCommit[i] = make([]fr.Element, nbElem)
	for j := range toCommit[i] {
		toCommit[i][j].SetRandom()
	}
}
// commit to the values
commitments := make([]curve.G1Affine, nbPks)
for i := range commitments {
	commitments[i], err = pks[i].Commit(toCommit[i])
	if err != nil {
		panic(err)
	}
}
// combination coefficient is randomly sampled by the verifier. NB! In non-interactive protocol use Fiat-Shamir!
var combinationCoeff fr.Element
combinationCoeff.SetRandom()
proof, err := BatchProve(pks, toCommit, combinationCoeff)
if err != nil {
	panic(err)
}
// fold the commitments
foldedCommitment, err := new(curve.G1Affine).Fold(commitments, combinationCoeff, ecc.MultiExpConfig{NbTasks: 1})
if err != nil {
	panic(err)
}
// verify the proof
if err := vk.Verify(*foldedCommitment, proof); err != nil {
	panic(err)
}
fmt.Println("verified")
Output:

verified

func BatchVerifyMultiVk added in v0.14.0

func BatchVerifyMultiVk(vk []VerifyingKey, commitments []curve.G1Affine, pok []curve.G1Affine, combinationCoeff fr.Element) error

BatchVerifyMultiVk verifies multiple separate proofs of knowledge using n+1 pairings instead of 2n pairings.

The verifying keys may be from different setup ceremonies, but the G2 point must be the same. This can be enforced using WithG2Point option during setup.

The argument combinationCoeff is used as a linear combination coefficient to fold separate proofs into one. This means that in an interactive setting, it must be randomly generated by the verifier and sent to the prover. Otherwise, it must be generated via Fiat-Shamir.

The prover can fold the proofs using curve.G1Affine.Fold itself using the random challenge, providing the verifier only the folded proof. In this case the argument pok should contain only the single folded proof.

Example

This example shows how to batch verify multiple proofs using multiple verifying keys.

const nbPks = 3
const nbElem = 4
// create a proving key with independent basis elements
var buf [32]byte
basis := make([][]curve.G1Affine, nbPks)
for i := range basis {
	basis[i] = make([]curve.G1Affine, nbElem)
	for j := range basis[i] {
		_, err := rand.Read(buf[:])
		if err != nil {
			panic(err)
		}
		// we use hash-to-curve to avoid linear dependencies between basis elements
		basis[i][j], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i)))
		if err != nil {
			panic(err)
		}
	}
}
// we create independent proving keys (different sigmas) with same G2
// g2Point does not have to be generated in a trusted manner
_, _, _, g2Point := curve.Generators()
pks := make([]ProvingKey, nbPks)
vks := make([]VerifyingKey, nbPks)
for i := range basis {
	pkss, vkss, err := Setup(basis[i:i+1], WithG2Point(g2Point))
	if err != nil {
		panic(err)
	}
	pks[i] = pkss[0]
	vks[i] = vkss
}
// generate random values to commit to
toCommit := make([][]fr.Element, nbPks)
for i := range toCommit {
	toCommit[i] = make([]fr.Element, nbElem)
	for j := range toCommit[i] {
		toCommit[i][j].SetRandom()
	}
}
// commit to the values
commitments := make([]curve.G1Affine, nbPks)
for i := range commitments {
	var err error
	commitments[i], err = pks[i].Commit(toCommit[i])
	if err != nil {
		panic(err)
	}
}
// prove the commitments
proofs := make([]curve.G1Affine, nbPks)
for i := range proofs {
	var err error
	proofs[i], err = pks[i].ProveKnowledge(toCommit[i])
	if err != nil {
		panic(err)
	}
}
// combination coefficient is randomly sampled by the verifier. NB! In non-interactive protocol use Fiat-Shamir!
var combinationCoeff fr.Element
combinationCoeff.SetRandom()
// batch verify the proofs
if err := BatchVerifyMultiVk(vks, commitments, proofs, combinationCoeff); err != nil {
	panic(err)
}

// alternatively, we can also provide the folded proof
foldedProof, err := new(curve.G1Affine).Fold(proofs, combinationCoeff, ecc.MultiExpConfig{NbTasks: 1})
if err != nil {
	panic(err)
}
if err := BatchVerifyMultiVk(vks, commitments, []curve.G1Affine{*foldedProof}, combinationCoeff); err != nil {
	panic(err)
}

fmt.Println("verified")
Output:

verified

func Setup

func Setup(bases [][]curve.G1Affine, options ...SetupOption) (pk []ProvingKey, vk VerifyingKey, err error)

Setup generates the proving keys for Pedersen commitments over the given bases allowing for batch proving. The common verifying key can be used to verify the batched proof of knowledge.

By default the G2 generator is sampled randomly. This can be overridden by providing a custom G2 generator using WithG2Point option.

The input bases do not have to be of the same length for individual committing and proving. The elements in bases[i] should be linearly independent of each other. Otherwise the prover may be able to construct multiple valid openings for a commitment.

NB! This is a trusted setup process. The randomness during the setup must be discarded. Failing to do so allows to create proofs without knowing the committed values.

Types

type ProvingKey added in v0.11.0

type ProvingKey struct {
	Basis         []curve.G1Affine
	BasisExpSigma []curve.G1Affine // basisExpSigma[i] = Basis[i]^{σ}
}

ProvingKey for committing and proofs of knowledge

func (*ProvingKey) Commit added in v0.11.0

func (pk *ProvingKey) Commit(values []fr.Element) (commitment curve.G1Affine, err error)

Commit computes a commitment to the values over proving key's basis

func (*ProvingKey) ProveKnowledge added in v0.11.2

func (pk *ProvingKey) ProveKnowledge(values []fr.Element) (pok curve.G1Affine, err error)

ProveKnowledge generates a proof of knowledge of a commitment to the given values over proving key's basis.

func (*ProvingKey) ReadFrom added in v0.11.0

func (pk *ProvingKey) ReadFrom(r io.Reader) (int64, error)

func (*ProvingKey) WriteRawTo added in v0.11.2

func (pk *ProvingKey) WriteRawTo(w io.Writer) (int64, error)

func (*ProvingKey) WriteTo added in v0.11.0

func (pk *ProvingKey) WriteTo(w io.Writer) (int64, error)

type SetupOption added in v0.14.0

type SetupOption func(cfg *setupConfig)

SetupOption allows to customize Pedersen vector commitment setup.

func WithG2Point added in v0.14.0

func WithG2Point(g2 curve.G2Affine) SetupOption

WithG2Point allows to set the G2 generator for the Pedersen vector commitment setup. If this is not set, we sample a random G2 point.

type VerifyingKey added in v0.11.0

type VerifyingKey struct {
	G      curve.G2Affine
	GSigma curve.G2Affine // GRootSigmaNeg = G^{-σ}
}

func (*VerifyingKey) ReadFrom added in v0.11.0

func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error)

func (*VerifyingKey) UnsafeReadFrom added in v0.11.2

func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error)

func (*VerifyingKey) Verify added in v0.11.0

func (vk *VerifyingKey) Verify(commitment curve.G1Affine, knowledgeProof curve.G1Affine) error

Verify checks if the proof of knowledge is valid for a given commitment.

func (*VerifyingKey) WriteRawTo added in v0.11.2

func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error)

func (*VerifyingKey) WriteTo added in v0.11.0

func (vk *VerifyingKey) WriteTo(w io.Writer) (int64, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL