Merge pull request #398 from harmony-one/rj_branch

Copy vrf from google/keytransparency package; we will build on this
pull/406/head
Rongjian Lan 6 years ago committed by GitHub
commit 04c6d69fc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .gitmodules
  2. 303
      crypto/vrf/p256/p256.go
  3. 349
      crypto/vrf/p256/p256_test.go
  4. 81
      crypto/vrf/p256/unmarshal.go
  5. 40
      crypto/vrf/vrf.go
  6. 28
      test/testdata/directory.json
  7. 1503
      test/testdata/getentryresponse.json
  8. 1
      vendor/github.com/golang/protobuf

3
.gitmodules vendored

@ -2,9 +2,6 @@
path = vendor/github.com/ethereum/go-ethereum
url = https://github.com/harmony-one/go-ethereum
branch = master
[submodule "vendor/github.com/golang/protobuf"]
path = vendor/github.com/golang/protobuf
url = https://github.com/golang/protobuf
[submodule "vendor/github.com/libp2p/go-libp2p-kad-dht"]
path = vendor/github.com/libp2p/go-libp2p-kad-dht
url = https://github.com/libp2p/go-libp2p-kad-dht

@ -0,0 +1,303 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package p256 implements a verifiable random function using curve p256.
package p256
// Discrete Log based VRF from Appendix A of CONIKS:
// http://www.jbonneau.com/doc/MBBFF15-coniks.pdf
// based on "Unique Ring Signatures, a Practical Construction"
// http://fc13.ifca.ai/proc/5-1.pdf
import (
"bytes"
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/binary"
"encoding/pem"
"errors"
"fmt"
"math/big"
"github.com/google/keytransparency/core/crypto/vrf"
"github.com/google/trillian/crypto/keys"
"github.com/golang/protobuf/proto"
)
var (
curve = elliptic.P256()
params = curve.Params()
// ErrPointNotOnCurve occurs when a public key is not on the curve.
ErrPointNotOnCurve = errors.New("point is not on the P256 curve")
// ErrWrongKeyType occurs when a key is not an ECDSA key.
ErrWrongKeyType = errors.New("not an ECDSA key")
// ErrNoPEMFound occurs when attempting to parse a non PEM data structure.
ErrNoPEMFound = errors.New("no PEM block found")
// ErrInvalidVRF occurs when the VRF does not validate.
ErrInvalidVRF = errors.New("invalid VRF proof")
)
// PublicKey holds a public VRF key.
type PublicKey struct {
*ecdsa.PublicKey
}
// PrivateKey holds a private VRF key.
type PrivateKey struct {
*ecdsa.PrivateKey
}
// GenerateKey generates a fresh keypair for this VRF
func GenerateKey() (vrf.PrivateKey, vrf.PublicKey) {
key, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, nil
}
return &PrivateKey{PrivateKey: key}, &PublicKey{PublicKey: &key.PublicKey}
}
// H1 hashes m to a curve point
func H1(m []byte) (x, y *big.Int) {
h := sha512.New()
var i uint32
byteLen := (params.BitSize + 7) >> 3
for x == nil && i < 100 {
// TODO: Use a NIST specified DRBG.
h.Reset()
binary.Write(h, binary.BigEndian, i)
h.Write(m)
r := []byte{2} // Set point encoding to "compressed", y=0.
r = h.Sum(r)
x, y = Unmarshal(curve, r[:byteLen+1])
i++
}
return
}
var one = big.NewInt(1)
// H2 hashes to an integer [1,N-1]
func H2(m []byte) *big.Int {
// NIST SP 800-90A § A.5.1: Simple discard method.
byteLen := (params.BitSize + 7) >> 3
h := sha512.New()
for i := uint32(0); ; i++ {
// TODO: Use a NIST specified DRBG.
h.Reset()
binary.Write(h, binary.BigEndian, i)
h.Write(m)
b := h.Sum(nil)
k := new(big.Int).SetBytes(b[:byteLen])
if k.Cmp(new(big.Int).Sub(params.N, one)) == -1 {
return k.Add(k, one)
}
}
}
// Evaluate returns the verifiable unpredictable function evaluated at m
func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) {
nilIndex := [32]byte{}
// Prover chooses r <-- [1,N-1]
r, _, _, err := elliptic.GenerateKey(curve, rand.Reader)
if err != nil {
return nilIndex, nil
}
ri := new(big.Int).SetBytes(r)
// H = H1(m)
Hx, Hy := H1(m)
// VRF_k(m) = [k]H
sHx, sHy := params.ScalarMult(Hx, Hy, k.D.Bytes())
vrf := elliptic.Marshal(curve, sHx, sHy) // 65 bytes.
// G is the base point
// s = H2(G, H, [k]G, VRF, [r]G, [r]H)
rGx, rGy := params.ScalarBaseMult(r)
rHx, rHy := params.ScalarMult(Hx, Hy, r)
var b bytes.Buffer
b.Write(elliptic.Marshal(curve, params.Gx, params.Gy))
b.Write(elliptic.Marshal(curve, Hx, Hy))
b.Write(elliptic.Marshal(curve, k.PublicKey.X, k.PublicKey.Y))
b.Write(vrf)
b.Write(elliptic.Marshal(curve, rGx, rGy))
b.Write(elliptic.Marshal(curve, rHx, rHy))
s := H2(b.Bytes())
// t = r−s*k mod N
t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D))
t.Mod(t, params.N)
// Index = H(vrf)
index = sha256.Sum256(vrf)
// Write s, t, and vrf to a proof blob. Also write leading zeros before s and t
// if needed.
var buf bytes.Buffer
buf.Write(make([]byte, 32-len(s.Bytes())))
buf.Write(s.Bytes())
buf.Write(make([]byte, 32-len(t.Bytes())))
buf.Write(t.Bytes())
buf.Write(vrf)
return index, buf.Bytes()
}
// ProofToHash asserts that proof is correct for m and outputs index.
func (pk *PublicKey) ProofToHash(m, proof []byte) (index [32]byte, err error) {
nilIndex := [32]byte{}
// verifier checks that s == H2(m, [t]G + [s]([k]G), [t]H1(m) + [s]VRF_k(m))
if got, want := len(proof), 64+65; got != want {
return nilIndex, ErrInvalidVRF
}
// Parse proof into s, t, and vrf.
s := proof[0:32]
t := proof[32:64]
vrf := proof[64 : 64+65]
uHx, uHy := elliptic.Unmarshal(curve, vrf)
if uHx == nil {
return nilIndex, ErrInvalidVRF
}
// [t]G + [s]([k]G) = [t+ks]G
tGx, tGy := params.ScalarBaseMult(t)
ksGx, ksGy := params.ScalarMult(pk.X, pk.Y, s)
tksGx, tksGy := params.Add(tGx, tGy, ksGx, ksGy)
// H = H1(m)
// [t]H + [s]VRF = [t+ks]H
Hx, Hy := H1(m)
tHx, tHy := params.ScalarMult(Hx, Hy, t)
sHx, sHy := params.ScalarMult(uHx, uHy, s)
tksHx, tksHy := params.Add(tHx, tHy, sHx, sHy)
// H2(G, H, [k]G, VRF, [t]G + [s]([k]G), [t]H + [s]VRF)
// = H2(G, H, [k]G, VRF, [t+ks]G, [t+ks]H)
// = H2(G, H, [k]G, VRF, [r]G, [r]H)
var b bytes.Buffer
b.Write(elliptic.Marshal(curve, params.Gx, params.Gy))
b.Write(elliptic.Marshal(curve, Hx, Hy))
b.Write(elliptic.Marshal(curve, pk.X, pk.Y))
b.Write(vrf)
b.Write(elliptic.Marshal(curve, tksGx, tksGy))
b.Write(elliptic.Marshal(curve, tksHx, tksHy))
h2 := H2(b.Bytes())
// Left pad h2 with zeros if needed. This will ensure that h2 is padded
// the same way s is.
var buf bytes.Buffer
buf.Write(make([]byte, 32-len(h2.Bytes())))
buf.Write(h2.Bytes())
if !hmac.Equal(s, buf.Bytes()) {
return nilIndex, ErrInvalidVRF
}
return sha256.Sum256(vrf), nil
}
// NewFromWrappedKey creates a VRF signer object from an encrypted private key.
// The opaque private key must resolve to an `ecdsa.PrivateKey` in order to work.
func NewFromWrappedKey(ctx context.Context, wrapped proto.Message) (vrf.PrivateKey, error) {
// Unwrap.
signer, err := keys.NewSigner(ctx, wrapped)
if err != nil {
return nil, err
}
switch key := signer.(type) {
case *ecdsa.PrivateKey:
return NewVRFSigner(key)
default:
return nil, fmt.Errorf("wrapped key has wrong type: %T, want ecdsa.PrivateKey", key)
}
}
// NewVRFSigner creates a signer object from a private key.
func NewVRFSigner(key *ecdsa.PrivateKey) (vrf.PrivateKey, error) {
if *(key.Params()) != *curve.Params() {
return nil, ErrPointNotOnCurve
}
if !curve.IsOnCurve(key.X, key.Y) {
return nil, ErrPointNotOnCurve
}
return &PrivateKey{PrivateKey: key}, nil
}
// Public returns the corresponding public key as bytes.
func (k PrivateKey) Public() crypto.PublicKey {
return &k.PublicKey
}
// NewVRFVerifier creates a verifier object from a public key.
func NewVRFVerifier(pubkey *ecdsa.PublicKey) (vrf.PublicKey, error) {
if *(pubkey.Params()) != *curve.Params() {
return nil, ErrPointNotOnCurve
}
if !curve.IsOnCurve(pubkey.X, pubkey.Y) {
return nil, ErrPointNotOnCurve
}
return &PublicKey{PublicKey: pubkey}, nil
}
// NewVRFSignerFromPEM creates a vrf private key from a PEM data structure.
func NewVRFSignerFromPEM(b []byte) (vrf.PrivateKey, error) {
p, _ := pem.Decode(b)
if p == nil {
return nil, ErrNoPEMFound
}
return NewVRFSignerFromRawKey(p.Bytes)
}
// NewVRFSignerFromRawKey returns the private key from a raw private key bytes.
func NewVRFSignerFromRawKey(b []byte) (vrf.PrivateKey, error) {
k, err := x509.ParseECPrivateKey(b)
if err != nil {
return nil, err
}
return NewVRFSigner(k)
}
// NewVRFVerifierFromPEM creates a vrf public key from a PEM data structure.
func NewVRFVerifierFromPEM(b []byte) (vrf.PublicKey, error) {
p, _ := pem.Decode(b)
if p == nil {
return nil, ErrNoPEMFound
}
return NewVRFVerifierFromRawKey(p.Bytes)
}
// NewVRFVerifierFromRawKey returns the public key from a raw public key bytes.
func NewVRFVerifierFromRawKey(b []byte) (vrf.PublicKey, error) {
k, err := x509.ParsePKIXPublicKey(b)
if err != nil {
return nil, err
}
pk, ok := k.(*ecdsa.PublicKey)
if !ok {
return nil, ErrWrongKeyType
}
return NewVRFVerifier(pk)
}

