secretsharing

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2024 License: MIT Imports: 2 Imported by: 9

README

Secure Secret Sharing

secret-sharing Go Reference codecov

  import "github.com/bytemare/secret-sharing"

This package implements Shamir's Secret Sharing extended with Feldman's Verifiable Secret Sharing over elliptic curve groups. It is aimed to be very easy to use.

Secret sharing enables to shard (or split) a secret key into an arbitrary number of shares n and to recover that same key with any subset of at minimum t of these key shares in a (t,n)-threshold scheme.

Note that the key distribution (sharding) algorithm used in this package is a trusted dealer (i.e. centralised). If you need a truly decentralized key generation, you can use the dkg package which builds on this package.

Documentation Go Reference

You can find the documentation and usage examples in the package doc.

Versioning

SemVer is used for versioning. For the versions available, see the tags on the repository.

Contributing

Please read CONTRIBUTING.md for details on the code of conduct, and the process for submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Overview

Package secretsharing provides Shamir Secret Sharing operations.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CombineShares added in v0.2.0

func CombineShares(g group.Group, shares []Share) (*group.Scalar, error)

CombineShares recovers the constant secret by combining the key shares using the Share interface.

func PolynomialInterpolateConstant

func PolynomialInterpolateConstant(g group.Group, shares []Share) (*group.Scalar, error)

PolynomialInterpolateConstant recovers the constant term of the interpolating polynomial defined by the set of key shares.

func PubKeyForCommitment added in v0.2.0

func PubKeyForCommitment(g group.Group, id uint64, commitment []*group.Element) (*group.Element, error)

PubKeyForCommitment computes the public key corresponding to the commitment of participant id.

func ShardReturnPolynomial added in v0.1.1

func ShardReturnPolynomial(
	g group.Group,
	secret *group.Scalar,
	threshold, total uint,
	polynomial ...*group.Scalar,
) ([]*KeyShare, Polynomial, error)

ShardReturnPolynomial splits the secret into total shares, recoverable by a subset of threshold shares, and returns the constructed secret polynomial. To use Verifiable Secret Sharing, call Commit with the returned polynomial.

func Verify

func Verify(g group.Group, id uint64, pk *group.Element, coms []*group.Element) bool

Verify allows verification of participant id's public key given its public key and the VSS commitment to the secret polynomial.

Example

ExampleShardAndVerify shows how to split a private key into shares, commit to the underlying polynomial, and verify the generated public keys given the initial commitment.

package main

import (
	"fmt"

	group "github.com/bytemare/crypto"

	secretsharing "github.com/bytemare/secret-sharing"
)

func main() {
	// These are the configuration parameters
	g := group.Ristretto255Sha512
	threshold := uint(3)    // threshold is minimum amount of necessary shares to recombine the secret
	shareholders := uint(7) // the total amount of key share-holders

	// This is the global secret to be shared
	secret := g.NewScalar().Random()

	// Shard the secret into shares
	shares, polynomial, err := secretsharing.ShardReturnPolynomial(g, secret, threshold, shareholders)
	if err != nil {
		panic(err)
	}

	// Commit to polynomial.
	commitment := secretsharing.Commit(g, polynomial)

	// You can verify any public key using the commitment. This can be run by a single participant or any other
	// participant access to the participant's public key.
	for _, keyshare := range shares {
		// Let's derive the public key. Other parties won't have access to the private key, naturally.
		publicKey := g.Base().Multiply(keyshare.SecretKey())

		// Verify that the key share's public key is consistent with the commitment.
		if !secretsharing.Verify(g, keyshare.Identifier(), publicKey, commitment) {
			panic("invalid public key for shareholder")
		}
	}

	fmt.Println("All key shares verified.")

}
Output:

All key shares verified.

Types

type Commitment

type Commitment []*group.Element

Commitment is the tuple defining a Verifiable Secret Sharing Commitment.

func Commit

func Commit(g group.Group, polynomial Polynomial) Commitment

Commit builds a Verifiable Secret Sharing vector Commitment to each of the coefficients (of threshold length which uniquely determines the polynomial).

type KeyShare

type KeyShare struct {
	// The Secret of a participant (or secret share).
	Secret *group.Scalar

	// PublicKeyShare is the public part of the participant's key share.
	*PublicKeyShare
}

KeyShare holds the secret and public key share for a given participant.

func Shard added in v0.1.1

func Shard(
	g group.Group,
	secret *group.Scalar,
	threshold, total uint,
	polynomial ...*group.Scalar,
) ([]*KeyShare, error)

