This repository has been archived by the owner on Jan 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
disruption.go
203 lines (179 loc) · 6.89 KB
/
disruption.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package client
import (
"bytes"
"fmt"
"github.com/dedis/prifi/prifi-lib/config"
"github.com/dedis/prifi/prifi-lib/net"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/proof"
"gopkg.in/dedis/onet.v2/log"
"strconv"
"time"
)
/*
* Received_REL_ALL_DISRUPTION_REVEAL handles REL_ALL_DISRUPTION_REVEAL messages.
* The method calls a function from the DCNet to regenerate the bits from roundID in position BitPos
* The result is sent to the relay.
*/
func (p *PriFiLibClientInstance) Received_REL_ALL_DISRUPTION_REVEAL(msg net.REL_ALL_DISRUPTION_REVEAL) error {
log.Lvl1("Disruption Phase 1: Received de-anonymization query for round", msg.RoundID, "bit pos", msg.BitPos)
bitMap, PRGs := p.clientState.DCNet.GetBitsOfRound(int32(msg.RoundID), int32(msg.BitPos))
var pred_array []proof.Predicate
sval := make(map[string]kyber.Scalar)
pval := make(map[string]kyber.Point)
suite := config.CryptoSuite
B := suite.Point().Base()
pval["B"] = B
for i, prg := range PRGs {
i_string := strconv.Itoa(i)
pred_array = append(pred_array, proof.Rep("T"+i_string, "t"+i_string, "B"))
p_i := suite.Scalar().SetBytes(prg)
P_i := suite.Point().Mul(p_i, B)
sval["t"+i_string] = p_i
pval["T"+i_string] = P_i
}
pred := proof.And(pred_array...)
prover := pred.Prover(suite, sval, pval, nil)
NIZK, _ := proof.HashProve(suite, "DISRUPTION", prover)
//send the data to the relay
toSend := &net.CLI_REL_DISRUPTION_REVEAL{
ClientID: p.clientState.ID,
Bits: bitMap,
NIZK: NIZK,
Pval: pval,
}
if p.clientState.ForceDisruptionSinceRound3 && p.clientState.ID == 0 {
log.Lvl1("Disruption: Malicious client cheating again, old value", bitMap, "(new value right below)")
trusteeToAccuse := 0
if bitMap[trusteeToAccuse] == 0 {
bitMap[trusteeToAccuse] = 1
} else {
bitMap[trusteeToAccuse] = 0
}
}
log.Lvl1("Disruption: Sending previous round to relay (Round: ", msg.RoundID, ", bit position:", msg.BitPos, "), value", bitMap)
p.messageSender.SendToRelayWithLog(toSend, "")
return nil
}
/*
* Received_REL_ALL_REVEAL_SHARED_SECRETS handles REL_ALL_REVEAL_SHARED_SECRETS messages.
* The method gets the shared secret and sends it to the relay.
*/
func (p *PriFiLibClientInstance) Received_REL_ALL_REVEAL_SHARED_SECRETS(msg net.REL_ALL_REVEAL_SHARED_SECRETS) error {
log.Lvl1("Disruption Phase 2: Received a reveal secret message for trustee", msg.EntityID)
// TODO: NIZK
// TODO: check that the relay asks for the correct entity, and not a honest entity. There should be a signature check on the TRU_REL_DISRUPTION_REVEAL the relay received (and forwarded to the client)
secret := p.clientState.sharedSecrets[msg.EntityID]
// as a pseudorandom base point multiplied by our private key.
suite := config.CryptoSuite
X := make([]kyber.Point, 1)
X[0] = p.clientState.PublicKey
B := suite.Point().Base() //BACK
// Generate the proof predicate: an OR branch for each public key.
sec := map[string]kyber.Scalar{"x": p.clientState.privateKey} //BACK
pub := map[string]kyber.Point{"B": B, "BT": p.clientState.TrusteePublicKey[msg.EntityID], "T": p.clientState.sharedSecrets[msg.EntityID]}
preds := make([]proof.Predicate, len(X))
for i := range X {
name := fmt.Sprintf("X[%d]", i) // "X[0]","X[1]",...
pub[name] = X[i] // public point value
// Predicate indicates knowledge of the private key for X[i]
// and correspondence of the key with the linkage tag
preds[i] = proof.And(proof.Rep(name, "x", "B"), proof.Rep("T", "x", "BT"))
}
pred := proof.Or(preds...) // make a big Or predicate
// The prover needs to know which Or branch (mine) is actually true.
choice := make(map[proof.Predicate]int)
choice[pred] = 0
// Generate the signature
M := "SHAREDKEY"
prover := pred.Prover(suite, sec, pub, choice)
NIZK, _ := proof.HashProve(suite, M, prover)
// Verify the signature
verifier := pred.Verifier(suite, pub)
err := proof.HashVerify(suite, M, verifier, NIZK)
if err != nil {
log.Lvl1("signature failed to verify: ", err)
}
log.Lvl1("Linkable Ring Signature verified.")
toSend := &net.CLI_REL_SHARED_SECRET{
ClientID: p.clientState.ID,
TrusteeID: msg.EntityID,
Secret: secret,
NIZK: make([]byte, 0),
Pub: pub,
}
if p.clientState.ForceDisruptionSinceRound3 && p.clientState.ID == 0 {
//this client is hesitant to answer as he will get caught
//CV->LB: How do we handle this in the relay?
time.Sleep(1 * time.Second)
// this is just to let the honest trustee answer and see what happens
}
p.messageSender.SendToRelayWithLog(toSend, "Sent secret to relay")
log.Lvl1("Reveling secret with trustee", msg.EntityID)
return nil
}
func (p *PriFiLibClientInstance) handlePossibleDisruption(msg net.REL_CLI_DOWNSTREAM_DATA) error {
if p.clientState.RoundNo-1 == p.clientState.MyLastRound {
if p.clientState.B_echo_last == 1 {
log.Lvl1("We previously set b_echo_last=1, relay retransmitted message", msg.Data)
// We are in the disruption protection blame protocol
if bytes.Equal(msg.Data, p.clientState.LastMessage) {
p.clientState.B_echo_last = 0
p.clientState.DisruptionWrongBitPosition = -1
log.Error("There was no disruption; the relay is lying about disruption (outside of threat model).")
} else {
log.Lvl1("We previously set b_echo_last=1, comparing messages: (only on log level 3)")
log.Lvl3(msg.Data)
log.Lvl3(p.clientState.LastMessage)
// Get the l-th bit
found := false
log.Lvl1("COMPARING", msg.Data, p.clientState.LastMessage)
for index, b := range msg.Data {
if b != p.clientState.LastMessage[index] {
log.Lvl1("MISMATCH", b, p.clientState.LastMessage[index])
log.Lvl1(index)
//Get the bit
for j := 0; j < 8; j++ {
mask := byte(1 << uint(j))
if (b & mask) != (p.clientState.LastMessage[index] & mask) {
bitPos := index*8 + (7 - j)
if (p.clientState.LastMessage[index] & mask) == 1 {
log.Lvl1("Bit at position", bitPos, "was a 1 toggled to 0, ignoring...")
} else {
// Found bit
p.clientState.DisruptionWrongBitPosition = bitPos
log.Lvl1("Disruptive bit position:", p.clientState.DisruptionWrongBitPosition)
found = true
break
}
}
}
if found {
break
}
}
}
}
} else {
p.clientState.B_echo_last = 0
p.clientState.DisruptionWrongBitPosition = -1
if len(msg.HashOfPreviousUpstreamData) != 32 {
log.Error("The relay did not send the hash back. This should never happen.")
p.clientState.B_echo_last = 1
} else {
// Getting hash sent by relay
hash := msg.HashOfPreviousUpstreamData
// Getting previously calculated hash
previousHash := p.clientState.HashFromPreviousMessage[:]
// Comparing both hashes
if !bytes.Equal(hash, previousHash) {
log.Error("Disruption protection hash comparison failed.", p.clientState.RoundNo)
p.clientState.B_echo_last = 1
} else {
p.clientState.B_echo_last = 0
}
}
}
}
return nil
}