@ -0,0 +1,349 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package p256
import (
"bytes"
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"io/ioutil"
"math"
"os"
"testing"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/google/keytransparency/core/testdata"
"github.com/google/trillian/crypto/keys"
"github.com/google/trillian/crypto/keys/der"
"github.com/google/trillian/crypto/keyspb"
pb "github.com/google/keytransparency/core/api/v1/keytransparency_go_proto"
_ "github.com/google/trillian/crypto/keys/der/proto"
)
const (
// openssl ecparam -name prime256v1 -genkey -out p256-key.pem
privKey = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIGbhE2+z8d5lHzb0gmkS78d86gm5gHUtXCpXveFbK3pcoAoGCCqGSM49
AwEHoUQDQgAEUxX42oxJ5voiNfbjoz8UgsGqh1bD1NXK9m8VivPmQSoYUdVFgNav
csFaQhohkiCEthY51Ga6Xa+ggn+eTZtf9Q==
-----END EC PRIVATE KEY-----`
// openssl ec -in p256-key.pem -pubout -out p256-pubkey.pem
pubKey = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUxX42oxJ5voiNfbjoz8UgsGqh1bD
1NXK9m8VivPmQSoYUdVFgNavcsFaQhohkiCEthY51Ga6Xa+ggn+eTZtf9Q==
-----END PUBLIC KEY-----`
)
func TestH1(t *testing.T) {
for i := 0; i < 10000; i++ {
m := make([]byte, 100)
if _, err := rand.Read(m); err != nil {
t.Fatalf("Failed generating random message: %v", err)
}
x, y := H1(m)
if x == nil {
t.Errorf("H1(%v)=%v, want curve point", m, x)
}
if got := curve.Params().IsOnCurve(x, y); !got {
t.Errorf("H1(%v)=[%v, %v], is not on curve", m, x, y)
}
}
}
func TestH2(t *testing.T) {
l := 32
for i := 0; i < 10000; i++ {
m := make([]byte, 100)
if _, err := rand.Read(m); err != nil {
t.Fatalf("Failed generating random message: %v", err)
}
x := H2(m)
if got := len(x.Bytes()); got < 1 || got > l {
t.Errorf("len(h2(%v)) = %v, want: 1 <= %v <= %v", m, got, got, l)
}
}
}
func TestNewFromWrappedKey(t *testing.T) {
ctx := context.Background()
for _, tc := range []struct {
desc string
wantFromWrappedErr bool
spec *keyspb.Specification
keygen keys.ProtoGenerator
}{
{
desc: "DER with ECDSA spec",
spec: &keyspb.Specification{
Params: &keyspb.Specification_EcdsaParams{
EcdsaParams: &keyspb.Specification_ECDSA{
Curve: keyspb.Specification_ECDSA_P256,
},
},
},
keygen: func(ctx context.Context, spec *keyspb.Specification) (proto.Message, error) {
return der.NewProtoFromSpec(spec)
},
},
{
desc: "DER with Non-ECDSA spec",
wantFromWrappedErr: true,
spec: &keyspb.Specification{
Params: &keyspb.Specification_RsaParams{
RsaParams: &keyspb.Specification_RSA{Bits: 2048},
},
},
keygen: func(ctx context.Context, spec *keyspb.Specification) (proto.Message, error) {
return der.NewProtoFromSpec(spec)
},
},
} {
t.Run(tc.desc, func(t *testing.T) {
// Generate VRF key.
wrapped, err := tc.keygen(ctx, tc.spec)
if err != nil {
t.Fatalf("keygen failed: %v", err)
}
vrfPriv, err := NewFromWrappedKey(ctx, wrapped)
if got, want := err != nil, tc.wantFromWrappedErr; got != want {
t.Errorf("NewFromWrappedKey (): %v, want err: %v", err, want)
}
if err != nil {
return
}
vrfPubDER, err := der.MarshalPublicKey(vrfPriv.Public())
if err != nil {
t.Fatalf("MarshalPublicKey failed: %v", err)
}
vrfPub, err := NewVRFVerifierFromRawKey(vrfPubDER)
if err != nil {
t.Fatalf("NewVRFVerifierFromRawKey(): %v", err)
}
// Test that the public and private components match.
m := []byte("foobar")
indexA, proof := vrfPriv.Evaluate(m)
indexB, err := vrfPub.ProofToHash(m, proof)
if err != nil {
t.Fatalf("ProofToHash(): %v", err)
}
if got, want := indexB, indexA; got != want {
t.Errorf("ProofToHash(%s, %x): %x, want %x", m, proof, got, want)
}
})
}
}
func TestVRF(t *testing.T) {
k, pk := GenerateKey()
m1 := []byte("data1")
m2 := []byte("data2")
m3 := []byte("data2")
index1, proof1 := k.Evaluate(m1)
index2, proof2 := k.Evaluate(m2)
index3, proof3 := k.Evaluate(m3)
for _, tc := range []struct {
m []byte
index [32]byte
proof []byte
err error
}{
{m1, index1, proof1, nil},
{m2, index2, proof2, nil},
{m3, index3, proof3, nil},
{m3, index3, proof2, nil},
{m3, index3, proof1, ErrInvalidVRF},
} {
index, err := pk.ProofToHash(tc.m, tc.proof)
if got, want := err, tc.err; got != want {
t.Errorf("ProofToHash(%s, %x): %v, want %v", tc.m, tc.proof, got, want)
}
if err != nil {
continue
}
if got, want := index, tc.index; got != want {
t.Errorf("ProofToInex(%s, %x): %x, want %x", tc.m, tc.proof, got, want)
}
}
}
// Test vectors in core/testdata are generated by running
// go generate ./core/testdata
func TestProofToHash(t *testing.T) {
directoryFile := "../../../test/testdata/directory.json"
f, err := os.Open(directoryFile)
if err != nil {
t.Fatalf("ReadFile(%v): %v", directoryFile, err)
}
defer f.Close()
var directory pb.Directory
if err := jsonpb.Unmarshal(f, &directory); err != nil {
t.Fatalf("jsonpb.Unmarshal(): %v", err)
}
pk, err := NewVRFVerifierFromRawKey(directory.GetVrf().GetDer())
if err != nil {
t.Fatalf("NewVRFVerifier failure: %v", err)
}
respFile := "../../../test/testdata/getentryresponse.json"
b, err := ioutil.ReadFile(respFile)
if err != nil {
t.Fatalf("ReadFile(%v): %v", respFile, err)
}
var getUserResponses []testdata.GetUserResponseVector
if err := json.Unmarshal(b, &getUserResponses); err != nil {
t.Fatalf("Unmarshal(): %v", err)
}
for _, tc := range getUserResponses {
t.Run(tc.Desc, func(t *testing.T) {
_, err := pk.ProofToHash([]byte(tc.UserID), tc.Resp.GetLeaf().GetVrfProof())
if err != nil {
t.Errorf("ProofToHash(%v): %v)", tc.Desc, err)
}
})
}
}
func TestReadFromOpenSSL(t *testing.T) {
for _, tc := range []struct {
priv string
pub string
}{
{privKey, pubKey},
} {
// Private VRF Key
signer, err := NewVRFSignerFromPEM([]byte(tc.priv))
if err != nil {
t.Errorf("NewVRFSigner failure: %v", err)
}
// Public VRF key
verifier, err := NewVRFVerifierFromPEM([]byte(tc.pub))
if err != nil {
t.Errorf("NewVRFSigner failure: %v", err)
}
// Evaluate and verify.
m := []byte("M")
_, proof := signer.Evaluate(m)
if _, err := verifier.ProofToHash(m, proof); err != nil {
t.Errorf("Failed verifying VRF proof")
}
}
}
func TestRightTruncateProof(t *testing.T) {
k, pk := GenerateKey()
data := []byte("data")
_, proof := k.Evaluate(data)
proofLen := len(proof)
for i := 0; i < proofLen; i++ {
proof = proof[:len(proof)-1]
if _, err := pk.ProofToHash(data, proof); err == nil {
t.Errorf("Verify unexpectedly succeeded after truncating %v bytes from the end of proof", i)
}
}
}
func TestLeftTruncateProof(t *testing.T) {
k, pk := GenerateKey()
data := []byte("data")
_, proof := k.Evaluate(data)
proofLen := len(proof)
for i := 0; i < proofLen; i++ {
proof = proof[1:]
if _, err := pk.ProofToHash(data, proof); err == nil {
t.Errorf("Verify unexpectedly succeeded after truncating %v bytes from the beginning of proof", i)
}
}
}
func TestBitFlip(t *testing.T) {
k, pk := GenerateKey()
data := []byte("data")
_, proof := k.Evaluate(data)
for i := 0; i < len(proof)*8; i++ {
// Flip bit in position i.
if _, err := pk.ProofToHash(data, flipBit(proof, i)); err == nil {
t.Errorf("Verify unexpectedly succeeded after flipping bit %v of vrf", i)
}
}
}
func flipBit(a []byte, pos int) []byte {
index := int(math.Floor(float64(pos) / 8))
b := a[index]
b ^= (1 << uint(math.Mod(float64(pos), 8.0)))
var buf bytes.Buffer
buf.Write(a[:index])
buf.Write([]byte{b})
buf.Write(a[index+1:])
return buf.Bytes()
}
func TestVectors(t *testing.T) {
k, err := NewVRFSignerFromPEM([]byte(privKey))
if err != nil {
t.Errorf("NewVRFSigner failure: %v", err)
}
pk, err := NewVRFVerifierFromPEM([]byte(pubKey))
if err != nil {
t.Errorf("NewVRFSigner failure: %v", err)
}
for _, tc := range []struct {
m []byte
index [32]byte
}{
{
m: []byte("test"),
index: h2i("1af0a7e3d9a96a71be6257cf4ad1a0ffdec57e9959b2eafc4673a6c31241fc9f"),
},
{
m: nil,
index: h2i("2ebac3669807f474f4d49891a1d0b2fba8e966f945ac01cbfffb3bb48627e67d"),
},
} {
index, proof := k.Evaluate(tc.m)
if got, want := index, tc.index; got != want {
t.Errorf("Evaluate(%s).Index: %x, want %x", tc.m, got, want)
}
index2, err := pk.ProofToHash(tc.m, proof)
if err != nil {
t.Errorf("ProofToHash(%s): %v", tc.m, err)
}
if got, want := index2, index; got != want {
t.Errorf("ProofToHash(%s): %x, want %x", tc.m, got, want)
}
}
}
func h2i(h string) [32]byte {
b, err := hex.DecodeString(h)
if err != nil {
panic("Invalid hex")
}
var i [32]byte
copy(i[:], b)
return i
}

