ecvrf

package module
v0.0.0-...-a63bf14 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2022 License: MIT Imports: 7 Imported by: 0

README

go-ecvrf

GoDoc Reference Travis License

Golang implementation of Elliptic Curve Verifiable Random Function (VRF) follows draft-irtf-cfrg-vrf-06 and RFC 6979.

What's VRF

A Verifiable Random Function (VRF) is the public-key version of a keyed cryptographic hash. Only the holder of the private key can compute the hash, but anyone with public key can verify the correctness of the hash.

A key application of the VRF is to provide privacy against offline enumeration (e.g. dictionary attacks) on data stored in a hash-based data structure. In this application, a Prover holds the VRF private key and uses the VRF hashing to construct a hash-based data structure on the input data. Due to the nature of the VRF, only the Prover can answer queries about whether or not some data is stored in the data structure. Anyone who knows the public VRF key can verify that the Prover has answered the queries correctly. However no offline inferences (i.e. inferences without querying the Prover) can be made about the data stored in the data strucuture.

Installation

go get -u github.com/vechain/go-ecvrf

Examples

Using SECP256K1_SHA256_TAI cipher suite:

  • VRF Proving

    // the private key
    var sk *ecdsa.PrivateKey
    // code to load sk
    // ... 
    
    // the input to be hashed by the VRF
    alpha := "Hello VeChain"
    
    // `beta`: the VRF hash output
    // `pi`: the VRF proof
    beta, pi, err := ecvrf.Secp256k1Sha256Tai.Prove(sk, []byte(alpha))
    if err != nil {
        // something wrong.
        // most likely sk is not properly loaded.
        return
    }
    
  • VRF Verifying

    // the public key
    var pk *ecdsa.PublicKey
    // code to load pk
    // ...
    
    // the input to be hashed by the VRF
    alpha := "Hello VeChain"
    
    // `pi` is the VRF proof
    beta, err := ecvrf.Secp256k1Sha256Tai.Verify(pk, []byte(alpha), pi)
    if err != nil {
        // invalid proof
        return
    }
    
    // got correct beta
    

Supported Cipher Suites

  • P256_SHA256_TAI
  • SECP256K1_SHA256_TAI

It's easy to extends this library to use different Weierstrass curves and Hash algorithms, by providing cooked Config like:

// the following codes build a new P256_SHA256_TAI VRF object.
vrf := ecvrf.New(&ecvrf.Config{
    Curve:       elliptic.P256(),
    SuiteString: 0x01,
    Cofactor:    0x01,
    NewHasher:   sha256.New,
    Decompress: elliptic.UnmarshalCompressed,
})

Benchmark

$ go test -benchmem -run=^$ -bench ^BenchmarkVRF$ github.com/vechain/go-ecvrf -benchtime=5s
goos: linux
goarch: amd64
pkg: github.com/vechain/go-ecvrf
cpu: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
BenchmarkVRF/secp256k1sha256tai-proving-8         	   22207	    279600 ns/op	    4881 B/op	      95 allocs/op
BenchmarkVRF/secp256k1sha256tai-verifying-8       	   15150	    399938 ns/op	    5009 B/op	     114 allocs/op
BenchmarkVRF/p256sha256tai-proving-8              	   31328	    193911 ns/op	    9083 B/op	     294 allocs/op
BenchmarkVRF/p256sha256tai-verifying-8            	   19875	    300613 ns/op	   19472 B/op	     515 allocs/op
PASS
ok  	github.com/vechain/go-ecvrf	36.060s

References

License

Copyright (c) 2020 vechain.org. Licensed under the MIT license.

Documentation

Overview

Package ecvrf is the Elliptic Curve Verifiable Random Function (VRF) library.

Index

Constants

This section is empty.

Variables

View Source
var (
	// Secp256k1Sha256Tai is the pre-configured VRF object with secp256k1/SHA256 and hash_to_curve_try_and_increment algorithm.
	Secp256k1Sha256Tai = New(&Config{
		Curve:       secp256k1.S256(),
		SuiteString: 0xfe,
		Cofactor:    0x01,
		NewHasher:   sha256.New,
		Decompress: func(c elliptic.Curve, pk []byte) (x, y *big.Int) {
			var fx, fy secp256k1.FieldVal

			format := pk[0]
			switch format {
			case secp256k1.PubKeyFormatCompressedEven, secp256k1.PubKeyFormatCompressedOdd:
			default:
				return
			}

			if overflow := fx.SetByteSlice(pk[1:33]); overflow {
				return
			}

			wantOddY := format == secp256k1.PubKeyFormatCompressedOdd
			if !secp256k1.DecompressY(&fx, wantOddY, &fy) {
				return
			}
			fy.Normalize()
			return new(big.Int).SetBytes(fx.Bytes()[:]), new(big.Int).SetBytes(fy.Bytes()[:])
		},
	})
	// P256Sha256Tai is the pre-configured VRF object with P256/SHA256 and hash_to_curve_try_and_increment algorithm.
	P256Sha256Tai = New(&Config{
		Curve:       elliptic.P256(),
		SuiteString: 0x01,
		Cofactor:    0x01,
		NewHasher:   sha256.New,
		Decompress:  elliptic.UnmarshalCompressed,
	})
)

