├── README.md ├── .gitignore ├── AUTHORS ├── CONTRIBUTORS ├── core └── crypto │ └── vrf │ └── p256 │ ├── unmarshal.go │ ├── p256_test.go │ └── p256.go └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | # Key Transparency 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | *~ 4 | 5 | /keytransparency-server 6 | /keytransparency-sequencer 7 | /keytransparency-client 8 | 9 | infra*.etcd 10 | genfiles/* 11 | .keytransparency-scts.dat 12 | .keystore 13 | travis_secrets.tar.gz 14 | service_key.json 15 | client_secret*.json 16 | 17 | .DS_Store -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of End-To-End authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | 5 | # Names should be added to this file as: 6 | # Name or Organization 7 | # The email address is not required for organizations. 8 | 9 | Antonio Marcedone 10 | Google Inc. 11 | Yahoo! Inc. 12 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # People who have agreed to one of the CLAs and can contribute patches. 2 | # The AUTHORS file lists the copyright holders; this file 3 | # lists people. For example, Google employees are listed here 4 | # but not in AUTHORS, because Google holds the copyright. 5 | # 6 | # https://developers.google.com/open-source/cla/individual 7 | # https://developers.google.com/open-source/cla/corporate 8 | # 9 | # Names should be added to this file as: 10 | # Name 11 | 12 | Antonio Marcedone 13 | Cesar Ghali 14 | Daniel Ziegler 15 | Gary Belvin 16 | Ismail Khoffi 17 | -------------------------------------------------------------------------------- /core/crypto/vrf/p256/unmarshal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package p256 16 | 17 | // This file implements compressed point unmarshaling. Preferably this 18 | // functionality would be in a standard library. Code borrowed from: 19 | // https://go-review.googlesource.com/#/c/1883/2/src/crypto/elliptic/elliptic.go 20 | 21 | import ( 22 | "crypto/elliptic" 23 | "math/big" 24 | ) 25 | 26 | // Unmarshal a compressed point in the form specified in section 4.3.6 of ANSI X9.62. 27 | func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) { 28 | byteLen := (curve.Params().BitSize + 7) >> 3 29 | if (data[0] &^ 1) != 2 { 30 | return // unrecognized point encoding 31 | } 32 | if len(data) != 1+byteLen { 33 | return 34 | } 35 | 36 | // Based on Routine 2.2.4 in NIST Mathematical routines paper 37 | params := curve.Params() 38 | tx := new(big.Int).SetBytes(data[1 : 1+byteLen]) 39 | y2 := y2(params, tx) 40 | sqrt := defaultSqrt 41 | ty := sqrt(y2, params.P) 42 | if ty == nil { 43 | return // "y^2" is not a square: invalid point 44 | } 45 | var y2c big.Int 46 | y2c.Mul(ty, ty).Mod(&y2c, params.P) 47 | if y2c.Cmp(y2) != 0 { 48 | return // sqrt(y2)^2 != y2: invalid point 49 | } 50 | if ty.Bit(0) != uint(data[0]&1) { 51 | ty.Sub(params.P, ty) 52 | } 53 | 54 | x, y = tx, ty // valid point: return it 55 | return 56 | } 57 | 58 | // Use the curve equation to calculate y² given x. 59 | // only applies to curves of the form y² = x³ - 3x + b. 60 | func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int { 61 | 62 | // y² = x³ - 3x + b 63 | x3 := new(big.Int).Mul(x, x) 64 | x3.Mul(x3, x) 65 | 66 | threeX := new(big.Int).Lsh(x, 1) 67 | threeX.Add(threeX, x) 68 | 69 | x3.Sub(x3, threeX) 70 | x3.Add(x3, curve.B) 71 | x3.Mod(x3, curve.P) 72 | return x3 73 | } 74 | 75 | func defaultSqrt(x, p *big.Int) *big.Int { 76 | var r big.Int 77 | if nil == r.ModSqrt(x, p) { 78 | return nil // x is not a square 79 | } 80 | return &r 81 | } 82 | -------------------------------------------------------------------------------- /core/crypto/vrf/p256/p256_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package p256 16 | 17 | import ( 18 | "bytes" 19 | "crypto/rand" 20 | "encoding/hex" 21 | "math" 22 | "testing" 23 | ) 24 | 25 | const ( 26 | // openssl ecparam -name prime256v1 -genkey -out p256-key.pem 27 | privKey = `-----BEGIN EC PRIVATE KEY----- 28 | MHcCAQEEIGbhE2+z8d5lHzb0gmkS78d86gm5gHUtXCpXveFbK3pcoAoGCCqGSM49 29 | AwEHoUQDQgAEUxX42oxJ5voiNfbjoz8UgsGqh1bD1NXK9m8VivPmQSoYUdVFgNav 30 | csFaQhohkiCEthY51Ga6Xa+ggn+eTZtf9Q== 31 | -----END EC PRIVATE KEY-----` 32 | // openssl ec -in p256-key.pem -pubout -out p256-pubkey.pem 33 | pubKey = `-----BEGIN PUBLIC KEY----- 34 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUxX42oxJ5voiNfbjoz8UgsGqh1bD 35 | 1NXK9m8VivPmQSoYUdVFgNavcsFaQhohkiCEthY51Ga6Xa+ggn+eTZtf9Q== 36 | -----END PUBLIC KEY-----` 37 | ) 38 | 39 | func TestH1(t *testing.T) { 40 | for i := 0; i < 10000; i++ { 41 | m := make([]byte, 100) 42 | if _, err := rand.Read(m); err != nil { 43 | t.Fatalf("Failed generating random message: %v", err) 44 | } 45 | x, y := H1(m) 46 | if x == nil { 47 | t.Errorf("H1(%v)=%v, want curve point", m, x) 48 | } 49 | if got := curve.Params().IsOnCurve(x, y); !got { 50 | t.Errorf("H1(%v)=[%v, %v], is not on curve", m, x, y) 51 | } 52 | } 53 | } 54 | 55 | func TestH2(t *testing.T) { 56 | l := 32 57 | for i := 0; i < 10000; i++ { 58 | m := make([]byte, 100) 59 | if _, err := rand.Read(m); err != nil { 60 | t.Fatalf("Failed generating random message: %v", err) 61 | } 62 | x := H2(m) 63 | if got := len(x.Bytes()); got < 1 || got > l { 64 | t.Errorf("len(h2(%v)) = %v, want: 1 <= %v <= %v", m, got, got, l) 65 | } 66 | } 67 | } 68 | 69 | func TestVRF(t *testing.T) { 70 | k, pk := GenerateKey() 71 | 72 | m1 := []byte("data1") 73 | m2 := []byte("data2") 74 | m3 := []byte("data2") 75 | index1, proof1 := k.Evaluate(m1) 76 | index2, proof2 := k.Evaluate(m2) 77 | index3, proof3 := k.Evaluate(m3) 78 | for _, tc := range []struct { 79 | m []byte 80 | index [32]byte 81 | proof []byte 82 | valid bool 83 | }{ 84 | {m1, index1, proof1, true}, 85 | {m2, index2, proof2, true}, 86 | {m3, index3, proof3, true}, 87 | {m3, index3, proof2, true}, 88 | {m3, index3, proof1, false}, 89 | } { 90 | if valid := pk.Verify(tc.m, tc.proof); valid != tc.valid { 91 | t.Errorf("Verify(%s, %x): %v, want %v", tc.m, tc.proof, valid, tc.valid) 92 | } 93 | } 94 | } 95 | 96 | func TestVerify(t *testing.T) { 97 | pk, err := NewVRFVerifierFromPEM([]byte(pubKey)) 98 | if err != nil { 99 | t.Errorf("NewVRFSigner failure: %v", err) 100 | } 101 | 102 | for _, tc := range []struct { 103 | m []byte 104 | index [32]byte 105 | proof []byte 106 | }{ 107 | { 108 | m: []byte("data1"), 109 | index: h2i("6ed5469b409c4ac0e48151d6db6250b28f6776af0f6eb05aaeb3970f3b72e022"), 110 | proof: h2b("ceaccb3cfc61954004948f131de6cd689555b3834480221ab9ef103a40a63f7a9b47fe8155512531bc0acf9b2314837c2fc43d24b4b9d98f13aff09b2a7ae8810423835a97b337a06769a47e05e4c0b68bcd499d35e7cf7606283d74e41d59a4bbc5f4af2da3b83b7c7ab76598aecbf495714815eae51016410e961f6153a6c5ea"), 111 | }, 112 | { 113 | m: []byte("data2"), 114 | index: h2i("ff6743a082fe6ed66dc04e6e11775070ebbe1088b0a378bf97fd84e960c9ed89"), 115 | proof: h2b("0c39c84e152596e81df4281c5459957b893a7fde2492e0358cc1c8ab891c9a00c74f36c349306e039a3c0f1fcc9e9523ee8d8f29398b68e6c02ddb70b3406f9e0447d0f7c330343720da2ae0959cfd2c3bda9083af475203efb07bcb2e18d12b99abf1a10001d355ae3f9a34c53052a70ff3af03024ad3ada1d188949a707376e6"), 116 | }, 117 | { 118 | m: []byte("data2"), 119 | index: h2i("ff6743a082fe6ed66dc04e6e11775070ebbe1088b0a378bf97fd84e960c9ed89"), 120 | proof: h2b("a907df20dcd190c10ab217db1c752ccf12817a221e43e99e6187e3d3848b803b991b7e474c120af45a46698724136a5691c189afdf73ab00033eb491849b44600447d0f7c330343720da2ae0959cfd2c3bda9083af475203efb07bcb2e18d12b99abf1a10001d355ae3f9a34c53052a70ff3af03024ad3ada1d188949a707376e6"), 121 | }, 122 | } { 123 | if !pk.Verify(tc.m, tc.proof) { 124 | t.Errorf("Verify(%s, %x): %v, want %v", tc.m, tc.proof, false, true) 125 | } 126 | } 127 | } 128 | 129 | func TestReadFromOpenSSL(t *testing.T) { 130 | for _, tc := range []struct { 131 | priv string 132 | pub string 133 | }{ 134 | {privKey, pubKey}, 135 | } { 136 | // Private VRF Key 137 | signer, err := NewVRFSignerFromPEM([]byte(tc.priv)) 138 | if err != nil { 139 | t.Errorf("NewVRFSigner failure: %v", err) 140 | } 141 | 142 | // Public VRF key 143 | verifier, err := NewVRFVerifierFromPEM([]byte(tc.pub)) 144 | if err != nil { 145 | t.Errorf("NewVRFSigner failure: %v", err) 146 | } 147 | 148 | // Evaluate and verify. 149 | m := []byte("M") 150 | _, proof := signer.Evaluate(m) 151 | if !verifier.Verify(m, proof) { 152 | t.Errorf("Failed verifying VRF proof") 153 | } 154 | } 155 | } 156 | 157 | func TestRightTruncateProof(t *testing.T) { 158 | k, pk := GenerateKey() 159 | 160 | data := []byte("data") 161 | _, proof := k.Evaluate(data) 162 | proofLen := len(proof) 163 | for i := 0; i < proofLen; i++ { 164 | proof = proof[:len(proof)-1] 165 | if pk.Verify(data, proof) { 166 | t.Errorf("Verify unexpectedly succeeded after truncating %v bytes from the end of proof", i) 167 | } 168 | } 169 | } 170 | 171 | func TestLeftTruncateProof(t *testing.T) { 172 | k, pk := GenerateKey() 173 | 174 | data := []byte("data") 175 | _, proof := k.Evaluate(data) 176 | proofLen := len(proof) 177 | for i := 0; i < proofLen; i++ { 178 | proof = proof[1:] 179 | if pk.Verify(data, proof) { 180 | t.Errorf("Verify unexpectedly succeeded after truncating %v bytes from the beginning of proof", i) 181 | } 182 | } 183 | } 184 | 185 | func TestBitFlip(t *testing.T) { 186 | k, pk := GenerateKey() 187 | 188 | data := []byte("data") 189 | _, proof := k.Evaluate(data) 190 | for i := 0; i < len(proof)*8; i++ { 191 | // Flip bit in position i. 192 | if pk.Verify(data, flipBit(proof, i)) { 193 | t.Errorf("Verify unexpectedly succeeded after flipping bit %v of vrf", i) 194 | } 195 | } 196 | } 197 | 198 | func flipBit(a []byte, pos int) []byte { 199 | index := int(math.Floor(float64(pos) / 8)) 200 | b := byte(a[index]) 201 | b ^= (1 << uint(math.Mod(float64(pos), 8.0))) 202 | 203 | var buf bytes.Buffer 204 | buf.Write(a[:index]) 205 | buf.Write([]byte{b}) 206 | buf.Write(a[index+1:]) 207 | return buf.Bytes() 208 | } 209 | 210 | func TestVectors(t *testing.T) { 211 | k, err := NewVRFSignerFromPEM([]byte(privKey)) 212 | if err != nil { 213 | t.Errorf("NewVRFSigner failure: %v", err) 214 | } 215 | pk, err := NewVRFVerifierFromPEM([]byte(pubKey)) 216 | if err != nil { 217 | t.Errorf("NewVRFSigner failure: %v", err) 218 | } 219 | for _, tc := range []struct { 220 | m []byte 221 | index [32]byte 222 | }{ 223 | { 224 | m: []byte("test"), 225 | index: h2i("1af0a7e3d9a96a71be6257cf4ad1a0ffdec57e9959b2eafc4673a6c31241fc9f"), 226 | }, 227 | { 228 | m: nil, 229 | index: h2i("2ebac3669807f474f4d49891a1d0b2fba8e966f945ac01cbfffb3bb48627e67d"), 230 | }, 231 | } { 232 | index, proof := k.Evaluate(tc.m) 233 | if got, want := index, tc.index; got != want { 234 | t.Errorf("Evaluate(%s).Index: %x, want %x", tc.m, got, want) 235 | } 236 | if !pk.Verify(tc.m, proof) { 237 | t.Errorf("Verify(%s): %v, want %v", tc.m, false, true) 238 | } 239 | } 240 | } 241 | 242 | func h2i(h string) [32]byte { 243 | b, err := hex.DecodeString(h) 244 | if err != nil { 245 | panic("Invalid hex") 246 | } 247 | var i [32]byte 248 | copy(i[:], b) 249 | return i 250 | } 251 | 252 | func h2b(h string) []byte { 253 | b, err := hex.DecodeString(h) 254 | if err != nil { 255 | panic("Invalid hex") 256 | } 257 | return b 258 | } 259 | 260 | func BenchmarkEvaluate(b *testing.B) { 261 | sk, _ := GenerateKey() 262 | alice := []byte("alice") 263 | b.ResetTimer() 264 | for n := 0; n < b.N; n++ { 265 | sk.Evaluate(alice) 266 | } 267 | } 268 | 269 | func BenchmarkVerify(b *testing.B) { 270 | sk, pk := GenerateKey() 271 | alice := []byte("alice") 272 | _, aliceProof := sk.Evaluate(alice) 273 | b.ResetTimer() 274 | for n := 0; n < b.N; n++ { 275 | pk.Verify(alice, aliceProof) 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /core/crypto/vrf/p256/p256.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package p256 implements a verifiable random function using curve p256. 16 | package p256 17 | 18 | // Discrete Log based VRF from Appendix A of CONIKS: 19 | // http://www.jbonneau.com/doc/MBBFF15-coniks.pdf 20 | // based on "Unique Ring Signatures, a Practical Construction" 21 | // http://fc13.ifca.ai/proc/5-1.pdf 22 | 23 | import ( 24 | "bytes" 25 | "crypto" 26 | "crypto/ecdsa" 27 | "crypto/elliptic" 28 | "crypto/hmac" 29 | "crypto/rand" 30 | "crypto/sha256" 31 | "crypto/sha512" 32 | "crypto/x509" 33 | "encoding/binary" 34 | "encoding/pem" 35 | "errors" 36 | "math/big" 37 | ) 38 | 39 | var ( 40 | curve = elliptic.P256() 41 | params = curve.Params() 42 | 43 | // ErrPointNotOnCurve occurs when a public key is not on the curve. 44 | ErrPointNotOnCurve = errors.New("point is not on the P256 curve") 45 | // ErrWrongKeyType occurs when a key is not an ECDSA key. 46 | ErrWrongKeyType = errors.New("not an ECDSA key") 47 | // ErrNoPEMFound occurs when attempting to parse a non PEM data structure. 48 | ErrNoPEMFound = errors.New("no PEM block found") 49 | // ErrInvalidVRF occurs when the VRF does not validate. 50 | ErrInvalidVRF = errors.New("invalid VRF proof") 51 | ) 52 | 53 | // PublicKey holds a public VRF key. 54 | type PublicKey struct { 55 | *ecdsa.PublicKey 56 | } 57 | 58 | // PrivateKey holds a private VRF key. 59 | type PrivateKey struct { 60 | *ecdsa.PrivateKey 61 | } 62 | 63 | // GenerateKey generates a fresh keypair for this VRF 64 | func GenerateKey() (*PrivateKey, *PublicKey) { 65 | key, err := ecdsa.GenerateKey(curve, rand.Reader) 66 | if err != nil { 67 | return nil, nil 68 | } 69 | 70 | return &PrivateKey{key}, &PublicKey{&key.PublicKey} 71 | } 72 | 73 | // H1 hashes m to a curve point 74 | func H1(m []byte) (x, y *big.Int) { 75 | h := sha512.New() 76 | var i uint32 77 | byteLen := (params.BitSize + 7) >> 3 78 | for x == nil && i < 100 { 79 | // TODO: Use a NIST specified DRBG. 80 | h.Reset() 81 | binary.Write(h, binary.BigEndian, i) 82 | h.Write(m) 83 | r := []byte{2} // Set point encoding to "compressed", y=0. 84 | r = h.Sum(r) 85 | x, y = Unmarshal(curve, r[:byteLen+1]) 86 | i++ 87 | } 88 | return 89 | } 90 | 91 | var one = big.NewInt(1) 92 | 93 | // H2 hashes to an integer [1,N-1] 94 | func H2(m []byte) *big.Int { 95 | // NIST SP 800-90A § A.5.1: Simple discard method. 96 | byteLen := (params.BitSize + 7) >> 3 97 | h := sha512.New() 98 | for i := uint32(0); ; i++ { 99 | // TODO: Use a NIST specified DRBG. 100 | h.Reset() 101 | binary.Write(h, binary.BigEndian, i) 102 | h.Write(m) 103 | b := h.Sum(nil) 104 | k := new(big.Int).SetBytes(b[:byteLen]) 105 | if k.Cmp(new(big.Int).Sub(params.N, one)) == -1 { 106 | return k.Add(k, one) 107 | } 108 | } 109 | } 110 | 111 | // Evaluate returns the verifiable unpredictable function evaluated at m 112 | func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) { 113 | nilIndex := [32]byte{} 114 | // Prover chooses r <-- [1,N-1] 115 | r, _, _, err := elliptic.GenerateKey(curve, rand.Reader) 116 | if err != nil { 117 | return nilIndex, nil 118 | } 119 | ri := new(big.Int).SetBytes(r) 120 | 121 | // H = H1(m) 122 | Hx, Hy := H1(m) 123 | 124 | // VRF_k(m) = [k]H 125 | sHx, sHy := params.ScalarMult(Hx, Hy, k.D.Bytes()) 126 | vrf := elliptic.Marshal(curve, sHx, sHy) // 65 bytes. 127 | 128 | // G is the base point 129 | // s = H2(G, H, [k]G, VRF, [r]G, [r]H) 130 | rGx, rGy := params.ScalarBaseMult(r) 131 | rHx, rHy := params.ScalarMult(Hx, Hy, r) 132 | var b bytes.Buffer 133 | b.Write(elliptic.Marshal(curve, params.Gx, params.Gy)) 134 | b.Write(elliptic.Marshal(curve, Hx, Hy)) 135 | b.Write(elliptic.Marshal(curve, k.PublicKey.X, k.PublicKey.Y)) 136 | b.Write(vrf) 137 | b.Write(elliptic.Marshal(curve, rGx, rGy)) 138 | b.Write(elliptic.Marshal(curve, rHx, rHy)) 139 | s := H2(b.Bytes()) 140 | 141 | // t = r−s*k mod N 142 | t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D)) 143 | t.Mod(t, params.N) 144 | 145 | // Index = H(vrf) 146 | index = sha256.Sum256(vrf) 147 | 148 | // Write s, t, and vrf to a proof blob. Also write leading zeros before s and t 149 | // if needed. 150 | var buf bytes.Buffer 151 | buf.Write(make([]byte, 32-len(s.Bytes()))) 152 | buf.Write(s.Bytes()) 153 | buf.Write(make([]byte, 32-len(t.Bytes()))) 154 | buf.Write(t.Bytes()) 155 | buf.Write(vrf) 156 | 157 | return index, buf.Bytes() 158 | } 159 | 160 | // Verify asserts that proof is correct for m. 161 | func (pk *PublicKey) Verify(m, proof []byte) bool { 162 | // verifier checks that s == H2(m, [t]G + [s]([k]G), [t]H1(m) + [s]VRF_k(m)) 163 | if got, want := len(proof), 64+65; got != want { 164 | return false 165 | } 166 | 167 | // Parse proof into s, t, and vrf. 168 | s := proof[0:32] 169 | t := proof[32:64] 170 | vrf := proof[64 : 64+65] 171 | 172 | uHx, uHy := elliptic.Unmarshal(curve, vrf) 173 | if uHx == nil { 174 | return false 175 | } 176 | 177 | // [t]G + [s]([k]G) = [t+ks]G 178 | tGx, tGy := params.ScalarBaseMult(t) 179 | ksGx, ksGy := params.ScalarMult(pk.X, pk.Y, s) 180 | tksGx, tksGy := params.Add(tGx, tGy, ksGx, ksGy) 181 | 182 | // H = H1(m) 183 | // [t]H + [s]VRF = [t+ks]H 184 | Hx, Hy := H1(m) 185 | tHx, tHy := params.ScalarMult(Hx, Hy, t) 186 | sHx, sHy := params.ScalarMult(uHx, uHy, s) 187 | tksHx, tksHy := params.Add(tHx, tHy, sHx, sHy) 188 | 189 | // H2(G, H, [k]G, VRF, [t]G + [s]([k]G), [t]H + [s]VRF) 190 | // = H2(G, H, [k]G, VRF, [t+ks]G, [t+ks]H) 191 | // = H2(G, H, [k]G, VRF, [r]G, [r]H) 192 | var b bytes.Buffer 193 | b.Write(elliptic.Marshal(curve, params.Gx, params.Gy)) 194 | b.Write(elliptic.Marshal(curve, Hx, Hy)) 195 | b.Write(elliptic.Marshal(curve, pk.X, pk.Y)) 196 | b.Write(vrf) 197 | b.Write(elliptic.Marshal(curve, tksGx, tksGy)) 198 | b.Write(elliptic.Marshal(curve, tksHx, tksHy)) 199 | h2 := H2(b.Bytes()) 200 | 201 | // Left pad h2 with zeros if needed. This will ensure that h2 is padded 202 | // the same way s is. 203 | var buf bytes.Buffer 204 | buf.Write(make([]byte, 32-len(h2.Bytes()))) 205 | buf.Write(h2.Bytes()) 206 | 207 | if !hmac.Equal(s, buf.Bytes()) { 208 | return false 209 | } 210 | return true 211 | } 212 | 213 | // NewVRFSigner creates a signer object from a private key. 214 | func NewVRFSigner(key *ecdsa.PrivateKey) (*PrivateKey, error) { 215 | if *(key.Params()) != *curve.Params() { 216 | return nil, ErrPointNotOnCurve 217 | } 218 | if !curve.IsOnCurve(key.X, key.Y) { 219 | return nil, ErrPointNotOnCurve 220 | } 221 | return &PrivateKey{key}, nil 222 | } 223 | 224 | // Public returns the corresponding public key as bytes. 225 | func (k PrivateKey) Public() crypto.PublicKey { 226 | return &k.PublicKey 227 | } 228 | 229 | // NewVRFVerifier creates a verifier object from a public key. 230 | func NewVRFVerifier(pubkey *ecdsa.PublicKey) (*PublicKey, error) { 231 | if *(pubkey.Params()) != *curve.Params() { 232 | return nil, ErrPointNotOnCurve 233 | } 234 | if !curve.IsOnCurve(pubkey.X, pubkey.Y) { 235 | return nil, ErrPointNotOnCurve 236 | } 237 | return &PublicKey{pubkey}, nil 238 | } 239 | 240 | // NewVRFSignerFromPEM creates a vrf private key from a PEM data structure. 241 | func NewVRFSignerFromPEM(b []byte) (*PrivateKey, error) { 242 | p, _ := pem.Decode(b) 243 | if p == nil { 244 | return nil, ErrNoPEMFound 245 | } 246 | return NewVRFSignerFromRawKey(p.Bytes) 247 | } 248 | 249 | // NewVRFSignerFromRawKey returns the private key from a raw private key bytes. 250 | func NewVRFSignerFromRawKey(b []byte) (*PrivateKey, error) { 251 | k, err := x509.ParseECPrivateKey(b) 252 | if err != nil { 253 | return nil, err 254 | } 255 | return NewVRFSigner(k) 256 | } 257 | 258 | // NewVRFVerifierFromPEM creates a vrf public key from a PEM data structure. 259 | func NewVRFVerifierFromPEM(b []byte) (*PublicKey, error) { 260 | p, _ := pem.Decode(b) 261 | if p == nil { 262 | return nil, ErrNoPEMFound 263 | } 264 | return NewVRFVerifierFromRawKey(p.Bytes) 265 | } 266 | 267 | // NewVRFVerifierFromRawKey returns the public key from a raw public key bytes. 268 | func NewVRFVerifierFromRawKey(b []byte) (*PublicKey, error) { 269 | k, err := x509.ParsePKIXPublicKey(b) 270 | if err != nil { 271 | return nil, err 272 | } 273 | pk, ok := k.(*ecdsa.PublicKey) 274 | if !ok { 275 | return nil, ErrWrongKeyType 276 | } 277 | return NewVRFVerifier(pk) 278 | } 279 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------