Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Disruption Protection overhaul #216

Merged
merged 48 commits into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d08563d
Adding the new disruption detection by a HASH
carlosvillasanchez Oct 21, 2019
1cfbcb7
Fixing bugs and cleaning code
carlosvillasanchez Oct 21, 2019
bdff4ba
Fixing bugs and cleaning code
carlosvillasanchez Oct 21, 2019
7ef8e2e
Client tests for disruption protection changed. All tests Ok.
carlosvillasanchez Oct 21, 2019
f938c73
Lint changes
carlosvillasanchez Oct 22, 2019
e9d74f3
Small changes
carlosvillasanchez Oct 23, 2019
c827a22
Tests passed
carlosvillasanchez Oct 23, 2019
3ddb547
Tests passed
carlosvillasanchez Oct 23, 2019
1d9583d
Disruption bit detected and comunicated to relay. Cleaning needed
carlosvillasanchez Oct 29, 2019
c167567
Disruption blame implemented. NIZK todo
carlosvillasanchez Nov 3, 2019
0bbca61
All test passed
carlosvillasanchez Nov 19, 2019
3ccd8cd
Lint changes
carlosvillasanchez Nov 19, 2019
50fadb5
Refactoring & Adding comments LB->CV
lbarman Nov 20, 2019
d8ebb5e
Linter pass
lbarman Nov 20, 2019
93775a2
Linter pass
lbarman Nov 20, 2019
944e599
CV->LB
carlosvillasanchez Nov 27, 2019
23f16ed
Duplicate function removed
carlosvillasanchez Nov 27, 2019
4f7748d
WIP
lbarman Nov 30, 2019
896619e
Moves Hash of Downstream Message into its own field
lbarman Nov 30, 2019
d22c82f
Some general cleanup
lbarman Nov 30, 2019
e16a9a9
Clean up disruption, add log messages, etc
lbarman Dec 1, 2019
9f7fe1b
Add pause to see a successful check of SECRET_REVEAL message
lbarman Dec 1, 2019
a08cefc
Some placeholders in the Equiv
lbarman Dec 1, 2019
77b37c9
Merge branch 'master' of github.com:dedis/prifi into disruption-test
lbarman Dec 2, 2019
8dc437b
Merge pull request #217 from dedis/disruption-test
lbarman Dec 2, 2019
6ab520c
Linter pass
lbarman Dec 2, 2019
d141253
Fix tests
lbarman Dec 2, 2019
92616e4
Added option of forcing disruption in toml
carlosvillasanchez Dec 4, 2019
0c2e952
Problem in disruption detection solved (CiphertextHistory from slice …
carlosvillasanchez Dec 4, 2019
1c788c9
Changed structure of blaming data (from slice to proper structure)
carlosvillasanchez Dec 4, 2019
346ea86
Removing unnecessary b_echo_last = 2
carlosvillasanchez Dec 4, 2019
af57a2c
General cleaning
carlosvillasanchez Dec 5, 2019
4f4b370
Preparing for tests
carlosvillasanchez Dec 5, 2019
69d7824
Solving bug
carlosvillasanchez Dec 5, 2019
71b9c6c
Removing comment
carlosvillasanchez Dec 9, 2019
543f1e7
Changed equivaction encription from XOR to AES-GCM
carlosvillasanchez Dec 10, 2019
b54a4ed
Checking tests
carlosvillasanchez Dec 11, 2019
680cf2c
Trying to solve OpenClosedSlot+Equivocation bug
carlosvillasanchez Dec 13, 2019
4290baf
NIZK proof with hard-coded keys
carlosvillasanchez Dec 22, 2019
6f7d2c2
Linter pass
lbarman Jan 2, 2020
20e4f9f
Making Govet happy
lbarman Jan 6, 2020
2e8d138
NIZK added as a PoC
carlosvillasanchez Jan 6, 2020
c4a7588
Merge
carlosvillasanchez Jan 6, 2020
86163ac
New disruption detection when equivocation protection is active too
carlosvillasanchez Jan 7, 2020
5b1b8f0
Bugs in the disruption protection fixed
carlosvillasanchez Jan 8, 2020
70e0137
Equivocation blame part 1 done
carlosvillasanchez Jan 8, 2020
46729c8
Big NIZK of blame phase added
carlosvillasanchez Jan 8, 2020
cdbf8ea
Merge branch 'wip' into CarlosVilla
lbarman Jun 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/prifi-integration-window1-oc-equiv-test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ TrusteeSleepTimeBetweenMessages = 100
TrusteeAlwaysSlowDown = true
TrusteeNeverSlowDown = false
OverrideLogLevel = -1
ForceConsoleColor = true
ForceConsoleColor = true
RelayReportingLimit = -1
SocksServerPort = 8080
SocksClientPort = 8090
Expand Down
23 changes: 12 additions & 11 deletions config/prifi.toml
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
PayloadSize = 5000 # CellSizeUp is automatically computed w.r.t to equivocation protection flag
PayloadSize = 40 # CellSizeUp is automatically computed w.r.t to equivocation protection flag
CellSizeDown = 17500
RelayWindowSize = 1
DCNetType = "Simple"
EnforceSameVersionOnNodes = true
OverrideLogLevel = 1
OverrideLogLevel = 3
ForceConsoleColor = true
RelayUseOpenClosedSlots = true
RelayUseOpenClosedSlots = false
RelayUseDummyDataDown = false
RelayReportingLimit = 1000
RelayDataOutputEnabled = true
ClientDataOutputEnabled = true
RelayReportingLimit = 20
RelayDataOutputEnabled = false
ClientDataOutputEnabled = false
UseUDP = false
DoLatencyTests = false
SocksServerPort = 8080
SocksClientPort = 8090
TrusteeIPRegexPattern = "10\\.1\\.0\\.([0-9]+)"
ClientIPRegexPattern = "10\\.0\\.1\\.([0-9]+)"
RelayIPRegexPattern = "10\\.([0-9]+)\\.([0-9]+)\\.254"
ReplayPCAP = true
ReplayPCAP = false
PCAPFolder = "pcap/"
SimulDelayBetweenClients = 0
DisruptionProtectionEnabled = false
DisruptionProtectionEnabled = true
OpenClosedSlotsMinDelayBetweenRequests = 100
TrusteeSleepTimeBetweenMessages = 100
TrusteeAlwaysSlowDown = false
TrusteeNeverSlowDown = false
RelayMaxNumberOfConsecutiveFailedRounds = 3
RelayProcessingLoopSleepTime = 0
RelayRoundTimeOut = 1000
RelayProcessingLoopSleepTime = 2000
RelayRoundTimeOut = 10000
RelayTrusteeCacheLowBound = 10
RelayTrusteeCacheHighBound = 15
EquivocationProtectionEnabled = false
EquivocationProtectionEnabled = true
VerboseIngressEgressServers = false
ForceDisruptionSinceRound3 = true
184 changes: 153 additions & 31 deletions prifi-lib/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/dedis/prifi/prifi-lib/scheduler"
"github.com/dedis/prifi/prifi-lib/utils"
"github.com/dedis/prifi/utils"
"go.dedis.ch/kyber/proof"
"math/rand"
"time"
)
Expand Down Expand Up @@ -66,7 +67,7 @@ func (p *PriFiLibClientInstance) Received_ALL_ALL_PARAMETERS(msg net.ALL_ALL_PAR
dcNetType := msg.StringValueOrElse("DCNetType", "not initialized")
disruptionProtection := msg.BoolValueOrElse("DisruptionProtectionEnabled", false)
equivProtection := msg.BoolValueOrElse("EquivocationProtectionEnabled", false)

ForceDisruptionSinceRound3 := msg.BoolValueOrElse("ForceDisruptionSinceRound3", false)
//sanity checks
if clientID < -1 {
return errors.New("ClientID cannot be negative")
Expand Down Expand Up @@ -101,6 +102,10 @@ func (p *PriFiLibClientInstance) Received_ALL_ALL_PARAMETERS(msg net.ALL_ALL_PAR
p.clientState.MessageHistory = config.CryptoSuite.XOF([]byte("init")) //any non-nil, non-empty, constant array
p.clientState.DisruptionProtectionEnabled = disruptionProtection
p.clientState.EquivocationProtectionEnabled = equivProtection
p.clientState.ForceDisruptionSinceRound3 = ForceDisruptionSinceRound3
p.clientState.MyLastRound = -10
p.clientState.DisruptionWrongBitPosition = -1
p.clientState.AllreadyDisrupted = false

//we know our client number, if needed, parse the pcap for replay
if p.clientState.pcapReplay.Enabled {
Expand Down Expand Up @@ -192,21 +197,24 @@ func (p *PriFiLibClientInstance) Received_REL_CLI_UDP_DOWNSTREAM_DATA(msg net.RE
}

/*
ProcessDownStreamData handles the downstream data. After determining if the data is for us (this is not done yet), we test if it's a
ProcessDownStreamData handles the downstream data. After determining if the data is for us, we test if it's a
latency-test message, test if the resync flag is on (which triggers a re-setup).
When this function ends, it calls SendUpstreamData() which continues the communication loop.
*/
func (p *PriFiLibClientInstance) ProcessDownStreamData(msg net.REL_CLI_DOWNSTREAM_DATA) error {

timing.StartMeasure("round-processing")

/*
* HANDLE THE DOWNSTREAM DATA
*/

//if disruption protection is enabled, perform the checks
if p.clientState.DisruptionProtectionEnabled {
p.handlePossibleDisruption(msg)
}

//if it's just one byte, no data
if len(msg.Data) > 1 {

//pass the data to the VPN/SOCKS5 proxy, if enabled
if p.clientState.DataOutputEnabled {
p.clientState.DataFromDCNet <- msg.Data
Expand Down Expand Up @@ -263,7 +271,7 @@ func (p *PriFiLibClientInstance) ProcessDownStreamData(msg net.REL_CLI_DOWNSTREA

//produce the next upstream cell

upstreamCell := p.clientState.DCNet.EncodeForRound(p.clientState.RoundNo, false, contribution)
upstreamCell, _ := p.clientState.DCNet.EncodeForRound(p.clientState.RoundNo, false, contribution)

//send the data to the relay
toSend := &net.CLI_REL_OPENCLOSED_DATA{
Expand Down Expand Up @@ -353,20 +361,31 @@ func (p *PriFiLibClientInstance) SendUpstreamData(ownerSlotID int) error {

var upstreamCellContent []byte

//if we can send data
slotOwner := false
if ownerSlotID == p.clientState.MySlot {
slotOwner = true
log.Lvl1("SLOT OWNER", p.clientState.RoundNo)
p.clientState.MyLastRound = p.clientState.RoundNo
}

//how much data we can send
actualPayloadSize := p.clientState.PayloadSize
if p.clientState.DisruptionProtectionEnabled {
actualPayloadSize -= 32
// Making room for the b_echo_last flag
actualPayloadSize--
if actualPayloadSize <= 0 {
log.Fatal("Client", p.clientState.ID, "Cannot have disruption protection with less than 32 bytes payload")
log.Fatal("Client", p.clientState.ID, "Cannot have disruption protection with less than 1 bytes payload")
}
}

//if we can send data
slotOwner := false
if ownerSlotID == p.clientState.MySlot {
slotOwner = true
if p.clientState.EquivocationProtectionEnabled && slotOwner {
// Making room for the
actualPayloadSize -= 16
if actualPayloadSize <= 0 {
log.Fatal("Client", p.clientState.ID, "Cannot have equivocation protection with less than 16 bytes payload")
}
}

if slotOwner {

//this data has already been polled out of the DataForDCNet chan, so send it first
Expand Down Expand Up @@ -446,14 +465,94 @@ func (p *PriFiLibClientInstance) SendUpstreamData(ownerSlotID int) error {
}
}

//produce the next upstream cell
var hmac []byte
if p.clientState.DisruptionProtectionEnabled {
hmac = p.computeHmac256(upstreamCellContent)
if p.clientState.DisruptionProtectionEnabled && slotOwner {
// If we are in blame part and checking the previous message
if p.clientState.DisruptionWrongBitPosition != -1 {
// TODO => there should be a NIZK here proving the ownership of the slot

blameRoundID := p.clientState.RoundNo - int32(p.clientState.nClients)*2

pred := proof.Rep("X", "x", "B")
suite := config.CryptoSuite
B := suite.Point().Base()
sval := map[string]kyber.Scalar{"x": p.clientState.ephemeralPrivateKey}
pval := map[string]kyber.Point{"B": B, "X": p.clientState.EphemeralPublicKey}
prover := pred.Prover(suite, sval, pval, nil)
NIZK, _ := proof.HashProve(suite, "DISRUPTION", prover)

//send the data to the relay
toSend := &net.CLI_REL_DISRUPTION_BLAME{
BitPos: p.clientState.DisruptionWrongBitPosition,
RoundID: blameRoundID,
NIZK: NIZK,
Pval: pval,
}

log.Lvl1("Disruption: Attempting to transmit blame for round", blameRoundID, p.clientState.DisruptionWrongBitPosition)

p.messageSender.SendToRelayWithLog(toSend, "(round "+strconv.Itoa(int(p.clientState.RoundNo))+")")

return nil
}
if !p.clientState.EquivocationProtectionEnabled {
// Making and storing hash
var hash [32]byte
if upstreamCellContent == nil {
// If the content is nil, some code will later change it into an empty slice. So the Hash must be from that
payload_to_hash := make([]byte, p.clientState.DCNet.DCNetPayloadSize-1)

// Saving data for possible disruption
p.clientState.LastMessage = payload_to_hash

// Creating hash
hash = sha256.Sum256(payload_to_hash)
} else {
// CARLOS TODO: CHECK IT FITS
upstreamCellContent[3] = byte(p.clientState.ID)
// Saving data for possible disruption
p.clientState.LastMessage = upstreamCellContent
// Creating hash
hash = sha256.Sum256([]byte(upstreamCellContent))
}

p.clientState.HashFromPreviousMessage = hash
}

}
payload := append(hmac, upstreamCellContent...)
upstreamCell := p.clientState.DCNet.EncodeForRound(p.clientState.RoundNo, slotOwner, payload)

// Adding the b_echo_last if the disruption protection is enabled
var slice_b_echo_last []byte
if p.clientState.DisruptionProtectionEnabled && slotOwner {
slice_b_echo_last = make([]byte, 1)
b_echo_last := p.clientState.B_echo_last
slice_b_echo_last[0] = b_echo_last
}
payload := append(slice_b_echo_last, upstreamCellContent...)

upstreamCell, plainPayload := p.clientState.DCNet.EncodeForRound(p.clientState.RoundNo, slotOwner, payload)

if p.clientState.EquivocationProtectionEnabled && p.clientState.DisruptionProtectionEnabled && slotOwner && p.clientState.B_echo_last != 1 {
// Saving data for possible disruption
p.clientState.LastMessage = plainPayload
hash := sha256.Sum256(plainPayload)
p.clientState.HashFromPreviousMessage = hash
log.Lvl1("CARLOS: HASING", plainPayload[:10], "HASH", hash)
}

if p.clientState.ID == 0 && p.clientState.ForceDisruptionSinceRound3 && p.clientState.RoundNo > 3 && !slotOwner {
if p.clientState.AllreadyDisrupted {
if p.clientState.RoundNo != 6 {
p.clientState.AllreadyDisrupted = false
}
} else {
// TESTING DISRUPTION
log.Error("Pre-disruption", upstreamCell)
upstreamCell[len(upstreamCell)-1]++ // only disrupt a 0->1. if there was already a 1, no disruption (this simplifies things)
log.Error("Disrupting! ", upstreamCell)
p.clientState.AllreadyDisrupted = true
}

}
//send the data to the relay
toSend := &net.CLI_REL_UPSTREAM_DATA{
ClientID: p.clientState.ID,
Expand All @@ -466,6 +565,7 @@ func (p *PriFiLibClientInstance) SendUpstreamData(ownerSlotID int) error {
return nil
}

// TODO: Delete
func (p *PriFiLibClientInstance) computeHmac256(message []byte) []byte {
key := []byte("client-secret" + strconv.Itoa(p.clientState.ID))
h := hmac.New(sha256.New, key)
Expand Down Expand Up @@ -528,11 +628,10 @@ As the client should send the first data, we do so; to keep this function simple
"round function", that is Received_REL_CLI_DOWNSTREAM_DATA().
*/
func (p *PriFiLibClientInstance) Received_REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG(msg net.REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG) error {

//verify the signature
neff := new(scheduler.NeffShuffle)
mySlot, err := neff.ClientVerifySigAndRecognizeSlot(p.clientState.ephemeralPrivateKey, p.clientState.TrusteePublicKey, msg.Base, msg.EphPks, msg.GetSignatures())

p.clientState.EphemeralPublicKeys = msg.EphPks
if err != nil {
e := "Client " + strconv.Itoa(p.clientState.ID) + "; Can't recognize our slot ! err is " + err.Error()
log.Error(e)
Expand All @@ -559,22 +658,45 @@ func (p *PriFiLibClientInstance) Received_REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG(
log.Lvl3("Client", p.clientState.ID, "ready to communicate.")

//produce a blank cell (we could embed data, but let's keep the code simple, one wasted message is not much)
data := make([]byte, p.clientState.PayloadSize)
slotOwner := false
if p.clientState.DisruptionProtectionEnabled {
if p.clientState.PayloadSize < 32 {
log.Fatal("Client", p.clientState.ID, "Cannot have disruption protection with less than 32 bytes payload")
}
data2 := make([]byte, p.clientState.PayloadSize-32)
hmac := p.computeHmac256(data2)

data = append(hmac, data2...)
}
if p.clientState.ID == 0 {
slotOwner = true // we need one guy that takes the responsability for this first slot
}
payloadSize := p.clientState.PayloadSize

upstreamCell := p.clientState.DCNet.EncodeForRound(0, slotOwner, data)
if p.clientState.EquivocationProtectionEnabled && slotOwner {
payloadSize -= 16
}
data := make([]byte, payloadSize)
if p.clientState.DisruptionProtectionEnabled {
// Making space for the b_echo_last
data2 := make([]byte, payloadSize-1)

// Saving data for possible disruption
p.clientState.LastMessage = data2

// Creating and storing hash
var hash [32]byte
hash = sha256.Sum256([]byte(data2))
p.clientState.HashFromPreviousMessage = hash

// As is inicialization, b_echo_last is 0
slice_b_echo_last := make([]byte, 1)
p.clientState.B_echo_last = 0
b_echo_last := p.clientState.B_echo_last
slice_b_echo_last[0] = b_echo_last
data = append(slice_b_echo_last, data2...)
}

upstreamCell, plainPayload := p.clientState.DCNet.EncodeForRound(0, slotOwner, data)
if p.clientState.EquivocationProtectionEnabled && p.clientState.DisruptionProtectionEnabled {
// Saving data for possible disruption
p.clientState.LastMessage = plainPayload
hash := sha256.Sum256(plainPayload)
p.clientState.HashFromPreviousMessage = hash
log.Lvl1("CARLOS: HASING", plainPayload[:10], "HASH", hash)
log.Lvl1("CARLOS: UPSTREAM: ", upstreamCell)
}

//send the data to the relay
toSend := &net.CLI_REL_UPSTREAM_DATA{
Expand Down
Loading