Functions

This section is empty.

Types

type Config

type Config struct {
	// the elliptic curve.
	Curve elliptic.Curve
	// a single nonzero octet specifying the ECVRF ciphersuite.
	SuiteString byte
	// number of points on curve divided by group order.
	Cofactor byte
	// create cryptographic hash function.
	NewHasher func() hash.Hash
	// decompress the compressed public key into x and y coordinate.
	Decompress func(c elliptic.Curve, pk []byte) (x, y *big.Int)
}

Config contains VRF parameters.

type Core

type Core struct {
	*Config
	// contains filtered or unexported fields
}

func (*Core) Add

func (c *Core) Add(pt1, pt2 *Point) *Point

func (*Core) DecodeProof

func (c *Core) DecodeProof(pi []byte) (gamma *Point, C, S *big.Int, err error)

See: [draft-irtf-cfrg-vrf-06 section 5.4.4](https://tools.ietf.org/id/draft-irtf-cfrg-vrf-06.html#rfc.section.5.4.4)

func (*Core) EncodeProof

func (c *Core) EncodeProof(gamma *Point, C, S *big.Int) []byte

func (*Core) GammaToHash

func (c *Core) GammaToHash(gamma *Point) []byte

func (*Core) HashPoints

func (c *Core) HashPoints(points ...*Point) *big.Int

See: [draft-irtf-cfrg-vrf-06 section 5.4.3](https://tools.ietf.org/id/draft-irtf-cfrg-vrf-06.html#rfc.section.5.4.3)

func (*Core) HashToCurveTryAndIncrement

func (c *Core) HashToCurveTryAndIncrement(pk *Point, alpha []byte) (*Point, error)

HashToCurveTryAndIncrement takes in the VRF input `alpha` and converts it to H, using the try_and_increment algorithm. See: [draft-irtf-cfrg-vrf-06 section 5.4.1.1](https://tools.ietf.org/id/draft-irtf-cfrg-vrf-06.html#rfc.section.5.4.1.1).

func (*Core) Marshal

func (c *Core) Marshal(pt *Point) []byte

Marshal marshals a Point into compressed form specified in section 4.3.6 of ANSI X9.62. It's the alias of `point_to_string` specified in [draft-irtf-cfrg-vrf-06 section 5.5](https://tools.ietf.org/id/draft-irtf-cfrg-vrf-06.html#rfc.section.5.5).

func (*Core) N

func (c *Core) N() int

N return half of length, in octets, of a field element in F, rounded up to the nearest even integer

func (*Core) Q

func (c *Core) Q() *big.Int

Q returns prime order of large prime order subgroup.

func (*Core) ScalarBaseMult

func (c *Core) ScalarBaseMult(k []byte) *Point

func (*Core) ScalarMult

func (c *Core) ScalarMult(pt *Point, k []byte) *Point

func (*Core) Sub

func (c *Core) Sub(pt1, pt2 *Point) *Point

func (*Core) Unmarshal

func (c *Core) Unmarshal(in []byte) *Point

Unmarshal unmarshals a compressed Point in the form specified in section 4.3.6 of ANSI X9.62. It's the alias of `string_to_point` specified in [draft-irtf-cfrg-vrf-06 section 5.5](https://tools.ietf.org/id/draft-irtf-cfrg-vrf-06.html#rfc.section.5.5). This is borrowed from the project https://github.com/google/keytransparency.

type Point

type Point struct {
	X, Y *big.Int
}

type VRF

type VRF interface {
	// Prove constructs a VRF proof `pi` for the given input `alpha`,
	// using the private key `sk`. The hash output is returned as `beta`.
	Prove(sk *ecdsa.PrivateKey, alpha []byte) (beta, pi []byte, err error)

	// Verify checks the proof `pi` of the message `alpha` against the given
	// public key `pk`. The hash output is returned as `beta`.
	Verify(pk *ecdsa.PublicKey, alpha, pi []byte) (beta []byte, err error)

	GetVerifyComponents(pk *ecdsa.PublicKey, alpha, pi []byte) (U, sH, cG *Point, err error)

	Core() Core
}

VRF is the interface that wraps VRF methods.

func New

func New(cfg *Config) VRF

New creates and initializes a VRF object using customized config.

Jump to

Keyboard shortcuts

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