@ -0,0 +1,81 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package p256
// This file implements compressed point unmarshaling. Preferably this
// functionality would be in a standard library. Code borrowed from:
// https://go-review.googlesource.com/#/c/1883/2/src/crypto/elliptic/elliptic.go
import (
"crypto/elliptic"
"math/big"
)
// Unmarshal a compressed point in the form specified in section 4.3.6 of ANSI X9.62.
func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) {
byteLen := (curve.Params().BitSize + 7) >> 3
if (data[0] &^ 1) != 2 {
return // unrecognized point encoding
}
if len(data) != 1+byteLen {
return
}
// Based on Routine 2.2.4 in NIST Mathematical routines paper
params := curve.Params()
tx := new(big.Int).SetBytes(data[1 : 1+byteLen])
y2 := y2(params, tx)
sqrt := defaultSqrt
ty := sqrt(y2, params.P)
if ty == nil {
return // "y^2" is not a square: invalid point
}
var y2c big.Int
y2c.Mul(ty, ty).Mod(&y2c, params.P)
if y2c.Cmp(y2) != 0 {
return // sqrt(y2)^2 != y2: invalid point
}
if ty.Bit(0) != uint(data[0]&1) {
ty.Sub(params.P, ty)
}
x, y = tx, ty // valid point: return it
return
}
// Use the curve equation to calculate y² given x.
// only applies to curves of the form y² = x³ - 3x + b.
func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int {
// y² = x³ - 3x + b
x3 := new(big.Int).Mul(x, x)
x3.Mul(x3, x)
threeX := new(big.Int).Lsh(x, 1)
threeX.Add(threeX, x)
x3.Sub(x3, threeX)
x3.Add(x3, curve.B)
x3.Mod(x3, curve.P)
return x3
}
func defaultSqrt(x, p *big.Int) *big.Int {
var r big.Int
if nil == r.ModSqrt(x, p) {
return nil // x is not a square
}
return &r
}

