forked from coinbase/kryptology
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
160 lines (147 loc) · 5.06 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//
// Copyright Coinbase, Inc. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"bufio"
"encoding/hex"
"fmt"
"os"
"github.com/berry-block/kryptology/pkg/accumulator"
"github.com/berry-block/kryptology/pkg/core/curves"
)
func main() {
curve := curves.BLS12381(&curves.PointBls12381G1{})
sk, _ := new(accumulator.SecretKey).New(curve, []byte("1234567890"))
pk, _ := sk.GetPublicKey(curve)
skBytes, _ := sk.MarshalBinary()
pkBytes, _ := pk.MarshalBinary()
fmt.Println("Coinbase generates secret key and public key pair...")
fmt.Printf("Coinbase publishes public key %v\n", hex.EncodeToString(pkBytes))
fmt.Printf("Coinbase retains secret key %v\n", hex.EncodeToString(skBytes))
// Enter initial elements
fmt.Println("Coinbase starts initiating an accumulator")
var userInput []string
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Coinbase enters the elements accumulated in the initial accumulator, press enter to start")
for scanner.Scan() {
fmt.Println("Enter a string or stop")
line := scanner.Text()
if line == "stop" {
break
}
userInput = append(userInput, line+"\n")
}
elements := make([]accumulator.Element, len(userInput))
for i := 0; i < len(elements); i++ {
elements[i] = curve.Scalar.Hash([]byte(userInput[i]))
}
// Coinbase initiates a new accumulator with elements
acc, err := new(accumulator.Accumulator).WithElements(curve, sk, elements)
if err != nil || acc == nil {
panic(err)
}
accBytes, _ := acc.MarshalBinary()
fmt.Printf("Accumulator Initiated! Value is %v\n", hex.EncodeToString(accBytes))
// Initiate a new membership witness
fmt.Println("Coinbase issues a membership witness to a user")
fmt.Println("Coinbase enters the element that a membership witness is associated with")
reader := bufio.NewReader(os.Stdin)
witnessInput, _ := reader.ReadString('\n')
witElement := curve.Scalar.Hash([]byte(witnessInput))
wit, err := new(accumulator.MembershipWitness).New(witElement, acc, sk)
if err != nil {
panic(err)
}
fmt.Printf("Coinbase issued membership witness associated to element %v\n", witnessInput)
// User uses the witness to verify the membership
fmt.Println("The user can use the witness to verify the associated element is accumulated")
fmt.Println("verifying...")
err = wit.Verify(pk, acc)
if err != nil {
panic(err)
}
fmt.Println("membership verification succeeds!")
// Batch Update accumulator and membership witness
fmt.Println("Coinbase could batch update the accumulator")
fmt.Println("That is, Coinbase can add/delete multiple elements together")
var addInput []string
fmt.Println("Enter elements that you want to batch add, press enter the start")
for scanner.Scan() {
fmt.Println("Enter a string or stop")
line := scanner.Text()
if line == "stop" {
break
}
addInput = append(addInput, line+"\n")
}
additions := make([]accumulator.Element, len(addInput))
for i := 0; i < len(additions); i++ {
additions[i] = curve.Scalar.Hash([]byte(addInput[i]))
}
var deleteInput []string
fmt.Println("Enter elements that you want to batch delete, press enter to start")
for scanner.Scan() {
fmt.Println("Enter a string or stop")
line := scanner.Text()
if line == "stop" {
break
}
deleteInput = append(deleteInput, line+"\n")
}
deletions := make([]accumulator.Element, len(deleteInput))
for i := 0; i < len(deletions); i++ {
deletions[i] = curve.Scalar.Hash([]byte(deleteInput[i]))
}
// Batch update accumulator
_, coefficients, err := acc.Update(sk, additions, deletions)
if err != nil {
panic(err)
}
accBytes, _ = acc.MarshalBinary()
fmt.Println("Accumulator batch-update succeeds!")
fmt.Printf("The new accumulator value is %v\n", hex.EncodeToString(accBytes))
// Batch update witness accordingly
fmt.Println("User should batch-update his/her witness accordingly. This can be done by a trusted third party")
fmt.Println("so that the witness is still usable to verify the associated element is accumulated")
_, err = wit.BatchUpdate(additions, deletions, coefficients)
if err != nil {
panic(err)
}
err = wit.Verify(pk, acc)
if err != nil {
panic(err)
}
fmt.Println("Verification succeeds after batch-update")
// Proof ownership of witness
fmt.Println("The user can also generate a zero-knowledge proof proving the ownership of witness")
params, err := new(accumulator.ProofParams).New(curve, pk, []byte("entropy"))
if err != nil {
panic(err)
}
mpc, err := new(accumulator.MembershipProofCommitting).New(wit, acc, params, pk)
if err != nil {
panic(err)
}
challenge := curve.Scalar.Hash(mpc.GetChallengeBytes())
proof := mpc.GenProof(challenge)
finalProof, err := proof.Finalize(acc, params, pk, challenge)
if err != nil {
panic(err)
}
proofBytes, err := proof.MarshalBinary()
if err != nil {
panic(err)
}
fmt.Println("ZK proof successfully generated!")
fmt.Printf("ZK proof value is %v\n", hex.EncodeToString(proofBytes))
fmt.Println("Verifying....")
challenge2 := finalProof.GetChallenge(curve)
if challenge.Cmp(challenge2) == 0 {
fmt.Println("proof verification succeeds!")
} else {
fmt.Println("proof verification fails!")
}
}