Shard splits the secret into total shares, recoverable by a subset of threshold shares. To use Verifiable Secret Sharing, use ShardReturnPolynomial and commit to the polynomial with Commit.

Example

ExampleShard shows how to split a private key into shares and how to recombine it from a subset of shares. For an example of Verifiable Secret Sharing, see ExampleVerify.

package main

import (
	"fmt"

	group "github.com/bytemare/crypto"

	secretsharing "github.com/bytemare/secret-sharing"
)

func main() {
	// These are the configuration parameters
	g := group.Ristretto255Sha512
	threshold := uint(3)    // threshold is the minimum amount of necessary shares to recombine the secret
	shareholders := uint(7) // the total amount of key share-holders

	// This is the global secret to be shared
	secret := g.NewScalar().Random()

	// Shard the secret into shares
	shares, err := secretsharing.Shard(g, secret, threshold, shareholders)
	if err != nil {
		panic(err)
	}

	// Assemble a subset of shares to recover the secret. We must use threshold or more shares.
	subset := []secretsharing.Share{
		shares[5], shares[0], shares[3],
	}

	// Combine the subset of shares.
	recovered, err := secretsharing.CombineShares(g, subset)
	if err != nil {
		panic(err)
	}

	if recovered.Equal(secret) != 1 {
		fmt.Println("ERROR: recovery failed")
	} else {
		fmt.Println("Key split into shares and recombined with a subset of shares!")
	}

}
Output:

Key split into shares and recombined with a subset of shares!

func (KeyShare) Identifier

func (s KeyShare) Identifier() uint64

Identifier returns the identity for this share.

func (KeyShare) Public added in v0.2.0

func (s KeyShare) Public() *PublicKeyShare

Public returns the public key share and identifier corresponding to the secret key share.

func (KeyShare) SecretKey

func (s KeyShare) SecretKey() *group.Scalar

SecretKey returns the participant's secret share.

type KeyShares added in v0.2.0

type KeyShares []*KeyShare

KeyShares is a set of KeyShares.

func (KeyShares) Combine added in v0.2.0

func (k KeyShares) Combine(g group.Group) (*group.Scalar, error)

Combine recovers the constant secret by combining the key shares.

type Polynomial

type Polynomial []*group.Scalar

Polynomial over scalars, represented as a list of t+1 coefficients, where t is the threshold. The constant term is in the first position and the highest degree coefficient is in the last position. All operations on the polynomial's coefficient are done modulo the scalar's group order.

func NewPolynomial

func NewPolynomial(coefficients uint) Polynomial

NewPolynomial returns a slice of Scalars with the capacity to hold the desired coefficients.

func NewPolynomialFromIntegers added in v0.1.4

func NewPolynomialFromIntegers(g group.Group, ints []uint64) Polynomial

NewPolynomialFromIntegers returns a Polynomial from a slice of uint64.

func NewPolynomialFromListFunc added in v0.1.4

func NewPolynomialFromListFunc[S ~[]E, E any](g group.Group, s S, f func(E) *group.Scalar) Polynomial

NewPolynomialFromListFunc returns a Polynomial from the uint64 returned by f applied on each element of the slice.

func (Polynomial) DeriveInterpolatingValue

func (p Polynomial) DeriveInterpolatingValue(g group.Group, id *group.Scalar) (*group.Scalar, error)

DeriveInterpolatingValue derives a value used for polynomial interpolation. id and all the coefficients must be non-zero scalars.

func (Polynomial) Evaluate

func (p Polynomial) Evaluate(x *group.Scalar) *group.Scalar

Evaluate evaluates the polynomial p at point x using Horner's method.

func (Polynomial) Verify added in v0.1.2

func (p Polynomial) Verify() error

Verify returns an appropriate error if the polynomial has a nil or 0 coefficient, or duplicates.

type PublicKeyShare added in v0.2.0

type PublicKeyShare struct {
	// The PublicKey of Secret belonging to the participant.
	PublicKey *group.Element

	// ID of the participant.
	ID uint64
}

PublicKeyShare specifies the public key of a participant identified with ID. This can be useful to keep a registry of participants.

type Share added in v0.1.3

type Share interface {
	// Identifier returns the identity for this share.
	Identifier() uint64

	// SecretKey returns the participant's secret share.
	SecretKey() *group.Scalar
}

The Share interface enables to use functions in this package with compatible key shares.

Jump to

Keyboard shortcuts

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