@ -0,0 +1,40 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package vrf defines the interface to a verifiable random function.
package vrf
import (
"crypto"
)
// A VRF is a pseudorandom function f_k from a secret key k, such that that
// knowledge of k not only enables one to evaluate f_k at for any message m,
// but also to provide an NP-proof that the value f_k(m) is indeed correct
// without compromising the unpredictability of f_k for any m' != m.
// http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=814584
// PrivateKey supports evaluating the VRF function.
type PrivateKey interface {
// Evaluate returns the output of H(f_k(m)) and its proof.
Evaluate(m []byte) (index [32]byte, proof []byte)
// Public returns the corresponding public key.
Public() crypto.PublicKey
}
// PublicKey supports verifying output from the VRF function.
type PublicKey interface {
// ProofToHash verifies the NP-proof supplied by Proof and outputs Index.
ProofToHash(m, proof []byte) (index [32]byte, err error)
}

@ -0,0 +1,28 @@
{
"directoryId": "integration",
"log": {
"treeId": "8541686838476068721",
"treeType": "PREORDERED_LOG",
"hashStrategy": "RFC6962_SHA256",
"hashAlgorithm": "SHA256",
"signatureAlgorithm": "ECDSA",
"publicKey": {
"der": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqGXPnhMIclRmYHSmAnCMmfDUJ9iNBMmFxR/wHJdL12AuVUkgcuhbEp2hy5ETs7bfFc2P95IYFlmbiuHMq3UY/A=="
}
},
"map": {
"treeId": "6598072539431303895",
"treeType": "MAP",
"hashStrategy": "CONIKS_SHA256",
"hashAlgorithm": "SHA256",
"signatureAlgorithm": "ECDSA",
"publicKey": {
"der": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWLHm0TLYaTzENpPkBl2E79ySqJI+EW51VpoWh7wqY3OjSJcft4zgEeNeHYEb/T2jBFH4eYg4iSN7D/VYaJxJRA=="
}
},
"vrf": {
"der": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEF2Pm2kKya+JBun1QRmKQMcoMOIBNWp8fjECkJX+/hNWdV1UKb12W+yXcX2MqN7ZMX77hS9mLus/WaE0NS370mA=="
},
"minInterval": "0.100s",
"maxInterval": "216000s"
}

File diff suppressed because it is too large Load Diff

@ -1 +0,0 @@
Subproject commit 8d0c54c1246661d9a51ca0ba455d22116d485eaa
Loading…
Cancel
Save