pedersen

package
v0.0.0-...-6c19a75 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 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

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 FoldCommitments.

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 := FoldCommitments(commitments, combinationCoeff)
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

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.

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)
}
fmt.Println("verified")
Output:

verified

func FoldCommitments

func FoldCommitments(commitments []curve.G1Affine, combinationCoeff fr.Element) (commitment curve.G1Affine, err error)

FoldCommitments folds multiple commitments into a single commitment for verifying the batched proof computed with BatchProve.

The argument combinationCoeff is used as a linear combination coefficient to fold separate commitments 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.

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

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

ProvingKey for committing and proofs of knowledge

func (*ProvingKey) Commit

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

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

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

func (*ProvingKey) WriteRawTo

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

func (*ProvingKey) WriteTo

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

type SetupOption

type SetupOption func(cfg *setupConfig)

SetupOption allows to customize Pedersen vector commitment setup.

func WithG2Point

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

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

func (*VerifyingKey) ReadFrom

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

func (*VerifyingKey) UnsafeReadFrom

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

func (*VerifyingKey) Verify

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

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

func (*VerifyingKey) WriteTo

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